【问题标题】:Rails 4 - Pundit, Scopes: Getting StartedRails 4 - Pundit,范围:入门
【发布时间】:2017-01-15 21:01:47
【问题描述】:

在过去 2 年多的时间里,我一直在努力学习如何使用 pundit。

我正在尝试编写范围策略,以便不同的用户可以根据他们适合的范围类接收对象。

我之前就同一主题提出了几个问题,但我离解决方案还差得远。我最近的问题是:here, hereherehereherehere

还有其他几个,但这些给出了总体情况,我正在努力了解如何开始的基础知识。

我在开始时遇到了一百万个问题,并意识到经过 4 年的尝试(每天 - 10 多个小时),我在学习编码方面并没有真正走多远,但我目前面临的问题是出现此错误:

wrong number of arguments (given 2, expected 0)

它指向我将 authorize @eoi 行放在控制器中的任何位置。我之前问过这个错误here

我原来是在set_eoi方法中放入如下:

 def set_eoi
      @eoi = Eoi.find(params[:id])
      authorize @eoi
    end

我在控制器的 before 操作中使用了该方法:

before_action :set_eoi, only: [:show, :edit, :update, :destroy]

当我找到this 帖子的答案时,我停止了这样做,该帖子说不要在之前的操作中使用授权(即使权威人士的 Go Rails 视频教程显示这样做)。

然后,我将授权调用移至显示操作本身:

  def show
    authorize @eoi
  end

这会产生与在之前的操作中使用它相同的错误。

请,有人可以帮助开始。我目前的设置如下:

目标

用户有个人资料。这些配置文件拥有他们创建的项目。其他用户可以表示有兴趣加入其他用户拥有的项目。创建项目的用户应该能够看到在他们自己的项目中提交的所有 eois。提交项目 eoi 的用户在查看项目页面时应该只看到他们自己的 eoi。此外,每个用户都可以看到他们自己的 eois 的索引(无论他们在哪个项目上提交了 eois)。

我目前采用的方法是为同一个控制器制定两个策略(尽管我认为this 问题可能解决了这不是一个好的方法)。

我有用户、个人资料的模型。项目和Eoi。这些关联是:

class User < ActiveRecord::Base
  has_one :profile
  has_many :eois
end

class Profile < ActiveRecord::Base
  belongs_to :user
  has_many :projects, dependent: :destroy
end

class Project < ActiveRecord::Base
  belongs_to :profile
  has_many :eois
end

class Eoi < ActiveRecord::Base
  belongs_to :project
  belongs_to :user
end

我的路线文件有:

resources :eois#, only: [:index]
  concern :eoiable do
    resources :eois
  end

resources :projects do
    member do
  concerns :eoiable
end

我有一个 Eoi 政策和一个项目 Eoi 政策,如下所示:

class EoiPolicy < ApplicationPolicy

  class Scope

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

    def resolve
      # selects all the EOI's for a given user
      @scope.where(user_id: @user.id)
    end

  end

  def index?
    true
  end

  def new?
    true
  end

  def show?
#     record.user_id == user.id || user.profile.project_id == record.project_id
    true
  end

  def edit?
    user.id == eoi.user.id?
  end

  def create?
    true
  end

  def update?
    user.id == eoi.user.id?
  end

  def destroy?
    user.id == eoi.user.id?
  end


end


class ProjectEoiPolicy < ApplicationPolicy
  class Scope < Scope
    def resolve(project_id)
      project = Project.find(project_id)
      if project.owner?(@user)
        # if the user is the owner of the project, then get
        # all the eois
        project.eois
      else
        # select all the eois for the project
        # created by this user
        Eoi.for_user(@user.id).for_project(project_id)
      end
    end
  end

end

我的 eois 控制器有:

class EoisController < ApplicationController
  before_action :get_project, except: [:index, :show]
  before_action :set_eoi, only: [:show, :edit, :update, :destroy]
  # before_action :load_parent
  # before_action :load_eoi, only: [:show, :edit, :update, :destroy]


  def index
    if params[:project_id]
      @eois = ProjectEoiPolicy::Scope.new(current_user, Eoi).resolve(params[:project_id])
    else
      @eois = policy_scope(Eoi)
    end
  end


  # GET /eois/1
  # GET /eois/1.json
  def show
    authorize @eoi
  end

我的申请政策有:

class ApplicationPolicy
  attr_reader :user,  :scope

  class Scope
    def initialize(user, scope)
      #byebug        
      @user = user
      # record = record
      @scope = scope
    end

    def resolve
      scope
    end
  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

当我保存所有这些并尝试它时,我可以正确呈现所有索引(尽管当我将 authorize @eois 添加到 eois 控制器中的索引操作时我不能。

我无法渲染显示页面。相反,我收到一条错误消息:

ArgumentError at /projects/26/eois/24
wrong number of arguments (given 2, expected 0)

我不知道这个错误信息是什么意思。我只在 eoi 控制器的 show 动作中为 authorize 方法提供了一个参数 - 所以我觉得这个错误认为我给出了 2 对我来说很奇怪。

我已经看到 this 帖子,其中用户似乎有与我相同的错误消息,尽管该帖子中的答案突出显示了该用户设置中的一些我自己没有的错误。

谁能看出我哪里出错了?在我看来,该索引之所以有效,是因为我没有尝试向它添加 authorize @eois。范围对于索引目的是正确的。当我尝试授权时,显示操作根本不起作用。

【问题讨论】:

    标签: ruby-on-rails ruby scope parameter-passing pundit


    【解决方案1】:

    好的,在 Pundit 文档上:https://github.com/elabs/pundit

    该示例似乎表明 Policy Scope 需要从 applicationPolicy 的范围继承:

    class PostPolicy < ApplicationPolicy
      class Scope < Scope
    

    所以我猜你应该试试这个:

    class EoiPolicy < ApplicationPolicy
      class Scope < Scope # this is the changed line of code
    

    同样,您拥有的应用程序策略将 attr_readers 置于 Scope 之外,而权威示例将它们置于其中,例如:

    class ApplicationPolicy
      # should not be here
      # attr_reader :user,  :scope
    
      class Scope
        # should be here instead
        attr_reader :user,  :scope
    

    当您只需要阅读器时,您可能会在此处深入了解 @-var 的问题:

    def resolve
      # selects all the EOI's for a given user
      # should not use `@scope`
      # @scope.where(user_id: @user.id)
      # instead use `scope` which is the reader
      scope.where(user_id: @user.id)
    end
    

    不管这是否修复了你的错误......你可能需要做这些事情:)

    【讨论】:

    • 我尝试将
    • 该死...值得一试,但我很遗憾它没有帮助。我的猜测是它没有使用应该使用的initialize
    • 谢谢。接下来我将尝试了解有关初始化函数的更多信息。感谢您的帮助。
    • 好的,只是对权威页面上的示例进行比较和对比...您应该将 attr_reader 行移到 class Scope 定义中。您应该使用scope 而不是@scopeinitialize 方法除外)。我将更新上面的示例以匹配它
    • 谢谢。我尝试了所有这些事情。我一直在范围和@scope 之间切换,试图让这些工作。它们似乎都有效,尽管我理解为什么使用范围而不是“a”范围是一个很好的修正。我也一直在切换 attr_reader 行。我将它移到应用程序范围方法中。我仍然收到错误消息,但我会继续寻找线索。再次感谢
    猜你喜欢
    • 2017-01-04
    • 1970-01-01
    • 2017-04-26
    • 1970-01-01
    • 1970-01-01
    • 2014-12-04
    • 1970-01-01
    • 2016-07-11
    • 1970-01-01
    相关资源
    最近更新 更多