Pundit policy_scope错误:undefined方法`admin?为nil:NilClass [英] Pundit policy_scope error: undefined method `admin?' for nil:NilClass
问题描述
使用Rails 4.2.5.1,Pundit 1.1.0与Devise进行身份验证。
我正在尝试使用BlogController#Index操作的策略范围。
- 如果用户是admin,显示所有帖子(草稿,发布)
- 如果用户是标准的,则显示标记为仅发布的帖子
- 如果没有用户/用户未登录,显示标有发布的帖子
获取错误:
undefined方法`admin?'为nil:NilClass
Live shell显示:
>> user
=> nil
#ApplicationController
class ApplicationController< ActionController :: Base
包括Pundit
rescue_from Pundit :: NotAuthorizedError,具有::user_not_authorized
#通过引发异常来防止CSRF攻击。
#对于API,您可能需要使用:null_session。
protect_from_forgery with::exception
private
def user_not_authorized
flash [:error] =您无权执行此操作。
redirect_to(request.referrer || root_path)
end
end
< hr>
#BlogController
#==模式信息
#
#表名称:博客
#
#id:integer not null,主键
#title:string default(),not null
#body:text default(),not null
#已发布:boolean default(false),not null
#created_at:datetime not null
#updated_at:datetime not null
#
class BlogsController< ApplicationController
before_action:set_blog只有:[:show,:edit,:update,,destroy]
before_action:authenticate_user !,除了:[:index,:show]
after_action:verify_authorized,但:[: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
如果@ blog.save
redirect_to @blog,请注意:创建博客帖子。
else
render:new
end
end
def update
authorize @blog
if @blog .update(blog_params)
redirect_to @blog,注意:博客更新了。
else
render:edit
end
end
def destroy
authorize @blog
@ blog.destroy
redirect_to blogs_url,注意:博客帖子已删除。
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
#应用政策
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?
创建?
end
def update?
false
end
def编辑?
更新?
end
def destroy?
false
end
def scope
Pundit.policy_scope!(user,record.class)
end
class范围
attr_reader:user,:scope
def initialize(user,scope)
@user = user
@scope = scope
end
定义
范围
结束
结束
结束
#博客策略
class BlogPolicy< ApplicationPolicy
class Scope<范围
def解析
如果user.admin?
scope.all
else
scope.where(已发布: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 allowed_attributes
如果user.admin?
[:title,:body]
end
end
end
在Pundit BlogPolicy范围中,我创建了:
类别范围<范围
def解析
如果user.admin?
scope.order('id DESC')
else
scope.where('published:true')
end
end
end
如果我以
管理员用户身份登录
它工作正常。
我可以查看所有的博文。
如果我以标准的
用户身份登录
,它可以正常工作。
标准用户看到标有发布的博文。
如果我没有登录
user is nil
我收到错误:
NoMethodError at / blog
undefined方法`admin?'为nil:NilClass
我可以在 user.admin?
或案例之前添加另一个条款
语句,但我认为如果用户不是管理员,它应该只显示在其他块中是什么? elsif user.nil?
当
#这样看来错了?
class范围<范围
def解决
如果user.nil?
scope.where('published:true')
elsif user.admin?
scope.all
else
scope.where('published:true')
end
end
end
任何非常感谢的指针
你可以使用try:
如果user.try(:admin?)
#做某事
end
http://api.rubyonrails.org/v4.2.5/classes/Object.html#method-i-try
Running into something I don't understand with Pundit,
Using Rails 4.2.5.1, Pundit 1.1.0 with Devise for authentication.
I'm trying to use a policy scope for the BlogController#Index action.
- If user is admin, display all posts (drafts, published)
- If user is standard, display posts marked published only
- If no user / user not logged in, display posts marked published only
Getting an error:
undefined method `admin?' for nil:NilClass
Live shell reveals:
>> 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
In the Pundit BlogPolicy scope I've created:
class Scope < Scope
def resolve
if user.admin?
scope.order('id DESC')
else
scope.where('published: true')
end
end
end
If I log in as an
admin user
it works fine.
I'm able to view all blog posts.
If I log in as a standard
user
it works.
Standard user sees blog posts that are marked published.
If I'm not logged in where
user is nil
I get an error:
NoMethodError at /blog
undefined method `admin?' for nil:NilClass
I can add another clause elsif user.nil?
before user.admin?
or a case when
statement but I thought if the user is not an admin it should just display what is in the else block?
# 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
Any pointers much appreciated
You can use try:
if user.try(:admin?)
# do something
end
http://api.rubyonrails.org/v4.2.5/classes/Object.html#method-i-try
这篇关于Pundit policy_scope错误:undefined方法`admin?为nil:NilClass的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!