代码之家  ›  专栏  ›  技术社区  ›  Jesse Sravya

NoMethodError未定义的方法“admin?”对于nil:Nilclast专家,设计Rails

  •  1
  • Jesse Sravya  · 技术社区  · 7 年前

    我正在尝试将pundit与我的活动管理员集成,并设计配置。但这个应用程序运行起来很奇怪。它接受模型/记录作为当前用户。

    我的策略文件:

    class AdminUserPolicy
      attr_reader :current_user, :model
    
      def initialize(current_user, model)
        Rails.logger.info '--------------- initialize called-------------------'
        Rails.logger.info current_user
        Rails.logger.info model
        @current_user = current_user
        @record = model
      end
    
      def index?
        @current_user.admin?
      end
    end
    

    控制器:

    controller do
        include Pundit
        protect_from_forgery
        rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
        before_action :authenticate_admin_user!
    
        def index
            authorize current_admin_user
            super
        end
    
        private
    
            def user_not_authorized
               flash[:alert]="Access denied"
               redirect_to (request.referrer || admin_root_path)
            end
    end
    

    --------------- initialize called----------------------------------------
    
    #<AdminUser:0x007f27733f8a80>
    Completed 500 Internal Server Error in 364ms (ActiveRecord: 312.8ms)
    
    
    
    NoMethodError (undefined method `admin?' for nil:NilClass):
    
    app/policies/admin_user_policy.rb:13:in `index?'
    app/admin/dashboard.rb:19:in `index'
      Rendering /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout
      Rendering /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_source.html.erb
      Rendered /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_source.html.erb (4.8ms)
      Rendering /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb
      Rendered /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (2.5ms)
      Rendering /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
      Rendered /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (1.1ms)
      Rendered /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout (39.5ms)
    

    奇怪的是,根据日志, current_user=nil model=#<AdminUser:0x007f27733f8a80>

    我将当前_用户与模型策略文件交换为

    def index?
      @record.admin?
    end
    

    这是可行的! 我不理解这种奇怪的行为。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Wasif Hossain    7 年前

    行家 policy doc 说它调用了 current_user 方法检索发送到的第一个参数中的内容 initialize current_admin_user ,则必须在 ApplicationController 类似这样的类: Ref

    class ApplicationController < ActionController::Base
      // ...
      def pundit_user
        current_admin_user // or whatever based on ActiveAdmin initializer config
      end
    end
    

    为了使定义的策略工作,您必须调用 authorize 控制器内的操作与相应策略模型的实例。所以如果你有一个 PostPolicy 你想授权 update 行动,您必须执行以下操作:

    controller do
      def update
        @post = Post.find(params[:id])
        authorize @post // the current user will be automatically sent to the PostPolicy
        super
      end
    end
    

    批准 方法自动推断 Post 将有一个匹配的 后政策 类,并实例化该类,交给当前用户和给定的记录。然后从动作名称推断,它应该调用 update? 关于这项政策。在这种情况下,你可以想象 批准 会这样做:

    unless PostPolicy.new(current_user, @post).update?
      raise Pundit::NotAuthorizedError, "not allowed to update? this #{@post.inspect}"
    end
    

    AdminUserPolicy 就像你已经做的那样。然后在 index 您的行动 AdminUserController

    controller do
      def index
        @users = AdminUser.all
        authorize @users // NOT `authorize current_admin_user`
        super
      end
    end
    

    您可以将第二个参数传递给 批准 如果要检查的权限名称与操作名称不匹配。例如:

    def publish
      @post = Post.find(params[:id])
      authorize @post, :update?
      @post.publish!
      redirect_to @post
    end