Rails:使用CanCan根据单个模型的实例定义多个角色?

我目前仍然坚持如何根据我们想要的每个条件来分离CanCan的角色。 在我们的应用程序中,有许多类别(如数学,英语,历史等),每个类别都有很多课程。

每个用户可以在每个类别上拥有许多不同的角色。 例如,John可以成为数学的“读者”,这意味着他可以阅读所有数学课程。 约翰也可以成为英语的“作家”,这意味着他可以阅读所有英语课程,创建英语类别的课程,只编辑/删除他在英语中创建的课程。

如果这些是John所拥有的唯一角色,他将无法在导航栏中看到类别历史记录,并且将无法访问历史记录中的课程。

这些是建立关系的方式:

class User < ActiveRecord::Base has_many :roles def has_role?(role_sym) roles.any? { |r| r.level.underscore.to_sym == role_sym } end end class Category < ActiveRecord::Base has_many :roles has_many :courses end class Role < ActiveRecord::Base belongs_to :user belongs_to :category attr_accessible :level, :category_id, :user_id end 

在model / ability.rb中我们有

 class Ability include CanCan::Ability def initialize(user) user ||= User.new # guest user (not logged in) #guest if user.has_role? :reader reader(user) end if user.has_role? :writer writer(user) end end #BE ABLE TO SEE COURSES AND CATS FOR PERMITTED CATS. def reader(user) can :read, Category, :roles => { :user_id => user.id, :level => "reader" } ## how would we be able to limit reading of courses that are within permitted categories? something like category.courses ~~ end def writer(user) reader(user) #inheriting from reader? this doesnt work because level is hardcoded into reader can :read, Category, :roles => { :user_id => user.id, :level => "writer"} # 1.you can read all courses in category that you are given permission to # 2.you can write courses in permitted category # 3.you can edit, delete courses that only youve created within permitted category end end 

问题:

  1. 我们如何以正确的方式区分“读者”和“作家”的角色? 我们如何访问我们可以访问的类别中的课程?

  2. 在ability.rb中定义reader和writer方法之后,我们如何在视图页面中使用它们? 看起来当前的文档使用类似“”但不使用我们分离和定义的方法。

ps我们将有7个不同的角色:访客,读者,作家,编辑,经理,管理员和app_admin(我们的开发人员)

我一直试图解决这个问题3天了 – 请理解我还是个初学者! 提前致谢

我今天遇到了同样的需求,并在CanCan Wiki上找到了一种方法。

简单地按照以下简单步骤:

1)使用您的角色名称在User类下创建一个常量:

 class User < ActiveRecord::Base ROLES = %w[admin moderator author banned] end 

2a)如果您使用的是ActiveRecord,请创建并运行迁移:

 rails generate migration add_roles_mask_to_users roles_mask:integer rake db:migrate 

2b)如果您使用的是Mongoid,请在User模型上添加这些字段:

 field :roles_mask, type: Integer 

3)接下来,您需要将以下代码添加到User模型:

 # in models/user.rb def roles=(roles) self.roles_mask = (roles & ROLES).map { |r| 2**ROLES.index(r) }.inject(0, :+) end def roles ROLES.reject do |r| ((roles_mask.to_i || 0) & 2**ROLES.index(r)).zero? end end 

4)如果您使用没有强参数的设计,请不要忘记将attr_accessible:roles添加到您的用户模型。 如果您使用带有strong_parameters的设计,无论是作为Rails 3应用程序中的gem,还是Rails 4中内置的,都不要忘记将角色添加到控制器中的允许列表中:

 class ApplicationController < ActionController::Base before_filter :configure_permitted_parameters, if: :devise_controller? protected def configure_permitted_parameters devise_parameter_sanitizer.for(:sign_up) {|u| u.permit(:email, :password, :password_confirmation, roles: [])} end end 

5)在视图中添加以下代码以生成用于设置这些角色的复选框:

 <% for role in User::ROLES %> <%= check_box_tag "user[roles][#{role}]", role, @user.roles.include?(role), {:name => "user[roles][]"}%> <%= label_tag "user_roles_#{role}", role.humanize %>
<% end %> <%= hidden_field_tag "user[roles][]", "" %>

6)最后,您可以添加一种方便的方法来检查用户在Ability类中的角色:

 # in models/user.rb def is?(role) roles.include?(role.to_s) end # in models/ability.rb can :manage, :all if user.is? :admin 

而已。

我希望这可以提供帮助。

在你的gemfile Include中。

  1. gem“康康”

  2. 安装捆绑。

  3. rails g cancan:能力

这将在模型中生成一个能力等级。

在下面定义你的能力。

但请记住,您已经定义了角色,

比如你有一个用户模型,

有两个角色定义,即管理和支持。

  class Ability include CanCan::Ability def initialize(user) user||= User.new can :read, :all if user.role == 'admin' can :manage, :all else can :read, :all end end end 

4.要限制用户的资源,请在其控制器中使用以下filter。

  load_and_authorize_resource 

5.如果你想限制视图中的某些东西不显示。

  <% if can? :manage, @flower %> <%= link_to 'Edit', edit_flower_path(flower) %> <% end %> <% if can? :manage, @flower %> <%= link_to 'Destroy', flower_path(flower), method: :delete, data: { confirm: 'Are you sure?' } %> <% end %>