开发者

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:

  1. You define Ability as a separate model. There doesn't appear to be any necessary database columns.
  2. 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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜