NoMethodError 未定义方法“管理员?”对于 nil:NilClass 专家,设计 Rails
NoMethodError undefined method `admin?' for nil:NilClass Pundit, Devise Rails
我正在尝试将专家与我的活动管理员集成并设计配置。但该应用程序运行异常。它将 model/record 作为 current_user.
我的政策文件:
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>
我将 current_user 与我的政策文件模型交换为
def index?
@record.admin?
end
而且有效!
我不明白这种奇怪的行为。
专家policy doc says that it calls the current_user
method to retrieve what to send into the first argument of the initialize
method inside the Policy class. If you have configured ActiveAdmin to retrieve the current logged in user by using current_admin_user
, then you have to override the pundit default method in your ApplicationController
class like so: 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
class,并实例化这个class,将当前用户和给定的记录。然后它从操作名称推断出它应该在这个策略实例上调用 update?
。在这种情况下,你可以想象 authorize
会做这样的事情:
unless PostPolicy.new(current_user, @post).update?
raise Pundit::NotAuthorizedError, "not allowed to update? this #{@post.inspect}"
end
有了所有这些,在您的情况下,如果您希望在查看所有用户列表之前对用户进行授权,您可以像已经完成的那样定义 AdminUserPolicy
。然后在你的 AdminUserController
、
的 index
动作中
controller do
def index
@users = AdminUser.all
authorize @users // NOT `authorize current_admin_user`
super
end
end
如果您要检查的权限名称与操作名称不匹配,您可以将第二个参数传递给 authorize
。例如:
def publish
@post = Post.find(params[:id])
authorize @post, :update?
@post.publish!
redirect_to @post
end
我正在尝试将专家与我的活动管理员集成并设计配置。但该应用程序运行异常。它将 model/record 作为 current_user.
我的政策文件:
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>
我将 current_user 与我的政策文件模型交换为
def index?
@record.admin?
end
而且有效! 我不明白这种奇怪的行为。
专家policy doc says that it calls the current_user
method to retrieve what to send into the first argument of the initialize
method inside the Policy class. If you have configured ActiveAdmin to retrieve the current logged in user by using current_admin_user
, then you have to override the pundit default method in your ApplicationController
class like so: 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
class,并实例化这个class,将当前用户和给定的记录。然后它从操作名称推断出它应该在这个策略实例上调用 update?
。在这种情况下,你可以想象 authorize
会做这样的事情:
unless PostPolicy.new(current_user, @post).update?
raise Pundit::NotAuthorizedError, "not allowed to update? this #{@post.inspect}"
end
有了所有这些,在您的情况下,如果您希望在查看所有用户列表之前对用户进行授权,您可以像已经完成的那样定义 AdminUserPolicy
。然后在你的 AdminUserController
、
index
动作中
controller do
def index
@users = AdminUser.all
authorize @users // NOT `authorize current_admin_user`
super
end
end
如果您要检查的权限名称与操作名称不匹配,您可以将第二个参数传递给 authorize
。例如:
def publish
@post = Post.find(params[:id])
authorize @post, :update?
@post.publish!
redirect_to @post
end