Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 如何用权威解决命名错误_Ruby On Rails_Ruby_Pundit - Fatal编程技术网

Ruby on rails 如何用权威解决命名错误

Ruby on rails 如何用权威解决命名错误,ruby-on-rails,ruby,pundit,Ruby On Rails,Ruby,Pundit,我不知道我是不是做错了什么,但看起来好像是 我使用Pundit进行授权,现在我已经用它建立了一些模型 我有一个类别模型,只能由管理员创建。此外,我也不希望用户看到显示/编辑/销毁视图。我只希望管理员可以访问它。到目前为止还不错 将在下面添加一些代码: 类别_policy.rb class CategoryPolicy < ApplicationPolicy def index? user.admin? end def create? user.admin?

我不知道我是不是做错了什么,但看起来好像是

我使用Pundit进行授权,现在我已经用它建立了一些模型

我有一个类别模型,只能由管理员创建。此外,我也不希望用户看到显示/编辑/销毁视图。我只希望管理员可以访问它。到目前为止还不错

将在下面添加一些代码:

类别_policy.rb

class CategoryPolicy < ApplicationPolicy
  def index?
    user.admin?
  end

  def create?
    user.admin?
  end

  def show?
    user.admin?
  end

  def new?
    user.admin?
  end

  def update?
    return true if user.admin?
  end

  def destroy?
    return true if user.admin?
  end
end
class ApplicationPolicy
  attr_reader :user, :record

  def initialize(user, record)
    @user = user
    @record = record
  end

  def index?
    false
  end

  def create?
    create?
  end

  def new?
    create?
  end

  def update?
    false
  end

  def edit?
    update?
  end

  def destroy?
    false
  end

  class Scope
    attr_reader :user, :scope

    def initialize(user, scope)
      @user = user
      @scope = scope
    end

    def resolve
      scope.all
    end
  end
end
我的应用程序控制器中包含了Pundit,并且从Pundit::NotAuthorizedError中解救出了Pundit,在那里也设置了::forbidden

如果我使用管理员帐户登录,则授权本身有效,我可以访问/categories/*。如果我注销,我会得到以下信息:
NoMethodError at/categories
nil:NilClass的未定义方法`
在写问题的时候,我想我发现了问题所在——我猜Pundit寻找的是一个为零的用户,因为我没有登录。解决这个问题的正确方法是什么


最常用的方法是从未登录用户无法访问的页面重定向用户。只需在控制器中添加一个before操作:

class CategoriesController < ApplicationController
  before_action :redirect_if_not_logged_in

  <...>

  private

  def redirect_if_not_logged_in
    redirect_to :home unless current_user
  end
end
class CategoriesController

(这里我假设您有
current\u user
方法,该方法返回用户实例或nil。请更改:home to where you want redirect users)

有多种方法可以实现您想要的

  • 最明显(但有点脏)和直观的方法是在每种情况下都添加一个用户状态检查:

    user&&user.admin?
    

    它不会因
    nil
    错误而失败,因为条件的第二部分不会执行。但它看起来不太好看,对吗?特别是如果您必须将其复制到
    CategoryPolicy
    中的所有方法中

  • 相反,您可以做的是创建一个
    GuestUser
    类,用
    false
    响应
    admin?
    方法(),让专家“认为”您传递了一个
    User

    在面向对象的计算机编程中,空对象是没有引用值或具有定义的中性(“空”)行为的对象。空对象设计模式描述了此类对象的使用及其行为(或缺少)

    user
    nil
    时使用它。实际上,它将如下所示:

    class ApplicationPolicy
      attr_reader :user, :record
    
      def initialize(user, record)
        @user = user || GuestUser.new
        @record = record
      end
    
      # ...
    end
    
    class GuestUser
      def admin?
        false
      end
    end
    
    这样,您就不必修改任何其他代码,因为您传递的模型响应策略所期望的方法(
    admin?
    )。您可能希望在其他地方(不在策略文件中)定义此
    GuestUser
    ,具体取决于您是否希望应用程序的其他部分重用该行为

  • 您还可以继续使用p.Boro answer中的重定向方法。从某种意义上讲,它的灵活性较低,但如果您除了重定向所有未登录的用户之外不需要任何其他东西,那么它完全可以正常工作


  • 谢谢你的快速回答。这正是我想要的。我真的不知道为什么我没有提出重定向。
    class ApplicationPolicy
      attr_reader :user, :record
    
      def initialize(user, record)
        @user = user || GuestUser.new
        @record = record
      end
    
      # ...
    end
    
    class GuestUser
      def admin?
        false
      end
    end