Cancan it Rolify Ability

时间:2014-02-11 00:41:31

标签: ruby-on-rails activerecord cancan rolify

我的能力档案

if user.has_role? :admin
  can :manage, :all
else
  can :manage, Company, :id => Company.with_role(:operator, user).pluck(:id)
  ...
end

我的公司控制人指数

def index
@companies = Company.with_role(:operator, current_user)

但是当我以操作公司的用户身份登录时,我无法访问该页面。 (即使Company.with_role(:operator,user)在控制台中返回一个关系!)

公司有代码。我不知道如何用cancan写这个:

Company.with_role(:operator, user).map{|o| o.codes}

但是wiki说如果我使用一个块,那么authorize_resource就不会设置实例变量@codes,因为它不知道哪些对象属于用户。所以我不能用:

can :manage, Code =>  do |Code|
    user.has_role? :operator, code.company
end

我正在寻找一种让我的CodesController能够做到的解决方案:

def index
if params[:company_id]
  @keywords = Code.where(:company_id => params[:company_id])
end

以其他方式向用户显示他们拥有operator角色的所有公司的所有代码。

2 个答案:

答案 0 :(得分:0)

怎么样:

can :manage, Company do |company|
    user.has_role? :operator, company
end
can :manage, Code do |code|
    user.has_role? :operator, code.company
end

如果您没有对can定义使用块语法,则可以在CodesController中使用load_and_authorize_resource将索引过滤为仅当前用户可访问的索引。

<强>更新 因为这使用了块语法,CanCan无法使用load_resource确定要加载哪些对象(因为它想使用SQL语法)。如果你可以重写它不使用块语法,那么你会很好。如果必须使用角色类型逻辑,则可以在控制器的索引方法中添加类似于以下内容的代码:

@codes = Code.all.select {|code| can?(:manage, code)}

或者如果你想绕过这种情况下提高效率的能力

@codes = Company.with_role(:operator, @current_user).codes

答案 1 :(得分:0)

def index
    if params[:company_id]
      @codes = Company.with_role(:operator, current_user).where(:id => params[:company_id]).map{|o| o.keywords}.flatten
    else
      @codes = Company.with_role(:operator, current_user).map{|operator| operator.keywords}.flatten
    end
  end