【发布时间】:2019-06-05 00:26:43
【问题描述】:
我只需要使用 CanCanCan 在特定条件下从数据库中获取特定记录。这是我的数据模型。
class User < ApplicationRecord
has_many :regions_users
end
class RegionsUser < ApplicationRecord
belongs_to :region
end
class Region < ApplicationRecord
has_many :regions_users
has_many :sites
end
class Site < ApplicationRecord
belongs_to :region
has_many :offers
end
class Offer < ApplicationRecord
belongs_to :site
end
例如,一个用户被分配到两个区域,这意味着该用户
user.regions_users 返回两个 RegionsUser [RegionsUser1, RegionsUser2] 的数组。 RegionsUser1 属于区域 A,RegionsUser2 属于区域 B,因此如果我以用户身份登录,我就是可以监督属于这些区域的数据的区域用户。现在,我需要显示属于这些区域(区域 A 和区域 B)的优惠。这意味着,用户无法访问属于区域 A 和区域 B 以外的区域的商品,因此访问 /offers/3 应该会引发 Access Denied 错误。
我可以从 RegionsUser 中提取区域:
region_ids = user.regions_users.pluck(:regions_id)
然后是优惠:
Offer.joins(:site).where(sites: { region_id: region_ids })
我读到了关于使用 here 描述的块定义能力的文章
can :update, Project, ["priority < ?", 3] do |project|
project.priority < 3
end
但我想不出任何适合我的情况的解决方案。我会很感激任何想法。
更新
这有点工作,但不是显示访问被拒绝页面,而是引发 404 Page Not Found 错误。
offers_controller.rb
def offer
@offer ||= Offer.accessible_by(current_ability).find(params[:id])
end
ability.rb
if user.region_user?
region_ids = user.regions_users.pluck(:region_id)
can :read, Offer, site: { region_id: region_ids }
end
更新 2
我可以捕捉到ActiveRecord::RecordNotFound 和raise CanCanCan::AccessDenied,但这是一种解决方法。我希望 CanCanCan 处理授权部分。我可以在控制器中提取记录并引发异常,但这与 CanCanCan 并没有真正的关系,是吗?
【问题讨论】: