Rails / Cancancan:使用复杂/范围查询定义能力

时间:2016-01-06 17:13:54

标签: ruby-on-rails postgresql cancancan

我正在使用Cancancan在Rails 4中构建应用程序以进行角色授权。我有一个定义的能力适用于个人记录,但不适用于:index action。

我有一个名为' 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's WorkOrder's与当前用户的ID匹配的所有rvsp_id的能力和/或查询?我怀疑它是某种形式的联合,但我是新手,并且以前没有做过。

P.S。我想到只添加一个created_by列到Record,但我已经通过PaperTrail获得了这一点,我将其用于审计跟踪。但就查询的难度而言,Record.versions.first.whodunnitRecord.work_order.rvsp_id大致相同。感谢您提供的任何建议!

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

2 个答案:

答案 0 :(得分: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 

因此,就索引操作而言,似乎需要在两个地方执行相同的操作:定义一个获取所需记录的范围,然后在块中定义该功能。范围确保您加载所有正确的记录,并且能力块授权它们。无论如何似乎对我有用!

答案 1 :(得分:0)

我知道这已经太晚了,但是您可以遍历CanCanCan中的关联。

map(function_to_apply, list_of_inputs) x = map(lambda n: return len(n), object) Top15['population'] = map(lambda n:'{:,}'.format(n),Top15['population']) print(Top15['population'])