【问题标题】:rails3 Pundit policy base on join table value基于连接表值的 rails Pundit 策略
【发布时间】:2013-11-28 15:46:27
【问题描述】:

用户 has_many 构造用户,后者是 has_many 的连接表:通过与 Construct 的关系。出于应用目的,布尔角色定义在连接表中(constructusers.manager、constructusers.operator 等),而 admin 是用户属性。

因此,当需要为操作定义策略时,以下会为“经理”引发无方法错误,而识别出关系 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 以设置该属性。但是,具有该查找条件的 before_filter :set_constructuser_manager 以及 nil 案例处理在声明策略时仍然没有影响

  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?

不返回任何方法错误。

【问题讨论】:

    标签: ruby-on-rails-3 pundit


    【解决方案1】:

    manager? 将是 Constructuser 实例上的方法,而不是关系上的方法。想想你在问什么,“这个constructusers是一个经理吗?” - 这没有道理。计算机怎么知道你在说什么constructuser?

    如果一个用户有_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
    

    【讨论】:

    • 正确。我需要说明 Constructuser.where(['construct_id = ? and user_id = ?', params[:id], current_user]).first question modified
    • 这是在构造策略和构造控制器中吗?
    • 在构造策略和控制器中都是
    • undefined method 'before_action' 但我可以注释掉。在语法上初始化(用户,构造)后,我已经声明了@constructuser ||= Constructuser.where(['construct_id = ? and user_id = ?',construct,user])。使用未定义的方法“经理”仍然失败?打电话时||构造user.manager?而且我正在测试的案例不是零值的记录...
    • before_actionbefore_filter 的 Rails 4 版本。 find_bywhere(...).first 的 Rails 4 版本(技术上是 .take)。如果您只使用where(...),那么您仍然不会收到任何方法错误。最后你需要使用.first
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-30
    相关资源
    最近更新 更多