用户has_many构造用户,后者是has_many:与Construct的关系的连接表。出于应用程序的目的,布尔角色在连接表(constructusers.manager,constructusers.operator等)中定义,而admin是用户属性。
因此,当定义关于操作的策略时,以下会为'manager'抛出no方法错误,而关系被识别为ActiveRecord :: Relation:0x000001035c4370
def show?
user.admin? or user.constructusers.manager?
end
如果关系(我假设正确的关系)是正确的,为什么没有识别布尔属性?
根据下面的评论,简单的原因是复数。因此过滤需要:
Constructuser.where(['construct_id = ? and user_id = ?', params[:id], current_user]).first
...在控制器中运行并影响视图。尽管如此,对于正确的Pundit处理,需要将其考虑在内...仍然是在前置过滤器中的de application_controller来设置该属性。但是,具有该查找条件的具有nil案例处理的before_filter:set_constructuser_manager在声明策略时仍然没有影响
def show?
set_constructuser_manager?
end
更新:根据以下评论。 Pundit类私有方法
def contractorconstruct
@contructs = Construct.where(['constructusers.user_id = ?', user]).joins(:users).all
@contractorconstruct ||= Contractor.where(['construct_id IN (?)', @contructs]).first
end
和行动规则
|| contractorconstruct?
不返回方法错误。
答案 0 :(得分:1)
manager?
将是Constructuser实例上的方法,而不是关系上的方法。想想你在问什么,“这个建筑用户是经理吗?” - 这没有道理。计算机将如何知道您正在谈论的构造用户?
如果用户has_many构造用户,为了使用manager?
,您需要找到您关注的实例。如果这是在ConstructPolicy中,那么您需要找到将user
链接到您正在授权的构造的特定构造用户,然后检查该构造用户是否为manager?
。
如果您在Construct控制器中,那么您将拥有类似
的内容class ConstructsController
before_action :set_construct
def show
authorize @construct
# ...
end
# ...
end
在您的政策中,user
将是当前用户,record
将是@construct
。
class ConstructPolicy
def show?
user.admin? || constructuser.manage?
end
private
def constructuser
@constructuser ||= Constructuser.find_by(user_id: user, construct_id: record)
end
end