Any lazy way to do authentication on RoR?
I want to make a simple login, logout, also, different user have different user role. The Restful authentication seems works great, and the cancan is also very sweet for controlling user ability. But the question is how can I let these two works together. I watched the railcast, I was whether how to detect the user ability? Do I need to add a 开发者_高级运维"ability" column in the user table?? Thank u.
http://railscasts.com/episodes/67-restful-authentication
http://railscasts.com/episodes/192-authorization-with-cancan
Look at the CanCan GitHub page: http://github.com/ryanb/cancan
Based on looking at both that and the RailsCast, I notice two things:
- You define Ability as a separate model. There doesn't appear to be any necessary database columns.
- There is no way you are forced to do roles, you are free to do this however you will.
With restful_authentication, just do the normal thing with your User
model.
The most natural way to add CanCan would be to add an extra column to your User
model called role
or ability
or something, then define methods as you see fit. Personally I'd probably do some kind of number system stored in the database, such as "0" for admin, "1" for high-level user, "2" for low-level user, etc.
Here's a few possibilities:
# Returns true if User is an admin
def admin?
self.role == 0
end
And:
# Returns true if User is admin and role?(:admin) is called, etc.
def role?(to_match)
{
0 => :admin,
1 => :super_user,
2 => :user,
3 => :commenter,
}[self.role] == to_match
end
Then in your Ability
initialize
method, you can use some kind of conditionals to set abilities, such as these snippets from the Railscast/readme:
if user.role? :admin
can :manage, :all
elsif user.role? :super_user
...
end
Or:
if user.admin?
can :manage, :all
else
...
end
I wrote a simple solution that works with CanCan too, just add a role_id:integer column to the User model:
# puts this in /lib/
module RolePlay
module PluginMethods
def has_roleplay(roles = {})
@@roles = roles
@@roles_ids = roles.invert
def roles
@@roles
end
def find_by_role(role_name, *args)
find(:all, :conditions => { :role_id => @@roles[role_name]}, *args)
end
define_method 'role?' do |r|
r == @@roles_ids[role_id]
end
define_method :role do
@@roles_ids[role_id]
end
end
end
end
then include this line in config/initializers/roleplay.rb
ActiveRecord::Base.extend RolePlay::PluginMethods
finally use it in your User model:
class User < ActiveRecord::Base
# ...
has_roleplay(:admin => 0, :teacher => 1, :student => 2)
# ...
end
now your model will have 2 new methods:
@user.role?(:admin) # true if user has admin role
@user.role # returns role name for the user
精彩评论