Rails: Access to current_user from within a model in Ruby on Rails Rails: Access to current_user from within a model in Ruby on Rails ruby ruby

Rails: Access to current_user from within a model in Ruby on Rails


I'd say your instincts to keep current_user out of the model are correct.

Like Daniel I'm all for skinny controllers and fat models, but there is also a clear division of responsibilities. The purpose of the controller is to manage the incoming request and session. The model should be able to answer the question "Can user x do y to this object?", but it's nonsensical for it to reference the current_user. What if you are in the console? What if it's a cron job running?

In many cases with the right permissions API in the model, this can be handled with one-line before_filters that apply to several actions. However if things are getting more complex you may want to implement a separate layer (possibly in lib/) that encapsulates the more complex authorization logic to prevent your controller from becoming bloated, and prevent your model from becoming too tightly coupled to the web request/response cycle.


Although this question has been answered by many I just wanted to add my two cents in quickly.

Using the #current_user approach on the User model should be implemented with caution due to Thread Safety.

It is fine to use a class/singleton method on User if you remember to use Thread.current as a way or storing and retrieving your values. But it is not as easy as that because you also have to reset Thread.current so the next request does not inherit permissions it shouldn't.

The point I am trying to make is, if you store state in class or singleton variables, remember that you are throwing thread safety out the window.


The Controller should tell the model instance

Working with the database is the model's job. Handling web requests, including knowing the user for the current request, is the controller's job.

Therefore, if a model instance needs to know the current user, a controller should tell it.

def create  @item = Item.new  @item.current_user = current_user # or whatever your controller method is  ...end

This assumes that Item has an attr_accessor for current_user.

(Note - I first posted this answer on another question, but I've just noticed that question is a duplicate of this one.)