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
Related
In laravel I am use to having
Auth::user()->id
which I can reference for setting up data-id's or something in views. I am working in a ruby on rails app and cannot for the life of me find an answer to how to achieve this in rails. I found a lot of answers talking about current_user but I cannot get any data in the view.
To be clear what I am try to set up exactly is
Enroll
Here the "current_user.id" would be that users id. With the code above (and any variation of it I can think of) I am getting nothing, no errors but no data either. Do I really have to set this up in every controller method to access it somehow? Does anyone have a solution to this that they can point me towards?
Thanks so much for any help.
If you're going to access any instance variable in a view, you need to define it first (either in a controller or in the view).
Depending on how you have auth set up, you probably have a current_user method somewhere.
It could be defined in ApplicationController (which has functionality shared by all controllers);
class ApplicationController < ActionController::Base
def current_user
User.find_by id: session["current_user_id"]
# or whatever
end
helper_method :current_user
end
The helper_method line makes it accessible in your views, so you can write <%= current_user.id %>.
You could also write some code so that the #current_user instance variable is available in all your views:
class ApplicationController < ActionController::Base
before_action :define_current_user
def define_current_user
#current_user = current_user # call the 'current_user' method defined elsewhere
end
end
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).
I'm trying to set the current user into a variable to display "Logged in as Joe" on every page. Not really sure where to begin...
Any quick tips? Specifically, what file should something like this go in...
My current user can be defined as (I think): User.find_by_id(session[:user_id])
TY :)
You might want to use something like Authlogic or Devise to handle this rather than rolling your own auth system, especially when you aren't very familiar with the design patterns common in Rails applications.
That said, if you want to do what you're asking in the question, you should probably define a method in your ApplicationController like so:
def current_user
#current_user ||= User.limit(1).where('id = ?', session[:user_id])
end
You inherit from your ApplicationController on all of your regular controllers, so they all have access to the current_user method. Also, you might want access to the method as a helper in your views. Rails takes care of you with that too (also in your ApplicationController):
helper_method :current_user
def current_user ...
Note: If you use the find_by_x methods they will raise an ActiveRecord::RecordNotFound error if nothing is returned. You probably don't want that, but you might want something to prevent non-users from accessing user only resources, and again, Rails has you covered:
class ApplicationController < ActionController::Base
protect_from_forgery
helper_method :current_user
before_filter :require_user
private
def current_user
#current_user ||= User.limit(1).where('id = ?', session[:user_id])
end
def require_user
unless current_user
flash[:notice] = "You must be logged in to access this page"
redirect_to new_session_url
return false
end
end
end
Cheers!
It belongs in your controllers.
All your controllers inheirit from Application Controller for exactly this reason. Create a method in your Application Controller that returns whatever you need and then you can access it in any of your other controllers.
I would like to define a helper method, my_method, that will be available inside BuyersController methods (like index, create, e.t.c.).
I tried to define it in app/helpers/application_helper.rb but it didn't work:
undefined method `my_method' for #<BuyersController:0x26df468>
It should be in some shared place because I want to use it in other controllers also. This is why I tried app/helpers/application_helper.rb.
What is the right place to define it ?
It should be in app/controllers/application_controller.rb
The app/helpers/application_helper.rb is for shared view helpers.
You should include the application helper module in your application controller so that its methods will be available everywhere (all controllers and views) during a request.
class ApplicationController < ActionController::Base
helper ApplicationHelper
…
end
See the API docs for the helper method
Starting from Rails 3 you could also call view_context.my_method inside your controller
Expanding on the accepted answer, if you did want to share a controller method with views, helper_method seems well suited for this. Declaring a helper_method in the controller makes it accessible to the views.
class ApplicationController < ActionController::Base
helper_method :current_user, :logged_in?
def current_user
#current_user ||= User.find_by(id: session[:user])
end
def logged_in?
current_user != nil
end
end
Before rails 4, helpers with the same controller names will be only available in their controllers and views. Starting from rails 4, all helpers are available for all controllers (if you included them) and views. With that said, all helpers will be shared across your views.
Note: if you don't want this behavior for specific controllers, you can use clear_helpers, it will only include the helper with the same controller name.
For more information about using helpers see this
I have an object in ruby on rails for #user which contains username, password, etc
How can I ensure that the values are kept throughout all views?
Thanks
If you set it up as follows:
class ApplicationController < ActionController::Base
before_filter :set_user
protected
def set_user
#user = User.find_by_id(session[:user_id])
end
end
Then in all of controller, since they all inherits from ApplicationController, will have the #user value set.
Note: this will set the #user to nil if the session[:user_id] as not been set for this session.
For more on filters and the :before_filter, check this link out: Module:ActionController::Filters::ClassMethods
I take it you want some sort of user sustem? logged in and tracking all over your system?
AuthenticatedSystem is something that can help you. there is a lot of documentation out their that will tell you exactly how to setup an environment that uses it. I personally use if for several systems I've made.
In your ApplicationController, add your object to the session and create a variable for it. Add a before_filter that calls the method that does that.