我现在正在做一个小型Rails项目。我正在使用Pundit来授权控制器的操作和其他东西。现在的工作是使用Pundit进行索引操作,并使用我的控制器中的Pundit的policy_scope
来获取用户可以看到的项目。
用户应该能够通过以下三种方式查看项目:-他是主人-他被邀请了-该项目为公共
我现在已经尝试了几种解决方案,但最终完成了以下操作:
scope :public_or_involved, -> (user) {
joins('LEFT JOIN invitations ON invitations.project_id = projects.id').
where('projects.is_public = TRUE OR projects.owner_id = ? OR invitations.reciever_id = ?', user.id, user.id)
}
这是我在project_policy.rb:中使用以下专家范围的唯一方法
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
scope.public_or_involved(user)
end
end
最后,我的问题是:
有没有一种优雅的方式来做我现在正在做的事情感觉很难看,不像铁轨!
注意,我不认识专家(我更喜欢acl9的简单DSL方法),所以我只是真正为您转换查询,您通常可以让Rails给您一个LEFT JOIN
和includes()
,您可以使用这个小技巧来获得更整洁的OR
:
scope :public_or_involved,
-> (user) { includes(:invitations).where(
where( is_public: true, owner_id: user.id, invitations: { receiver_id: user.id } ).where_values.reduce(&:or)
)}
根据我的经验,您现在拥有的解决方案是最好的。您可以使用Arel、Squeel或MetaWhere之类的东西来Ruby fy SQL字符串,但这些都会增加复杂性。
如果这符合您的要求,我不会太担心让它"更像Rails-y"