Ruby on Rail - undefined method `admin?' for nil:NilClass - ruby-on-rails

I am using gem 'devise' and 'cancancan' for defining roles for user. problem is when I run rails server its says: undefined method 'admin?' for nil:NilClass
ability.rb:
class Ability
include CanCan::Ability
def initialize(user)
if user.admin?
can :manage, :all
else
can :read, :all
end
end
end
User model:
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :projects
def admin?
self.admin
end
end
What could be the problem?

I'm guessing the line from where the error is originating is something like:
if can? :manage, #object
# ...
This is likely causing an error because your user is not logged in.
The method defining the abilities looks like this:
def initialize(user)
if user.admin?
can :manage, :all
else
can :read, :all
end
end
So, if you have no user, the line user.admin? will cause an error because user is nil and nil has no admin? method.
I would do something like this:
def initialize(user)
if user.try(:admin?)
can :manage, :all
else
can :read, :all
end
end
try in Ruby won't throw an error but will return nil if the method doesn't exist.
(I have not tested this and since you're not sharing the error, I'm taking some liberties in the response.)
I'd also like to point out that if the admin attribute on your User model is a boolean, you don't need to define this method—Rails does that automatically for you.
def admin?
self.admin
end

ability
class Ability
include CanCan::Ability
def initialize(user)
if user.has_role? :admin
can :manage, :all
else
can :read, :all
end
end
end

Related

Rails Cancan: Defining Default Role on Signup

I've recently added roles to my rails application with CanCanCan (by enumeration)- but now I want to add a default role on signup. How do I go about doing this? Does it go in the controller or model?
My User model:
class User < ActiveRecord::Base
#Defining different roles
enum role: [:Admin, :User, :Guest]
#Users can only create one scholarship application
has_one :applications
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
My Ability Model - there's just three roles, an administrator which I will create through seeding the database with a user with a role of 1- and then everyone else should be 2 on signup.:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.role = 1
can :manage, :all
elsif user.role = 2
can :manage, Application
can :manage, User
else
can :read, Static_Page
end
end
end
you can add callback to your model
before_create :set_default_role
private
def set_default_role
self.role ||= Role.find_by_name('your_role')
end
devise article
or in your case you can do
before_create :set_default_role
def set_default_role
self.update_attribute(:role,'your_role')
end

rails cancan allow users to edit *only* their data, but view everyones

I have a rails app that uses Devise and cancan. I am wanting to allow only users to edit their own data, but still be able to view everyone elses.
I have:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.role == "member"
their own only
can :read, User
can :manage, User, user_id: user.id
elsif user.role == "guest"
can :read, User
end
I also have:
class User < ActiveRecord::Base
#attr_accessible :name , :email # Include default devise modules. Others available are:
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
ROLES = %w[member guest]
def is?( requested_role )
self.role == requested_role.to_s
end
end
But I can still edit and delete other users comments. When I shouldn't be able to. Why? What am I doing wrong?
Rails 4
Devise 2.5.2
cancan 1.6
Thanks
For giving the permission of user to edit their own data, change
From
can :manage, User, user_id: user.id
To
can :update, User
You're specifying user_id as a column name for your User model:
can :manage, User, user_id: user.id
I'm willing to bet that User has no user_id column -- it only has an id column. What you want is this:
can :manage, User, id: user.id
Double check this by looking at your schema.rb file and making sure that there is (or is not) a user_id column. The actual ID column is called id and is not listed in schema.rb but is actually present in the database table.
Also, be sure that you really want to allow :manage permissions. The :manage symbol is very powerful and allows the user to do anything with the object in question, including deleting it.

how to associate roles from a dropdown box to a user, using rolify

I have been trying to get rolify gem to work FOREVER. I have cancancan and devise as well, i basically have a signup page with email, password, password_confirmation, and a dropdown box selecting role. and when i click sign up it gives me an error to the segment of code creating the DDbox. Can anyone help me get this working ? my ability.rb is this
`class Ability
include CanCan::Ability
def initialize(user)
user ||=User.new
if user.has_role? :admin
can :manage, :all
elsif user.has_role? :regularUser
can :read, Menu
elsif user.has_role? :institution
can :read, Menu
elsif user.has_role? :franchiseOwner
can :read, Menu
end
# Define abilities for the passed in user here. For example:
#
# user ||= User.new # guest user (not logged in)
# if user.admin?
# can :manage, :all
# else
# can :read, :all
# end
#
# The first argument to `can` is the action you are giving the user
# permission to do.
# If you pass :manage it will apply to every action. Other common actions
# here are :read, :create, :update and :destroy.
#
# The second argument is the resource the user can perform the action on.
# If you pass :all it will apply to every resource. Otherwise pass a Ruby
# class of the resource.
#
# The third argument is an optional hash of conditions to further filter the
# objects.
# For example, here the user can only update published articles.
#
# can :update, Article, :published => true
#
# See the wiki for details:
# https://github.com/CanCanCommunity/cancancan/wiki/Defining-Abilities
end
end `
and this the the dropdown box code snippet from my view/devise/registation/new.html.erb..
<%= user_form.select :role, options_from_collection_for_select(Role.all,"Institution","Regular User", "Franchise Owner")%>
this is my User.rb model
`class User < ActiveRecord::Base
rolify :before_add => :before_add_method
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
def before_add_method(role)
end
end`
and my users_controller
`class UserController < ApplicationController
def index
#users = User.all
end
def new
#user = User.new
end
# POST /userss
# POST /users.json
def create
#user = User.new(user_params)
#user.add_role params[:user][:role]
end
private
def user_params
params.require(:user).permit(:email, :password, :password_confirmation, :role)
end
end`
User.new does not save a record and as such will not have an id.
Try saving the user either with user.save or by using User.create instead so it has an id before adding the role. Otherwise the role wont have a user_id to use for it's association.
user = User.create(:email => 'foo#bar.com', :password => 'somestring', :password_confirmation => 'somestring')
user.add_role :rolename

Deployed rails app to Heroku not working

I've created a rails app using Active Admin on Nitrous.io and all is working in that dev environment. I am using Devise/CanCanCan for authentication/authorisation
When I push to heroku, and try and access Active Admin, I get the following error:
Started GET "/admin" for 91.226.23.198 at 2014-09-06 21:15:49 +0000
Processing by Admin::ProductsController#index as HTML
NoMethodError (undefined method `include?' for nil:NilClass):
app/models/user.rb:8:in `role?'
app/models/ability.rb:6:in `initialize'
My user model is like so:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable,
:recoverable, :rememberable, :trackable, :validatable
def role?(r)
role.include? r.to_s
end
end
Ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.role? :administrator
can :manage, :all
elsif user.role? :moderator
can :manage, Product
can :manage, User, :id => user.id
cannot :destroy, User
#can :read, ActiveAdmin::Page, :name => "Dashboard"
can :read, ActiveAdmin::Page, :name => "Contact Us"
can :read, ActiveAdmin::Page, :name => "About x"
can :read, ActiveAdmin::Page, :name => "FAQ"
#can :manage, [Page, Unit, Category, News]
else
can :read, Product
can :manage, User, :id => user.id
cannot :destroy, User
#can :read, ActiveAdmin::Page, :name => "Dashboard"
can :read, ActiveAdmin::Page, :name => "Contact Us"
can :read, ActiveAdmin::Page, :name => "About x"
can :read, ActiveAdmin::Page, :name => "FAQ"
end
end
end
What am I doing wrong?
I've tried rebooting the heroku server multiple times.
Thanks for your help guys.
Cheers!
Ok finally got a solution to this one. The issue was the default user created by Active Admin didn't include a role, so I seeded a user with a role = 'administrator' and was able to login with this user and it all worked.
Thanks for all the help.

How to fix an error with undefined error with cancan and devise in rails?

I am trying to create permissions in my Rails app with Devise and Cancan.
ability.rb:
class Ability
include CanCan::Ability
def initialize(user)
if user.role == 'admin'
can :manage, :all
else
can :read, :all
end
end
end
user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :role
# attr_accessible :title, :body
def role(role)
roles.include? role.to_s
end
end
view
<% if can? :update, review %>
<p><p><i><a href = '/products/<%= #product.id %>/reviews/<%= review.id %>/edit'>Edit</a>
<% end %>
I get an error saying undefined method `role' for nil:NilClass for this line in the view. Any advice on how to fix this?
I've been trying to use https://github.com/ryanb/cancan/wiki/Role-Based-Authorization as a guide
try adding
user ||= User.new # guest user (not logged in)
to see if that fixes your role error.
class Ability
include CanCan::Ability
user ||= User.new # guest user (not logged in)
def initialize(user)
if user.role == 'admin'
can :manage, :all
else
can :read, :all
end
end
end
that way you can rule out user being nil.
Check out this screencast by the creator of the cancan gem. It explains what you are trying to do in depth a little better than the link you are following.

Resources