【问题标题】:Rails 5 - Pundit ScopesRails 5 - Pundit 范围
【发布时间】:2017-04-26 23:01:39
【问题描述】:

我正在尝试学习如何在我的 Rails 5 应用中使用 pundit。

我正在尝试遵循本文中的方法。

https://learn.co/lessons/devise_pundit_readme

我正在努力从这种方法中找到有效的结果。具体来说,我尝试使用定义范围的索引中的行是:

<% policy_scope(@user.proposals).each do |prop| %>

正在返回此错误:

undefined method `proposals' for nil:NilClass

我的设置是:

我有用户模型和提案模型。这些关联是:

用户:

  has_many :proposals

建议:

belongs_to :user

应用控制器:

include Pundit

提案控制器:

def index
    @proposals = Proposal.all
    # @bips = @proposal.bips
    authorize @proposals
  end

提案政策:

  class ProposalPolicy < ApplicationPolicy
      class Scope < Scope
         def resolve
           if user.has_role?(:admin)
             scope.all
           else
             scope.where(:current_state == :draft)
           end
         end
       end

      def index?
        true
      end

提案索引:

<% policy_scope(@user.proposals).each do |prop| %>
    <%= prop.title %>
    <%= prop.user.full_name %>
    <%= prop.created_at %>
    <%= link_to 'More', proposal_path(prop) %>
<% end %>

当我尝试这个时,我收到一个错误 - 突出显示我的索引这行的问题:

  <% policy_scope(@user.proposals).each do |prop| %>

鉴于这与我链接的文章完全一样,我不知道为什么它不起作用。

错误提示:

undefined method `proposals' for nil:NilClass

我链接的文章和 Pundit 文档之间的主要区别在于 Pundit 自述文件说:

  1. 关于 Scope 类 - 自述文件只有:

    类作用域

即它没有额外的“

  1. 自述文件在 Post Policy 中有这个(我在我的应用程序策略中有它 - 但也尝试将它添加到 Proposal Policy 中):

    attr_reader :user, :scope

  2. 自述文件在 Post Policy 中有这个(我在我的应用程序策略中有它 - 但也尝试将它添加到 Proposal Policy 中):

    def 初始化(用户,范围) @user = 用户 @范围 = 范围 结束

我尝试按照权威文档中的自述文件显示的方式进行操作 - 但我收到与尝试阅读文章时相同的错误。

我尝试更改解析方法,使其始终返回 scope.all:

def resolve
       if user.has_role?(:admin)
         scope.all
       else
        scope.all
       end

但我仍然遇到同样的错误。

谁能看到我需要做什么才能使用 Pundit 范围?

回顾我今年早些时候的相关问题 - 我可以看到权威人士 gem 上的自述文件和我链接的教程文章似乎都不正确:Rails 4 - Pundit - scoped policy for index

我无法从链接的 SO 帖子中获得任何解决方案 - 但这些答案中的概念比 gem 自述文件和教程更全面。

下一次尝试

权威发现用户的方式有些可疑。

我将解析方法更改为非常简单的方法 - 检查用户的名字值是否等于字符串(这是我的用户表中我登录的用户的名字的记录):

class ProposalPolicy < ApplicationPolicy
  class Scope #< Scope
    # class Scope
    attr_reader :user, :scope

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

     def resolve
       if user.first_name == "Jane"
         scope.all
       else
         scope.where(:current_state == :draft)
       end

     end
   end

当我尝试这个时,我收到一条错误消息:

undefined method `first_name' for nil:NilClass

我认为专家不知道如何找到用户。

当我在我的提案索引操作中添加一个 byebug 时,我得到:

user.inspect
*** NameError Exception: undefined local variable or method `user' for #<ProposalsController:0x007fa3e8cf8698>

(byebug) @user
nil


(byebug) current_user
#<User id: 43, first_name: "Jane",

所以 - 我试图让权威人士识别用户的方式有问题。我梳理了 GitHub 上的数百个存储库,试图找到人们如何让它工作的示例。我找不到与我在链接帖子中尝试的所有选项不同的地方。

我不确定这是否奇怪,但我可以做到:

(byebug) policy_scope(Proposal)
  Proposal Load (0.4ms)  SELECT "proposals".* FROM "proposals"
#<ActiveRecord::Relation [#<Proposal id: 17, user_id: 43, title: "asdf", description: "adsf", byline: "asdf", nda_required: true, created_at: "2016-11-16 00:28:31", updated_at: "2016-11-28 01:16:47", trl_id: 1>]>

user_id 43 有一个 first_name 属性,它是 Jane。我认为这可能表明某些东西正在运行,但是当我将解析方法更改为请求“John”而不是“Jane”时,我得到了相同的结果:

(byebug) policy_scope(Proposal)
  Proposal Load (0.8ms)  SELECT "proposals".* FROM "proposals"
#<ActiveRecord::Relation [#<Proposal id: 17, user_id: 43, title: "asdf", description: "adsf", byline: "asdf", nda_required: true, created_at: "2016-11-16 00:28:31", updated_at: "2016-11-28 01:16:47", trl_id: 1>]>

显然,这次不正确,因为该提案所属的用户的名字不是 John。

谁能看到我需要做什么才能让 Pundit 识别用户?

【问题讨论】:

  • undefined method 'proposals' for nil:NilClass 表示用户是nil,你能raise user.inspect 并显示输出吗
  • policyindex 上,在控制器中定义之前如何获得@user?要么在此处定义它,要么如果您使用过任何身份验证 gem,例如 devise,请尝试使用 current_user 而不是 @user
  • 我不确定你的意思。 user 是传递给应用程序策略中范围方法的两个属性之一。
  • @MihalkoFarhat: user.inspect NameError: undefined local variable or method `user' for main:Object
  • @Mel 他的意思是您的策略对象中有@user var,但视图中没有它。你必须先在控制器动作中初始化它,或者使用一些辅助方法,比如current_user

标签: ruby-on-rails ruby authorization pundit scopes


【解决方案1】:

因此,在 codementor.io 上的另一次会议之后,我没有解决方案,但我了解到我不能将 Pundit 范围与 statesman state_machine gem 一起使用。我要么需要找到另一个授权工具,要么使用不同的状态机工具。

我还了解到,权威自述文件在示例中有几个隐含的假设,这使得它们不适合使用。

如果我设法学习另一种状态机并再次尝试使用 Pundit,我将再次发布以分享我所学到的有关如何使用 Pundit 作用域的知识。以后。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-15
    • 1970-01-01
    • 2017-01-04
    • 1970-01-01
    • 1970-01-01
    • 2019-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多