nnyby
nnyby

Reputation: 4668

Boolean model attributes as automatic methods

I'm working through http://railstutorial.org (currently working on section 10.4.2 - destroying users).

My User model has a boolean admin attribute, and in the Users controller there is some simple code making use of this attribute:

def admin_user
  redirect_to(root_path) unless current_user.admin?
end

The RSpec test:

describe "as a non-signed-in user" do
  it "should deny access" do
    delete :destroy, :id => @user
    response.should redirect_to(signin_path)
  end
end

And the error this test produces:

NoMethodError in 'UsersController DELETE 'destroy' as a non-signed-in user should deny access' undefined method `admin?' for nil:NilClass

What is nil:NilClass? Why am I getting this?

edit: j., this might help:

  def sign_in(user)
    user.remember_me!
    cookies[:remember_token] = { :value => user.remember_token,
                                :expires => 20.years.from_now.utc }
    self.current_user = user
  end

  def current_user=(user)
    @current_user = user
  end

  def current_user
    @current_user ||= user_from_remember_token
  end

Upvotes: 1

Views: 1009

Answers (4)

joanwolk
joanwolk

Reputation: 1105

I had this exact problem, and I found that the underlying problem was that I'd failed to add :destroy to the before_filter :authenticate in app/controllers/users_controller.rb, as below (from listing 10.41:

before_filter :authenticate, :only => [:index, :edit, :update, :destroy]

Upvotes: 0

John Topley
John Topley

Reputation: 115322

Did you complete section 9.3.4 Current User of the tutorial? This creates a current_user variable within the SessionsController via the inclusion of the SessionsHelper module.

Upvotes: 0

MKumar
MKumar

Reputation: 1524

It looks like your current_user object is nil and it should be nil.

As you are not signed in then surely your current _user is nil and then you are trying to get nil.admin? so that's why it give No method error.

Probabily you should rewrite your method something like

def admin_user
  redirect_to(root_path) unless current_user || current_user.admin?
end

Upvotes: 0

Larry K
Larry K

Reputation: 49104

Good news! Your rspec test found a bug!

Your controller method

def admin_user
  redirect_to(root_path) unless current_user.admin?
end

is being called directly or indirectly by your controller's delete action.

And admin_user is being called when current_user is nil. So the admin_user method is failing with the error

undefined method `admin?' for nil:NilClass

fix: depends on how admin_user is being called and used. Is it in a filter?

Could be changed to either of

def admin_user
  redirect_to(root_path) unless current_user && current_user.admin?
end

# or
def admin_user
  redirect_to(root_path) if current_user && !current_user.admin?
end

depending on the situation....

Upvotes: 2

Related Questions