Rails 5 - Pundit Scopes

时间:2016-12-12 05:38:41

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

我正在尝试学习如何在我的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. 关于课程范围 - 自述文件只有:

    班级范围

  2. 即。它没有额外的&#34;&lt;范围&#34;

    1. 自述文件在邮政政策中有这个(我在我的申请政策中有这个 - 但是也尝试将其添加到投标政策中):

      attr_reader:user,:scope

    2. 自述文件在邮政政策中有这个(我在我的申请政策中有这个 - 但是也尝试将其添加到投标政策中):

      def初始化(用户,范围)   @user = user   @scope =范围 端

    3. 我尝试按照专家文档中的自述文件的方式进行操作 - 但是当我尝试阅读文章时,我得到了同样的错误。

      我尝试更改resolve方法,以便始终返回scope.all:

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

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

      任何人都可以看到我需要做什么才能使用Pundit范围?

      回顾今年早些时候的相关问题 - 我可以看到,关于专家宝石的自述文件和我链接的教程文章似乎都不正确:Rails 4 - Pundit - scoped policy for index

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

      下次尝试

      pundit找到用户的方式有点可疑。

      我将resolve方法更改为非常简单的方法 - 检查用户的名字值是否等于字符串(这是我的用户表的记录,该用户表是我登录的用户名的第一个名称):

      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具有Jane的first_name属性。我认为这可能是某些事情有效的迹象,但是当我改变解决方法来要求&#34; John&#34;而不是&#34; Jane&#34;,我得到了相同的结果:

      (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识别用户吗?

1 个答案:

答案 0 :(得分:0)

所以,在关于codementor.io的另一场会议之后,我没有解决方案,但我了解到我不能将Pundit范围与政治家state_machine gem一起使用。我要么找到另一个授权工具,要么使用不同的状态机工具。

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

如果我设法学习另一台状态机并再次与Pundit一起尝试,我将再次发布以分享我所学到的关于如何使用权威范围的知识。起。