undefined method `admin?' for nil:NilClass

Holly picture Holly · Apr 6, 2013 · Viewed 10.5k times · Source

I followed railscast #250 Authentication from Scratch & got everthing wworking fine. Now I'm trying to only display edit & destroy links on my index page to admin user's.

I've set up mu User database with a admin boolean field & tried putting a simple if statement in the view of another model (hikingtrails) to only display certain links to admin users but I get this error when I try it out, undefined method 'admin?' for nil:NilClass

Database Schema

  create_table "users", :force => true do |t|
    t.string   "email"
    t.string   "password_digest"
    t.boolean  "admin"
    t.datetime "created_at",      :null => false
    t.datetime "updated_at",      :null => false
  end

User Model

class User < ActiveRecord::Base
  attr_accessible :email, :password, :password_confirmation#, :admin

  validates :email, :uniqueness => true

  has_secure_password
end

Application Controller

class ApplicationController < ActionController::Base
  protect_from_forgery

  # fetch the currently logged-in user record to see if the user is currently logged in
  # putting this method in ApplicationController so that it’s available in all controllers
  private
  def current_user
    # checks for a User based on the session’s user id that was stored when they logged in, and stores result in an instance variable
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
  end
  # to give access to this method from all the views, the helper_method makes it a helper method
  helper_method :current_user

  # basic authorization, user must be logged in!
  def authorize
    redirect_to login_url, alert: "You must be logged in to perform this action" if current_user.nil?
  end
end

views/hikingtrails/index.html.erb

  <% if current_user.admin? %>
    <%= link_to t('.edit', :default => t("helpers.links.edit")),
              edit_hikingtrail_path(hikingtrail), :class => 'btn btn-mini' %>
    <%= link_to t('.destroy', :default => t("helpers.links.destroy")),
              hikingtrail_path(hikingtrail),
              :method => :delete,
              :data => { :confirm => t('.confirm', :default => t("helpers.links.confirm", :default => 'Are you sure?')) },
              :class => 'btn btn-mini btn-danger' %>
  <% end %>

Answer

Dogbert picture Dogbert · Apr 6, 2013

current_user will be nil if a user is not logged in according to your code. So you need to do this:

<% if current_user && current_user.admin? %>

or using the try method Rails adds to all objects.

<% if current_user.try(:admin?) %>