我正在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
范围是这个怪物:
scope :for_rvsp, -> (rvsp_id) { where( work_order: { rvsp: { id: rvsp_id } } ) }
那么:如何定义所有
Record.for_rvsp
的能力和/或查询,其中Records
Record's
WorkOrder's
与当前用户的id匹配?我怀疑这是某种形式的加入,但我是新来的,以前没有这样做过。另外,我想在
rvsp_id
中添加一个created_by
列,但我已经通过PaperTrail获得了它,我正在使用它进行审计跟踪。但就查询的难度而言,Record
与Record.versions.first.whodunnit
基本相同。谢谢你的建议!P.P.S.我使用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
因此,就索引操作而言,似乎需要在两个地方执行相同的操作:定义获取所需记录的作用域,然后定义块中的功能。作用域确保加载所有正确的记录,并且能力块授权它们。似乎对我有用!
关于ruby-on-rails - Rails/Cancancan:通过复杂/范围内的查询定义功能,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34638814/