2016-01-06 42 views
0

我在使用Cancancan进行角色授权的Rails 4中构建应用程序。我有一个能力定义,适用于单个记录,但不适用:索引操作。Rails/Cancancan:通过复杂/作用域查询来定义能力

我有一个名为'RVSP'的用户角色。 RVSP分配为WorkOrders,RVSP将从中创建Record

class WorkOrder < ActiveRecord::Base 
    has_one :record 
    belongs_to :rvsp, class_name: "User" 
end 

class Record < ActiveRecord::Base 
    belongs_to :work_order 
end 

这里是我的问题:我想RVSP用户能够读取或更新Records其中WorkOrder被分配到该RVSP。这里的能力定义至今:

can [:read, :update], Record, Record.for_rvsp(user.id) do |record| 
    work_order = record.work_order 
    user.id == work_order.rvsp_id 
end 

范围Record.for_rvsp在这个畸形:

scope :for_rvsp, -> (rvsp_id) { where(work_order: { rvsp: { id: rvsp_id } }) } 

所以:我如何定义所有Records的能力和/或查询的Record'sWorkOrder'srvsp_id匹配当前用户的ID?我怀疑这是一种加入,但我是新来的,并没有这样做过。

P.S.我想只是增加一个created_by列到Record,但我已经通过PaperTrail,我正在使用审计跟踪。但就查询的难度而言,Record.versions.first.whodunnitRecord.work_order.rvsp_id大致相同。感谢您提供的任何建议!

P.P.S.我使用Postgres,但我宁愿不做任何数据库特定的SQL,如果我能避免它。

+0

为什么这不起作用? :'can [:read,:update],Record,work_order:{rvsp:{id:user.id}}' –

回答

2

我开始敲打连接,它似乎在工作!我换成上面下面的类方法的适用范围:

def self.for_rvsp(rvsp_id) 
    joins(:work_order).where(work_orders: {rvsp_id: rvsp_id}) 
end 

我也收拾了能力Ability.rb:

can [:read, :update], Record, Record.for_rvsp(user.id) do |record| 
    user.id == record.work_order.rvsp_id 
end 

所以,就指数的行为而言,看来你需要在两个地方做同样的事情:你定义一个范围来获取你需要的记录,然后你在块中定义这个能力。范围确保您加载所有正确的记录,并且能力块授权他们。无论如何,似乎为我工作!