当id不为空时允许访问cancan / cancancan

时间:2016-09-20 09:36:05

标签: ruby-on-rails ruby cancan

我正在尝试使用cancan提供存在关联的访问权限。

它需要同时使用对象属性和accessible_by选择(所以我不能使用块,除非有人告诉我当我这样做时如何解决错误)。

我想出了一个残酷的黑客。

lead.rb
has_many :recordings
has_many :emails

ability.rb

can :manage, Lead
can :manage, Recording, :lead_id => (1..Lead.pluck(:id).max).to_a
can :manage, Email, :lead_id => (1..Lead.pluck(:id).max).to_a

我的意思是lead_id不为空......

如果没有每次创建100,000个项目数组,我有什么方法可以做到这一点吗?

额外信息:值得注意的是,这些并不是录制和电子邮件模型上的唯一控件,因此重要的是我可以添加额外的权限,而不是重置并对其进行负面表达。

2 个答案:

答案 0 :(得分:2)

有两种方法可以实现这一目标:

1。能力的组合哈希

这是recommended approach使用此功能,除非您有充分理由不这样做。

这里的想法是combine cannot能力与can一起使用:

can :manage, Recording
cannot :manage, Recording, lead_id: nil

请注意order is important此处,以便规则覆盖正确。

2。一块能力

defining the ability with a block,您可以形成更复杂的查询。

一个简单的实现如下:

can :manage, Recording do |recording|
  !recording.lead_id.nil?
end

但是,为了将此功能与其他功能相结合,您在获取记录时还必须specify the SQL conditions。此附加SQL控制load_resource操作,例如index

can :manage, Recording, ["lead_id IS NOT NULL"] do |recording|
  !recording.lead_id.nil?
end

为了保持此逻辑DRY,您还可以考虑在块中定义权限,例如:

[Recording, Email].each do |model|
  can :manage, model
  cannot :manage, model, lead_id: nil
end

答案 1 :(得分:0)

我有这个需求,这里的解决方案可能要快得多。您不必使用pluck来访问数据库,并且没有理由将范围更改为数组,因为检查范围可以正常工作(我不确定是否这在库中内部使用了一个范围,但理想情况下它会。)

can :manage, [Recording, Email], :lead_id => (1..(2**31-1))

我正在使用cancancan