Rails 4 – Pundit,Scopes:入门

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

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

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

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

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

wrong number of arguments (given 2, expected 0) 

它指向我将授权@eoi行放在我的控制器中的任何地方。 我之前在这里询问过这个错误

我最初放入set_eoi方法如下:

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

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

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

当我找到这篇文章的答案时,我停止了这样做, 该post说在之前的行动中不使用授权(即使权威的Go Railsvideo教程显示这样做)。

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

  def show authorize @eoi end 

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

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

目的

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

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

我有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。

我已经看过这篇post,用户似乎和我有相同的错误信息,尽管该post中的答案突出显示了该用户设置中的一些我自己没有的错误。

谁能看到我哪里出错了? 在我看来,索引只能起作用,因为我没有尝试将authorize @eois添加到它。 范围适用于索引目的。 当我尝试授权时,show动作根本不起作用。

好的,关于Pundit文档: https : //github.com/elabs/pundit

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

 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 

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