rails Pundit策略基于连接表值

时间:2013-11-28 15:46:28

标签: ruby-on-rails-3 pundit

用户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?

不返回方法错误。

1 个答案:

答案 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