Car*_*ela 1 ruby ruby-on-rails cancan
我正在尝试使用 cancan 授予存在关联的访问权限。
它需要同时使用对象属性和 access_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
Run Code Online (Sandbox Code Playgroud)
我的意思是lead_id不为空...
有什么方法可以做到这一点,而不必每次都创建 100,000 个项目数组?
额外信息:值得注意的是,这些并不是 Recording 和 Emails 模型中唯一可用的控件,因此重要的是我可以添加额外的权限,而不是重置和否定它们。
有两种方法可以实现这一点:
这是推荐的方法。使用这个,除非你有充分的理由不这样做。
这里的想法是结合一种cannot能力,结合can:
can :manage, Recording
cannot :manage, Recording, lead_id: nil
Run Code Online (Sandbox Code Playgroud)
请注意,这里的顺序很重要,因此覆盖规则是正确的。
通过使用 block 定义能力,您可以形成更复杂的查询。
一个简单的实现如下:
can :manage, Recording do |recording|
!recording.lead_id.nil?
end
Run Code Online (Sandbox Code Playgroud)
但是,为了将这种能力与其他能力结合起来,您还必须在获取记录时指定 SQL 条件。此附加 SQL 控制load_resource操作,例如index:
can :manage, Recording, ["lead_id IS NOT NULL"] do |recording|
!recording.lead_id.nil?
end
Run Code Online (Sandbox Code Playgroud)
为了保持此逻辑 DRY,您还可以考虑在块中定义您的权限,例如:
[Recording, Email].each do |model|
can :manage, model
cannot :manage, model, lead_id: nil
end
Run Code Online (Sandbox Code Playgroud)