[英]Pundit policy_scope error: undefined method `admin?' for nil:NilClass
碰到Pundit不了解的事情,
使用帶有Devise的Rails 4.2.5.1和Pundit 1.1.0進行身份驗證。
我正在嘗試對BlogController#Index操作使用策略范圍。
出現錯誤:
未定義的方法“管理員?” 對於nil:NilClass
活殼顯示:
>> user
=> nil
# ApplicationController
class ApplicationController < ActionController::Base
include Pundit
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
private
def user_not_authorized
flash[:error] = "You are not authorized to perform this action."
redirect_to(request.referrer || root_path)
end
end
# BlogController
# == Schema Information
#
# Table name: blogs
#
# id :integer not null, primary key
# title :string default(""), not null
# body :text default(""), not null
# published :boolean default("false"), not null
# created_at :datetime not null
# updated_at :datetime not null
#
class BlogsController < ApplicationController
before_action :set_blog, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
after_action :verify_authorized, except: [:index, :show]
after_action :verify_policy_scoped, only: [:index]
def index
@blogs = policy_scope(Blog)
authorize @blog
end
def show
end
def new
@blog = Blog.new
authorize @blog
end
def edit
authorize @blog
end
def create
@blog = Blog.new(blog_params)
@blog.user = current_user if user_signed_in?
authorize @blog
if @blog.save
redirect_to @blog, notice: "Blog post created."
else
render :new
end
end
def update
authorize @blog
if @blog.update(blog_params)
redirect_to @blog, notice: "Blog updated."
else
render :edit
end
end
def destroy
authorize @blog
@blog.destroy
redirect_to blogs_url, notice: "Blog post deleted."
end
private
def set_blog
@blog = Blog.friendly.find(params[:id])
end
def blog_params
params.require(:blog).permit(*policy(@blog|| Blog).permitted_attributes)
end
end
# Application Policy
class ApplicationPolicy
attr_reader :user, :record
def initialize(user, record)
@user = user
@record = record
end
def index?
false
end
def show?
scope.where(:id => record.id).exists?
end
def create?
false
end
def new?
create?
end
def update?
false
end
def edit?
update?
end
def destroy?
false
end
def scope
Pundit.policy_scope!(user, record.class)
end
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
scope
end
end
end
# Blog Policy
class BlogPolicy < ApplicationPolicy
class Scope < Scope
def resolve
if user.admin?
scope.all
else
scope.where(published: true)
end
end
end
def new?
user.admin?
end
def index?
true
end
def update?
user.admin?
end
def create?
user.admin?
end
def destroy?
user.admin?
end
def permitted_attributes
if user.admin?
[:title, :body]
end
end
end
在Pundit BlogPolicy范圍中,我創建了:
class Scope < Scope
def resolve
if user.admin?
scope.order('id DESC')
else
scope.where('published: true')
end
end
end
如果我以
admin user
身份登錄,則可以正常運行。
我可以查看所有博客文章。
如果我以標准
user
身份登錄,則可以正常工作。
標准用戶將看到標記為已發布的博客文章。
如果我未在
user is nil
地方登錄,user is nil
收到錯誤消息:
NoMethodError at /blog
undefined method `admin?' for nil:NilClass
我可以添加另一個子句elsif user.nil?
在user.admin?
之前user.admin?
還是一個case when
語句,但我認為如果用戶不是管理員,它應該只顯示else塊中的內容?
# This seems wrong?
class Scope < Scope
def resolve
if user.nil?
scope.where('published: true')
elsif user.admin?
scope.all
else
scope.where('published: true')
end
end
end
任何指針表示贊賞
您可以使用try:
if user.try(:admin?)
# do something
end
http://api.rubyonrails.org/v4.2.5/classes/Object.html#method-i-try
發生這種情況的原因是,當您未登錄時沒有用戶。(可能是user
變量nil
值分配在某個地方,因此您試圖在nil
對象上調用admin?
方法)
如果您使用ruby 2.3.0或更高版本,則最好使用安全導航
if user&.admin?
scope.order('id DESC')
else
scope.where('published: true')
end
如果您使用其他紅寶石版本
if user.try(:admin?)
scope.order(id: :desc)
else
scope.where(published: true)
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.