2017-11-06 1 views
1

명성있는 관리자와 전문가를 통합하고 구성을 고수하려고합니다. 하지만 앱이 이상하게 작동합니다. 그것은 모델/레코드를 current_user로 취합니다. NoMethodError 정의되지 않은 메소드`admin? ' nilClass Pundit, Devise Rails

내 정책 파일 :

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=nilmodel=#<AdminUser:0x007f27733f8a80>

에 따라

나는

def index? 
    @record.admin? 
end 

으로 모델 내 정책 파일 CURRENT_USER 교환 그리고 그것은 작동한다! 나는이 이상한 행동을 이해하지 못한다.

답변

1

전문가 policy doccurrent_user 메서드를 호출하여 Policy 클래스의 initialize 메서드의 첫 번째 인수로 보낼 내용을 검색합니다. 당신이 current_admin_user을 사용하여 로그인 한 사용자의 현재 검색 ActiveAdmin을 구성한 경우, 당신은 다음처럼 ApplicationController 클래스의 학자 기본 메소드를 오버라이드 (override) 할 필요가 : 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 

authorize 방법은 자동으로 Post가 일치 PostPolicy 클래스있을 것이라는 점을 추론하고,에, 나눠이 클래스의 인스턴스 현재 사용자와 주어진 레코드. 그런 다음 액션 이름에서이 정책 인스턴스에 대해 update?을 호출해야합니다. 당신은 사용자가 모든 사용자의 목록을보기 전에 권한이 부여되어야 함을 원하는 경우, 귀하의 경우

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

모든를 갖는 :이 경우 authorize이 같은 짓을했을 것이라고 상상할 수 이미 완료 한 것처럼 AdminUserPolicy을 정의 할 수 있습니다. 그런 다음

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

, 당신의 AdminUserControllerindex 행동에 당신은 authorize에 두 번째 인수를 전달할 수 있다면 당신이 액션 이름과 일치하지 않는 검사 할 권한의 이름입니다. 예 :

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

정말 고마워요! 그것은 많은 것들을 지 웁니다. ''@users = Admin.all'''과''@ post = Post.find()''와 같은 질의는 불필요한 처리에 추가 될 것입니다. 유스 케이스는 사용자가 인덱스, 업데이트 등의 메소드와 같은 것입니다.이 메소드를 분별력있는 정책으로 리디렉션 할 수있는 방법이 있습니까? 아니면 current_admin_user를 계속 사용할 수 있습니까? –

+0

알고 기뻐! '특정 정책으로 리디렉션 할 수있는 방법이 있습니까? '라는 질문을 통해 무엇을 의미하는지 자세히 설명해 주시겠습니까? –

+0

"이 사용자가 볼 수 있습니까?"또는 "이 사용자가 편집 할 수 있습니까?" 나는 @post 변수에 관심이 없다. 따라서 질의하는 것은 불필요합니다. 그러나 내가 생략하면 어떤 정책을 체크인 할 지 알 수 없습니다. 그렇다면 어떻게하면 "권한 부여 : 색인"이라고 할 수 있습니까? 어떤 입력없이. –

관련 문제