64

I've recently installed Devise on a rails application, and I am wondering if it is possible to get an instance of the currently logged in user in either one of the other models or controllers, and if so, how do I do that?

GSto
  • 41,512
  • 37
  • 133
  • 184

4 Answers4

120

Devise creates convenience methods on the fly that represent your currently logged user.

However you should note that the generated method name includes the class name of your user model. e.g. if your Devise model is called 'User' then the currently logged in user can be accessed with 'current_user', and if your Devise class is 'Admin' then the logged in admin user can be accessed with 'current_admin'.

There are a number of other methods created with similar conventions, for example 'user_signed_in?' or again 'admin_signed_in?', which are really nice.

These methods are available in controllers and views so you might have the following in a view:

<% if user_signed_in? %>
  <div>Signed in as... <%= current_user.email %></div>
<% end %>

Finally, if you are using two or more Devise models in your app (e.g. User and Admin), you can use the 'anybody_signed_in?' convenience method to check if either of those types of user are signed in:

<% if anybody_signed_in? %>
  <h2>Special offers</h2>
  <p>All registered users will receive free monkeys!</p>
<% end %>

Update:

Since Devise version 1.2.0, 'anybody_signed_in?' has been deprecated and replaced by 'signed_in?'

Scott
  • 17,127
  • 5
  • 53
  • 64
  • 1
    Everything Scott says is correct, but also (and this may be new as well) Devise calls `user` and `admin` here "scopes". If you see that word in the documentation, that's what it's referring to. – Peeja Mar 09 '15 at 20:37
  • 1
    But where in the request object is this info? – mehulkar May 10 '15 at 02:07
17

The Devise helper methods are only available at the controller and view layers. They are not available at the model layer (see Controller filters and helpers section of README).

  • Is it possible to get the currently logged in user from within a model?.

It is not possible via the default helper methods that Devise creates for you. However, there are many alternative methods you can use to provide the current_user to a model. The simplest way has already been suggested by Alex Bartlow, and that is to simply pass the current_user via a method to your model.

  • Is it possible to get the currently logged in user from within a controllers?

Yes it is possible. Use current_<modelname>, where <modelname> is the name of the model that has Devise authentication capabilities (i.e., via rails g devise <modelname>). If, for example, your model is User, then you would use current_user. If your model is Elmo, then you would use current_elmo.

John
  • 9,254
  • 12
  • 54
  • 75
1

simple method is:

if @suit.user == current_user

example:

= link_to "Back", root_path, class: "btn btn-default"

  -if @suit.user == current_user

    = link_to "Edit", edit_suit_path, class: "btn btn-default"

    = link_to "Delete", suit_path, method: :delete, data: {confirm: "Are you sure?" }, class: "btn btn-default"
Kick Buttowski
  • 6,709
  • 13
  • 37
  • 58
1

Pass it in as a parameter to the method call :).

One idea is to use Thread.current[:current_user] = @current_user as a before_filter - but if you're using a deployment stack like Thin + EM_Mysql2 + Rack::FiberPool, you'll need to set that to Fiber.current[:current_user].

Those solutions are really just covering up for a lack of good design logic.

  • Personally I consider sticking contextual values onto the thread object to be a "smell". You acknowledge that in the last line, so kudos, but I just want to emphasize that... – jaydel Jun 29 '13 at 18:05