2

I have been following the Railscast #270 found Rails Cast #270 about implementing Authentication in Rails 3.1. What I would like to do is have the ability in my templates to have different links displayed if a user is logged in. It should look something like this.

If user logged in
  Display link to Profile
  Display logout
If user logged out
 Display link to register
 Display link to login

I think I can figure out the link to various places from theRailsTutorial, but I'm stuck on how to tell if a user is signed in or not.

Using the rails tutorial I found this snippet

 <% if signed_in? %>
     <li><%= link_to "Profile", current_user %> sfsdfsdf</li>
 <% end %>

Which doesn't work when I put the following in my sessions helper:

    def signed_in?
      !@current_user.nil?  
end

How would you make this work?

Michael Durrant
  • 93,410
  • 97
  • 333
  • 497
Noah Clark
  • 8,101
  • 14
  • 74
  • 116

2 Answers2

6

Use current_user.

so just

 <% if current_user %>
     <li><%= link_to "Profile", current_user %> sfsdfsdf</li>
 <% end %>

btw in HAML that would be just

 -if current_user
   %li= 
     link_to "Profile", current_user, sfsdfsdf

(the ends get implied - both for the HTML <li> tag (i.e. the </li>) AND for the ruby if statement!)
For anyone not using HAML this should wet your appetite :)

current_user itself uses @current_user and it gets set up in your application controller as in:

  helper_method :current_user

  private

  def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
  end
Michael Durrant
  • 93,410
  • 97
  • 333
  • 497
  • Is @current_user and current_user the same thing? If this were normal ruby they wouldn't be, but does Rails do something magically so @ current_user is defined in application controller and then you access it via current_user in the views? Is this a common rails pattern? – Noah Clark Oct 26 '11 at 14:01
  • 1
    @NoahClark, `@current_user` and `current_user` are not the same thing. One in an instance variable and the other is a method. `@current_user` is set-up inside a method called `current_user` (which is in application_controller.rb). If you changed the name of the method to `def current_foo` then you would use that instead to check `@current_user`. We call the method `current_user` for convenience – stephenmurdoch Oct 26 '11 at 14:45
  • 1
    Oh, okay. That makes perfect sense. Thanks. I still struggle with this idea of methods not having parens on the end. I'll get it figured out though! – Noah Clark Oct 26 '11 at 15:24
1

Sounds like to need to set up the current_user method. Here's how ryan bates does it in railscast 270:

class ApplicationController < ActionController::Base
  protect_from_forgery

  private

  def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
  end

  # don't forget this line too 
  helper_method :current_user
end

Make sure you've got that in application_controller.rb. No need to use if signed_in anymore, although it should still work if you'd prefer to continue with it

stephenmurdoch
  • 34,024
  • 29
  • 114
  • 189
  • 1
    ps - If you are going to define a `signed_in` method, then you should almost certainly think about moving it from your sessions_helper (where it is only available to sessions views) into application_controller.rb where you can make it globally available with the help of `helper_method :signed_in` – stephenmurdoch Oct 26 '11 at 02:05
  • My application controller looks exactly like yours. – Noah Clark Oct 26 '11 at 13:55