我正在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的能力和/或查询,其中RecordsRecord'sWorkOrder's与当前用户的id匹配?我怀疑这是某种形式的加入,但我是新来的,以前没有这样做过。
另外,我想在rvsp_id中添加一个created_by列,但我已经通过PaperTrail获得了它,我正在使用它进行审计跟踪。但就查询的难度而言,RecordRecord.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/

10-11 01:55