Rails/Cancancan:用复杂/作用域查询定义功能



我正在Rails 4中使用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 } } ) }

那么:如果Record's WorkOrder's rvsp_id与当前用户的id匹配,我如何定义所有Records的能力和/或查询?我怀疑这是某种形式的加入,但我是新手,以前从未这样做过。

附言:我想在Record中添加一个created_by列,但我已经通过PaperTrail实现了,我正在使用它进行审计跟踪。但就查询难度而言,Record.versions.first.whodunnitRecord.work_order.rvsp_id大致相同。谢谢你能提供的任何建议!

附言:我使用Postgres,但如果可以避免的话,我宁愿不做任何特定于数据库的SQL。

我开始研究联接,它似乎起作用了!我用下面的类方法替换了上面的范围:

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 

因此,就索引操作而言,似乎需要在两个地方做同样的事情:定义一个获取所需记录的范围,然后定义块中的功能。作用域确保加载所有正确的记录,并且功能块对它们进行授权。看来对我有用!

我知道这太晚了,但你可以遍历CanCanCan中的关联。

can [:read, :update], Record, work_order: { rsvp_id: user.id }

最新更新