Rails 4 - 专家,范围:入门

时间:2016-09-08 03:47:23

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

我在过去2年多的努力中努力学习如何使用专家。

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

我之前曾就同一主题提出了几个问题,但我没有更接近解决方案。我最近的问题是:herehereherehereherehere

还有其他几个,但这些给出了一般情况,我正在努力解决如何开始的基本原理。

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

wrong number of arguments (given 2, expected 0)

它指向我将授权@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视频教程显示这样做)。

然后,我将授权调用移动到show动作本身:

  def show
    authorize @eoi
  end

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

请有人帮助您入门。我目前的设置如下:

目标

用户有个人资料。这些简档拥有他们创建的项目。其他用户可以表达对加入另一个用户拥有的项目的兴趣。创建项目的用户应该能够看到他们自己项目中提交的所有eois。在项目页面上查看项目页面时,在项目上提交eoi的用户应该只能看到自己的eoi。此外,每个用户都可以看到他们自己的eois的索引(无论他们提交eoi的项目是什么)。

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

我有User,Profile的模型。项目和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

当我保存所有这些并尝试它时,我可以正确地渲染所有索引(虽然我可以在我将@eois添加到eois控制器中的索引操作时添加。

我无法显示要显示的节目页面。相反,我收到的错误是:

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

我不知道此错误消息的含义。我只是在eoi控制器的show动作中为authorize方法提供了一个参数 - 所以我很奇怪这个错误认为我给了2。

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

任何人都可以看到我出错的地方吗?在我看来,索引只能起作用,因为我还没有尝试过为它添加authorize @eois。范围适用于索引目的。当我尝试授权时,show动作根本不起作用。

1 个答案:

答案 0 :(得分:0)

好的,关于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,其中权威示例将它们放在其中,例如:

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

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