简体   繁体   English

ID不为零时允许访问cancan / cancancan

[英]Allowing access cancan / cancancan when id is not nil

I'm trying to give access where an association exists using cancan. 我正在尝试使用cancan授予存在关联的位置。

It needs to work with both object attributes and accessible_by selection (so I can't use a block, unless someone tells me how I get around the error when I do that). 它需要同时处理对象属性和accessible_by选择(因此,我不能使用块,除非有人告诉我如何解决该错误)。

I've come up with a brutal hack. 我想出了一个残酷的办法。

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

What I mean is lead_id is not null... 我的意思是lead_id不为null ...

Is there any way I can do that without creating a 100,000 item array every time? 有什么办法可以做到,而不必每次都创建100,000个项目数组?


Extra info: It's worth noting that these are not the only controls in place on the Recording and Emails models, so it's important that I can add the extra permissions rather than reset and express them negatively. 额外信息:值得注意的是,这些不是Recording and Emails模型上唯一的控件,因此,我可以添加额外的权限,而不是重置并负面地表达它们,这一点很重要。

There are two ways to achieve this: 有两种方法可以实现此目的:

1. A combined hash of abilities 1.综合能力

This is the recommended approach . 这是推荐的方法 Use this, unless you have a good reason not to. 除非有充分的理由,否则请使用此选项。

The idea here is to combine a cannot ability, in conjunction with can : 这里的想法是 cannot能力与can结合在一起:

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

Note that the order is important here, so that the rule overriding is correct. 请注意,这里的顺序很重要 ,因此规则覆盖是正确的。

2. A block of abilities 2.一组能力

By defining the ability with a block , you can form more complicated queries. 通过使用块定义功能 ,您可以形成更复杂的查询。

A simple implementation would be as follows: 一个简单的实现如下:

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

However, in order to combine this ability with others, you must also specify the SQL conditions when fetching records. 但是,为了将此功能与其他功能结合使用,在获取记录时还必须指定SQL条件 This additional SQL controls load_resource actions, such as index : 此额外的SQL控制load_resource操作,例如index

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

In order to keep this logic DRY, you could also consider defining your permissions in a block such as: 为了使此逻辑保持DRY,还可以考虑在一个块中定义权限,例如:

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

I had this need, and here's a solution that is probably much faster. 我有这个需求,这里的解决方案可能要快得多。 You don't have to hit the database with a pluck , and there's no reason to change a range to an array, as checking the range works fine (I'm not sure if this uses a range internally in the library, but ideally it would). 您无需pluck访问数据库,也没有理由将范围更改为数组,因为检查范围可以正常工作(我不确定这是否在库内部使用了范围,但理想情况下是这样将)。

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

I'm using cancancan . 我正在用cancancan

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM