Alias/Override helpers loaded using ActiveSupport.on_load - ruby-on-rails

Devise provide several helper methods such as current_user. It uses ActiveSupport's on_load to lazily load these helpers into the controllers.
However this means that when I first starts Rails, my attempt to alias these helper methods will not work correctly. For example:
# in my ApplicationController
alias_method :devise_current_user, :current_user
def current_user
user = devise_current_user
if !user && !devise_controller?
foo
end
return user
end
This would cause "method not found error" when Rails is first initialized. I can start Rails first, then add these code, then it would work (correctly aliasing and overriding the method).
How to properly do my aliasing/overriding for these on_load helpers?

Related

Devise methods in helper file?

I have a helper module ModelHelper. I want to use user_signed_in? method inside that helper module. But it shows error. How can I call this method inside helper file.
Method user_signed_in? defined in the Devise::Controllers::Helpers::ClassModule module. Long story short it just checks if scope authenticated in warden. So you can try to check it without Devise helpers
def #{mapping}_signed_in?
!!current_#{mapping}
end
def current_#{mapping}
#current_#{mapping} ||= warden.authenticate(scope: :#{mapping})
end
I think that you can use current_user.present?
Anyway, rails helpers are very ugly and I advise to don't use it at all

Ruby on Rails: Common method available for controllers and views?

I have been working with Ruby on Rails for a short time. Recently I implemented an authentication system for my application. I made a method available on 'application_helper.rb' to retrieve the current logged user (method called current_user).
The method just retrieves my User object if the session[:user_id] variable is present.
However I face the following problem.
If I place the current_user method in 'application_helper.rb', my controllers can't make use of it
If I place the current_user method in 'application_controller.rb', my views can't make use of it
What's the best approach to solve this problem? The easy way would be duplicate my code in both controller and helper, but I know there is a better and more correct way.
Thanks in advance
This is a common and well-solved problem.
Rails doesn't allow controllers to access helper methods. If you want to share a method between your views and controllers, you need to define the method in your controller, and then make it available to your views with helper_method:
class ApplicationController < ActionController::Bbase
# Let views access current_user
helper_method :current_user
def current_user
# ...
end
end
You can pass more than one method name to helper_method to make additional methods in your controller available to your views:
helper_method :current_user, :logged_in?
def current_user
# ...
end
def logged_in?
!current_user.nil?
end

Rails 3 helper methods not available in controllers even after explicitly including them

Fist of all I'm newbie to rails.
I have this in SessionsController:
def method
sign_in 'user'
end
And this in SessionsHelper:
def sing_in(user)
......
end
So Googling and reading some answers on stackoverflow let me to try something like this:
Including the 'SessionsHelper' to the SessionsController and even tried to put it in 'ApplicationController' like this:
class ApplicationController < ActionController::Base
protect_from_forgery
include SessionsHelper
def handle_unverified_requests
sign_out
super
end
end
But I'm getting
NoMethodError : undefined method `sign_in' for SessionsController:0x007eff2004fcd8
Also few questions:
1) What's the point/difference in putting few methods in Heplers and few in Controllers? Is it a security issue or what?
2) I also tried puting the sign_in method in the SessionsController as i read in stackoverflow that methods defined in controllers can be accessed in views. so to avoid any problems in the views I used
helper_method
but still the same NoMethodError
3) THe best and easy way to access the helper methods in controllers?
So where am I going wrong.
I'm using Rails 3.2.11 and Ruby 2.0.0p0
Looks like a typo: your helper method is 'sing_in' instead of 'sign_in'.

How to call helper method from model?

I use MongoDB as a database in my Rails application with MongoID gem. I want to call the helper method from the model within after_create callback method. How is it possible?My model code is:
class Department
include ApplicationHelper
after_create :create_news
private
def create_news
#user = ApplicationHelper.get_current_users
end
end
And my helper code is:
module ApplicationHelper
def get_current_users
current_user
end
end
When I create new department then following error occur.
undefined method `get_current_users' for ApplicationHelper:Module
How to remove error? Thanks in advance.
I also use mongoid and use this all the time. Shouldn't be unique to mongoid though.
ApplicationController.helpers.my_helper_method
If you want a helper method that you can use in your views to return the current user, you can do so in your ApplicationController, something like this for example:
private
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
helper_method :current_user
Then you can use this in any view.
If you want some arbitrary method in a model to know what user it's dealing with, pass #current_user in as an argument to the method when you call it in your controller.
Your code seems incomplete so I can't really see what you're trying to accomplish, but this is pretty standard practice.
Make sure the module file is named properly, meaning in your case application_helper.rb and it's located on the helpers library.
You can also try to include the helper in the ApplicationController (app/controller/application_controller.rb).

Rails: controller method or instance variable inside a helper

I'm using the bitly gem and would like to have access to the bitly API inside my helper methods (which get called by views and mailers to generate URLs).
I initiate an API connection in this method in my ApplicationController:
(is there a more appropriate place to do this BTW?)
class ApplicationController < ActionController::Base
before_filter :bitly_connect
def bitly_connect
Bitly.use_api_version_3
#bitly ||= Bitly.new(APP_CONFIG['bitly_username'], APP_CONFIG['bitly_api_key'] )
end
end
By default I don't have access to #bitly in my helpers. Can you suggest a way to accomplish that?
The only related thread I found wasn't helpful:
Rails 3 and Controller Instance Variables Inside a Helper
Thanks.
Rails by convention passes instance variables set in the controller actions (and filters) along to the views. The helper methods are available in these views, and should have access to the instance variables you set inside your controller action.
Alternately, you can set a local variable inside your helper method by passing the variable to the method, or by using the Object#instance_variable_get method: http://ruby-doc.org/core/classes/Object.html#M001028
# app/controllers/example_controller.rb
class ExampleController
def index
#instance_variable = 'foo'
end
end
# app/helpers/example_helper.rb
module ExampleHelper
def foo
# instance variables set in the controller actions can be accessed here
#instance_variable # => 'foo'
# alternately using instance_variable_get
variable = instance_variable_get(:#instance_variable)
variable # => 'foo'
end
end
As for your concerns with the placement of the logic, it does not look like it belongs in the controller. Think of the controller as routing requests for your application. Most logic should be performed inside of your model classes. "Skinny controller, fat model.": http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model
If you need a controller method to be accessible as a helper, you can use helper_method
class ApplicationController < ActionController::Base
helper_method :bitly_connect
def bitly_connect
#bitly ||= begin
Bitly.use_api_version_3
Bitly.new(APP_CONFIG['bitly_username'], APP_CONFIG['bitly_api_key'] )
end
end
end
Note that I also altered the method, so that it doesn't call Bitly.use_api_version_3 each time it is called.
As Ben Simpson noted, you should probably move this into a Model though.

Resources