Pundit policy_scope错误:undefined方法`admin?为nil:NilClass [英] Pundit policy_scope error: undefined method `admin?' for nil:NilClass

查看:147
本文介绍了Pundit policy_scope错误:undefined方法`admin?为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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆