【问题标题】:Allowing access cancan / cancancan when id is not nil当 id 不为 nil 时允许访问 cancan / cancancan
【发布时间】:2016-09-20 09:36:04
【问题描述】:

我正在尝试使用 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 个项目的数组?


额外信息:值得注意的是,这些并不是录音和电子邮件模型中唯一的控件,因此我可以添加额外的权限而不是重置和否定地表达它们,这一点很重要。

【问题讨论】:

  • 生成数组的复杂方法有什么意义?为什么不只是lead_id: Lead.ids

标签: ruby-on-rails ruby cancan


【解决方案1】:

有两种方法可以实现:

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

【讨论】:

  • 是的,这很好,除了还有其他更复杂的事情发生。只有当您愿意清除所有其他权限时,这种方法才有效。澄清一下,在其他情况下,我根据 id 指定权限,如果我尝试将其反转为否定表达,我需要这样做以匹配上述内容,我最终会遇到完全相同的问题...
  • 而且我不能用块定义它,如上所述,因为它只支持对象属性,不适用于accessible_by,例如在索引操作上,这是我主要需要它的地方。
  • “这种方法只有在你愿意清除所有其他权限的情况下才有效”——是的,不幸的是,这是CanCan 的主要问题/批评之一- 这就是为什么许多开发人员现在更喜欢使用替代方法,例如pundit
  • 如果您的许可仅适用于 some lead_ids,那么据我所知,“定义具有 1000 个 ID 的列表”的问题是不可避免的 - 除非有是您可以查询的模型的其他一些属性,而不是 id。不过,您至少可以缓存ids 的列表以提高性能。
  • 嗨,汤姆,在这种情况下,任何 id 都可以。我只想限制 nil 值。
【解决方案2】:

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

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

我正在使用cancancan

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-28
    • 2020-05-03
    • 1970-01-01
    • 2019-07-09
    • 2012-10-05
    相关资源
    最近更新 更多