我正在尝试学习如何在我的Rails 4应用程序中使用Pundit。
我有以下型号:
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
我有一个范围EoiPolicy
:
class EoiPolicy < ApplicationPolicy
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
if user.profile.project.id == @eoi.project_id?
scope.where(project_id: @user.profile.project.id)
elsif user.id == eoi.user_id?
scope.where(user_id: user.id)
else
nil
end
end
end
def index?
user.profile.project.id == @eoi.project_id? or user.id == eoi.user_id?
end
def new?
true
end
def show?
user.profile.project.id == @eoi.project_id? or user.id == eoi.user_id?
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
在我的EoisController
中,我尝试将范围用于:
def index
# @eois = @project.eois
@eois = policy_scope(Eoi)
# @eois = Eois.find_by_project_id(params[:project_id])
end
然后在我的view/eois/index
中,我试图用:
<% policy_scope(@user.eois).each do |group| %>
我无法让它发挥作用。错误消息突出显示了策略中此范围方法的这一行:
if user.profile.project.id == @eoi.project_id?
对我而言,这看起来是正确的,尽管我仍然试图解决这个问题。任何人都可以看到使这项工作需要发生的事情,因此如果用户是用户,谁的个人资料拥有相关项目,那么与该项目相关的所有eois都是可见的。
否则,如果用户是创建eoi的用户,那么他们创建的所有eois都是可见的?
错误消息显示:
undefined method `project' for #<Profile:0x007fa03f3faf48>
Did you mean? projects
projects=
我想知道是否因为索引会有很多记录,它需要在策略中显示不同的内容以识别多个记录吗?
我也尝试用以下代码替换该行:
if @eoi.project_id == @user.profile.project.id?
虽然这也是错误的并且给出了
undefined method `project_id' for nil:NilClass
Did you mean? object_id
我也试过制作范围:
def resolve
# cant figure what is wrong with this
if eoi.project_id == user.profile.project.id?
scope.where(project_id: @user.profile.project.id)
else
nil
end
end
但这也是错误的并且给出了这个错误:
undefined local variable or method `eoi' for #<EoiPolicy::Scope:0x007ffb505784f8>
我也尝试过:
def resolve
# cant figure what is wrong with this
if @eoi.project_id == user.profile.project.id? or Eoi.project_id == user.profile.project.id?
scope.where(project_id: @user.profile.project.id)
elsif user.id == eoi.user_id?
scope.where(user_id: user.id)
else
nil
end
end
end
def index?
user.profile.project.id == Eoi.project_id? or user.id == Eoi.user_id?
end
但是该尝试提供了此错误消息:
undefined method `project_id' for nil:NilClass
Did you mean? object_id
当前的想法
我认为我需要将更多用户和范围传递给范围方法。如果我也可以通过项目,那么我可以使范围与EoI所涉及的项目相关。
如果我可以使用它,那么也许我可以让scope方法适用于控制器上的索引视图:
class Scope
attr_reader :user, :scope
def initialize(user, scope, project)
@user = user
@scope = scope
@project = project
end
end
然后在控制器中:
def index
# @eois = @project.eois
@eois = policy_scope(Eoi, @project)
# authorize @eois
# @eois = Eois.find_by_project_id(params[:project_id])
end
这不起作用,当我尝试时收到错误说明该政策
wrong number of arguments (given 2, expected 1)
请帮忙!
下次尝试
我的下一次尝试是尝试从[this] Pundit问题中获取建议,并实现如何为特定用户获得正确范围的想法。
在我的Eoi政策中,我将解决方法更改为:
class Scope
attr_reader :user, :scope
def initialize(user, scope) #project
@user = user
@scope = scope
# @project = project
end
def resolve
# if Eoi.project_id == user.profile.project.id? or Eoi.project_id == user.profile.project.id?
if user.id == eoi.projects.profile.user.map(&:id)
scope.joins(eois: :projects).where(project_id: user.profile.projects.map(&:id)).empty?
# if scope.eoi.project_id == user.profile.projects.map(&:id)
# scope.where(project_id: user.profile.projects.map(&:id)).empty?
# scope.where(project_id: user.profile.project.id)
# elsif user.id == eoi.user_id?
# scope.where(user_id: user.id)
else
# nil
end
end
end
然后在我的eoi控制器索引操作中,我尝试了这个:
def index
# @eois = @project.eois
# @eois = policy_scope(Eoi, @project)
policy_scope(Eoi).where(project_id: params[:project_id])
# authorize @eois
# @eois = Eois.find_by_project_id(params[:project_id])
end
这也不起作用。此尝试的错误消息显示:
undefined local variable or method `eoi' for #<EoiPolicy::Scope:0x007f98677c9cf8>
我想出的事情要尝试。任何人都可以看到一种方法来为范围提供正确的输入来设置它吗?
观察 我注意到github上很多使用Pundit和范围的repos也包括这样的方法:
def scope
Pundit.policy_scope!(user, record.class)
end
该方法是Scope类的补充,并未在Pundit gem文档中显示。如果有必要包含,它有什么作用? 1
REWRITE
我现在已经在github上查看了200多个回购,以了解我应该如何制定政策来实现我的目标。我没有按照预期使用Pundit的想法。
我完全改变了我的设置,试图解决我无法理解的问题。我现在有:
Eois控制器
class EoisController < ApplicationController
def index
@eois = Eoi.by_user_id(current_user.id)
end
end
Projects :: Eois控制器
module Projects
class EoisController < ApplicationController
before_action :get_project
before_action :set_eoi, only: [:edit, :update, :destroy]
# after_action :verify_authorized
def index
@eois = Project.by_user_id(current_user.id).find_by(id: params[:project_id]).try(:eois) || []
end
def show
@eoi = Eoi.find(params[:id])
authorize @eoi
end
def set_eoi
@eoi = EoiPolicy::Scope.new(current_user, params[:project_id]).resolve.find(params[:id])
end
def get_project
@project = Project.find(params[:project_id])
end
Eoi政策(决定何时展示用户制作的所有eois)
class EoiPolicy < ApplicationPolicy
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
if scope.present?
Eoi.by_user_id(user.id)
# end
else
[]
end
end
end
def index?
user.profile.project.id == Eoi.project_id? or user.id == Eoi.user_id?
end
def new?
true
end
def show?
record.user_id == user.id || user.profile.project_id == record.project_id
# user.profile.project.id == @eoi.project_id? or user.id == eoi.user_id?
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
路线
resources :eois
resources :projects do
member do
resources :eois, controller: 'projects/eois
end
当我想要显示与项目相关的提交的EoI时,我使用Projects Eoi Policy,当我想要显示用户创建的Eois时,我使用Eoi Policy - 没有范围。
我很想知道这个,所以我可以按照预期的方式使用这个宝石。建议将不胜感激。我确信这个尝试不是Pundit的意思 - 但我无法弄清楚如何使用这个宝石,如文档中所示。
我无法使用policy_scope,因为我需要将project_id参数传递给项目eoi控制器索引操作的索引操作。
PaReeOhNos建议
我尝试实施PareeOhNos建议的尝试如下所示。我不确定我是否理解正确,因为eois总是有项目ID和用户ID,但也许我没有明白load_parent方法正在做什么。
在我的Eois Controller中,我有:
class EoisController < ApplicationController
before_action :load_parent
before_action :load_eoi, only: [:show, :edit, :update, :destroy]
def index
authorize @parent
@eois = EoiPolicy::Scope.new(current_user, @parent).resolve
end
def show
end
# GET /eois/new
def new
@project = Project.find(params[:project_id])
@eoi = @project.eois.build
@contribute = params[:contribute] || false
@participate = params[:participate] || false
@partner = params[:partner] || false
@grant = params[:grant] || false
@invest = params[:invest] || false
end
# GET /eois/1/edit
def edit
end
# POST /eois
# POST /eois.json
def create
@eoi = Project.find(params[:project_id]).eois.build(eoi_params)
@eoi.user_id = @current_user.id
respond_to do |format|
if @eoi.save
format.html { redirect_to Project.find(params[:project_id]), notice: 'Eoi was successfully created.' }
format.json { render :show, status: :created, location: @project }
else
format.html { render :new }
format.json { render json: @eoi.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /eois/1
# PATCH/PUT /eois/1.json
def update
respond_to do |format|
if @eoi.update(eoi_params)
format.html { redirect_to @project, notice: 'Eoi was successfully updated.' }
format.json { render :show, status: :ok, location: @eoi }
else
format.html { render :edit }
format.json { render json: @eoi.errors, status: :unprocessable_entity }
end
end
end
# DELETE /eois/1
# DELETE /eois/1.json
def destroy
@eoi.destroy
respond_to do |format|
format.html { redirect_to @project, notice: 'Eoi was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def load_parent
# @parent = (params[:project_id] ? Project.find(params[:project_id] : current_user)
@parent = params[:project_id] ? Project.find(params[:project_id]) : current_user
end
def load_eoi
@eoi = Eoi.find(params[:id])
authorize @eoi
end
在我的Eoi政策中,我有:
class EoiPolicy < ApplicationPolicy
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
if scope.is_a?(User)
Eoi.where(user_id: scope.id)
elsif scope.is_a?(Project)
Eoi.where(project_id: scope.id)
else
[]
end
end
end
def index?
record.is_a?(User) || user.profile.project.id == record.project_id
end
def new?
true
end
def show?
record.user_id == user.id || user.profile.project_id == record.project_id
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
在我的routes.rb中,我有:
resources :projects do
member do
resources :eois, shallow: true
resources :eois, only: [:index]
在我的eois / index中,我有:
<% @eois.sort_by(&:created_at).in_groups_of(2) do |group| %>
<% group.compact.each do |eoi| %>
<h4><%= link_to eoi.user.full_name %></h4>
<%= link_to 'VIEW DETAILS', eoi_path(eoi), :class=>"portfolio-item-view" %>
<% end %>
<% end %>
在我的eois / show中,我有:
"test"
当我尝试所有这些时,加载了eois / index页面。当我尝试显示特定的eoi页面时,我收到一条错误消息:
wrong number of arguments (given 2, expected 0)
错误消息指向授权控制器的@eoi行:
def load_eoi
@eoi = Eoi.find(params[:id])
authorize @eoi
end
如果我在show动作中使用authore @eoi而不是load eoi方法,则会出现同样的错误。
应用政策
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
下次尝试
考虑到PaReeOhNos的建议(上面复制过),我尝试对其进行调整以更好地适应我的用例。
现在,我有:
Eoi控制器
class EoisController < ApplicationController
# before_action :get_project
# before_action :set_eoi, only: [:show, :edit, :update, :destroy]
before_action :load_parent
before_action :load_eoi, only: [:show, :edit, :update, :destroy]
# GET /eois
# GET /eois.json
# def index
# @eois = @project.eois
# # @eois = Eois.find_by_project_id(params[:project_id])
# end
def index
# authorize @parent
@eois = policy_scope(Eoi.where(project_id: params[:project_id]))
# @eois = EoiPolicy::Scope.new(current_user, @parent).resolve
end
# GET /eois/1
# GET /eois/1.json
def show
end
# GET /eois/new
def new
@project = Project.find(params[:project_id])
@eoi = @project.eois.build
@contribute = params[:contribute] || false
@participate = params[:participate] || false
@partner = params[:partner] || false
@grant = params[:grant] || false
@invest = params[:invest] || false
end
# GET /eois/1/edit
def edit
end
# POST /eois
# POST /eois.json
def create
@eoi = Project.find(params[:project_id]).eois.build(eoi_params)
@eoi.user_id = @current_user.id
respond_to do |format|
if @eoi.save
format.html { redirect_to Project.find(params[:project_id]), notice: 'Eoi was successfully created.' }
format.json { render :show, status: :created, location: @project }
else
format.html { render :new }
format.json { render json: @eoi.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /eois/1
# PATCH/PUT /eois/1.json
def update
respond_to do |format|
if @eoi.update(eoi_params)
format.html { redirect_to @project, notice: 'Eoi was successfully updated.' }
format.json { render :show, status: :ok, location: @eoi }
else
format.html { render :edit }
format.json { render json: @eoi.errors, status: :unprocessable_entity }
end
end
end
# DELETE /eois/1
# DELETE /eois/1.json
def destroy
@eoi.destroy
respond_to do |format|
format.html { redirect_to @project, notice: 'Eoi was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def load_parent
# @parent = (params[:project_id] ? Project.find(params[:project_id] : current_user)
@parent = params[:project_id] ? Project.find(params[:project_id]) : current_user
end
def load_eoi
@eoi = Eoi.find(params[:id])
# authorize @eoi
end
Eoi政策
class EoiPolicy < ApplicationPolicy
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
# since we send the scoped eois from controller, we can pick
# any eoi and get its project id
# check if the current user is the owner of the project
# if (user.profile.projects.map(&:id).include?(project_id))
# # user is the owner of the project, get all the eois
# scope.all
# end
# #not the owner , then get only the eois created by the user
# scope.where(user_id: user.id)
# end
if scope.is_a?(User)
Eoi.where(user_id: scope.id)
elsif scope.is_a?(Project) && (user.profile.projects.map(&:id).include?(project_id))
project_id = scope.first.project_id
Eoi.where(project_id: scope.id)
else
Eoi.none
end
end
end
def index?
record.is_a?(User) || user.profile.project.id == record.project_id
end
def new?
true
end
def show?
record.user_id == user.id || user.profile.project_id == record.project_id
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
路线
resources :eois#, only: [:index]
concern :eoiable do
resources :eois
end
resources :projects do
concerns :eoiable
end
索引
<% @eois.sort_by(&:created_at).in_groups_of(2) do |group| %>
<% group.compact.each do |eoi| %>
<h4><%= link_to eoi.user.full_name %></h4>
<%= link_to 'VIEW DETAILS', project_eoi_path(eoi.project, eoi), :class=>"portfolio-item-view" %>
<% end %>
<% end %>
查看
'test'
这不起作用,因为当我导航到一个项目然后尝试渲染具有匹配项目ID的eois索引时,我得到一个空索引页面,当我在我的数据库中有4条记录时应该呈现。
LEITO&#39; S建议
根据Leito的建议,我也试过了:
Eoi控制器
class EoisController < ApplicationController
before_action :get_project
before_action :set_eoi, only: [:show, :edit, :update, :destroy]
# before_action :load_parent
# before_action :load_eoi, only: [:show, :edit, :update, :destroy]
# GET /eois
# GET /eois.json
# def index
# @eois = @project.eois
# # @eois = Eois.find_by_project_id(params[:project_id])
# end
def index
# authorize @eois
# authorize @parent
# policy_scope(@project.eois)
@eois = policy_scope(Eoi.where(project_id: params[:project_id]))
# @eois = EoiPolicy::Scope.new(current_user, @parent).resolve
end
# GET /eois/1
# GET /eois/1.json
def show
end
# GET /eois/new
def new
@project = Project.find(params[:project_id])
@eoi = @project.eois.build
@contribute = params[:contribute] || false
@participate = params[:participate] || false
@partner = params[:partner] || false
@grant = params[:grant] || false
@invest = params[:invest] || false
end
# GET /eois/1/edit
def edit
end
# POST /eois
# POST /eois.json
def create
@eoi = Project.find(params[:project_id]).eois.build(eoi_params)
@eoi.user_id = @current_user.id
respond_to do |format|
if @eoi.save
format.html { redirect_to Project.find(params[:project_id]), notice: 'Eoi was successfully created.' }
format.json { render :show, status: :created, location: @project }
else
format.html { render :new }
format.json { render json: @eoi.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /eois/1
# PATCH/PUT /eois/1.json
def update
respond_to do |format|
if @eoi.update(eoi_params)
format.html { redirect_to @project, notice: 'Eoi was successfully updated.' }
format.json { render :show, status: :ok, location: @eoi }
else
format.html { render :edit }
format.json { render json: @eoi.errors, status: :unprocessable_entity }
end
end
end
# DELETE /eois/1
# DELETE /eois/1.json
def destroy
@eoi.destroy
respond_to do |format|
format.html { redirect_to @project, notice: 'Eoi was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# def load_parent
# # @parent = (params[:project_id] ? Project.find(params[:project_id] : current_user)
# @parent = params[:project_id] ? Project.find(params[:project_id]) : current_user
# end
# def load_eoi
# @eoi = Eoi.find(params[:id])
# # authorize @eoi
# end
# # Use callbacks to share common setup or constraints between actions.
def set_eoi
@eoi = Eoi.find(params[:id])
end
def get_project
@project = Project.find(params[:project_id])
end
Eoi政策
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
if scope.joins(project: :profile).where profiles: { user_id: user }
Eoi.where(project_id: scope.ids)
elsif scope.joins(eoi: :user).where eois: { user_id: user }
Eoi.where(user_id: scope.ids)
else
Eoi.none
end
# since we send the scoped eois from controller, we can pick
# any eoi and get its project id
# check if the current user is the owner of the project
# if (user.profile.projects.map(&:id).include?(project_id))
# # user is the owner of the project, get all the eois
# scope.all
# end
# #not the owner , then get only the eois created by the user
# scope.where(user_id: user.id)
# end
# if scope.is_a?(User)
# Eoi.where(user_id: scope.id)
# elsif scope.is_a?(Project) && (user.profile.projects.map(&:id).include?(project_id))
# project_id = scope.first.project_id
# Eoi.where(project_id: scope.id)
# else
# Eoi.none
# end
end
end
def index?
true
# record.is_a?(User) || user.profile.project.id == record.project_id
end
def new?
true
end
def show?
true
# record.user_id == user.id || user.profile.project_id == record.project_id
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
路线和视图与上面的尝试相同
这里的问题是我的控制器中的get project方法。对于我试图在特定项目中显示所有eois的场景,我需要这样做。当我试图展示所有用户的eois时,我不需要它。
当我保存所有这些并尝试它时,项目上的eois显示正确。然而,eois(没有嵌套在项目中)应该向我展示我的所有(作为用户)eois,显示错误说:
Couldn't find Project with 'id'=
错误消息突出显示&#39; get_project方法&#39;。
LEITO&#39;更新后的建议
根据Leito的最新建议,我已经列出了当前的尝试。
在此之前,我想澄清所有Eois都将拥有用户ID和项目ID。我使用这个表来表示用户对项目的兴趣。我的目标是让其配置文件拥有该项目的用户查看该项目上提交的所有eois。然后,我还希望用户看到他们自己提交的所有eois(跨所有项目)。
Eoi政策
def resolve
if scope.joins(project: :profile).where 'profiles.user_id = ? OR eois.user_id = ?', user.id, user.id
Eoi.all
else
Eoi.none
end
Eoi控制器
def index
@eois = policy_scope(Eoi)
@eois = @eois.where(project_id: params[:project_id]) if params[:project_id]
end
目前,这可以很好地找到嵌套在项目下的eois(project / 26 / eois)。但是,当我尝试执行eois / index(不在项目下嵌套)时,我想返回所有用户的eois,我得到一个错误:
Couldn't find Project with 'id'=
它突出了eoi控制器的这一行:
def get_project
@project = Project.find(params[:project_id])
end
我现在还不确定我是否理解解决方法或控制器剔除的想法。我无法查看范围行的错误,看看要尝试更改的内容。
答案 0 :(得分:3)
我是上一位关于该问题的评论者。
对于您的EoiScope,您只需要用户可以访问的Eois(因为它们属于此配置文件下的项目),独立于项目(此要求仅适用于控制器,因为是嵌套的),因此您的控制器应该看起来像这样:
编辑:根据您的最新尝试,我已更新范围以考虑Eois直接属于用户(而不是通过项目),您只需将其范围扩展到项目或者不是基于params [:project_id]的存在,请参阅更新的答案。
@eois = policy_scope(Eoi)
@eois = @eios.where(project_id: params[:project_id]) if params[:project_id]
你的范围应该在它到达用户之前进行连接,或者只是在Eoi上查找user_id属性。
class EoiPolicy < ApplicationPolicy
class Scope < Scope
def resolve
scope.joins(project: : profile).where 'profiles.user_id = ? OR eois.user_id = ?', user.id, user.id
end
end
# Other methods that differ from ApplicationPolicy's methods
end
请注意,Scope不会调用eoi
,但默认*范围只知道scope
和user
。 *默认情况下,我的意思是它继承自ApplicationPolicy::Scope
答案 1 :(得分:2)
在你的第一个例子中,有几个问题。首先,@eoi
不存在,也不存在。 @eoi
变量在控制器中设置,这是一个不同的对象。它的工作方式与您可以访问的视图不同,因此永远不会设置。
同样,eoi
变量不会设置,因为initialize
方法只分配user
和resource
变量,所以它们只是你的两个有权访问(除非你重命名)
政策范围与您认为的有效方式略有不同。策略本身通常会使用户登录,以及您要授权的类或记录。但是,范围通常不会将记录作为第二个参数。它是一个范围,因此可以是活动记录子类,也可以是关系。但是你并不局限于此,你可以通过提供记录来解决这个问题,但请注意这对于Pundit来说不是正常行为。
为了实现您的目标,您只需进行一些调整即可:
class EoiPolicy < ApplicationPolicy
class Scope
attr_reader :user, :eoi
def initialize(user, eoi)
@user = user
@eoi = eoi
end
def resolve
if user.profile.project.id == eoi.project_id
Eoi.where(project_id: user.profile.project.id)
elsif user.id == eoi.user_id
Eoi.where(user_id: user.id)
else
nil
end
end
end
def index?
user.profile.project.id == record.project_id or user.id == record.user_id
end
def new?
true
end
def show?
user.profile.project.id == record.project_id? or user.id == record.user_id
end
def edit?
user.id == record.user.id
end
def create?
true
end
def update?
user.id == record.user.id
end
def destroy?
user.id == record.user.id
end
end
此处的主要更改是attr_reader :user, :scope
现在为attr_reader :user, :eoi
,您可以访问该范围内的eoi
。
访问此内容不再以@
为前缀,因为这与专家的工作方式一致。
在整个策略的其余部分,@eoi
再次无效,但已更改为record
(假设这是ApplicationPolicy中的内容)。请记住范围,其余的政策是两个不同的类别。
通过此设置,您现在应该只需从控制器中调用policy_scope(@eoi)
即可。请注意此处@eoi
变量的使用,而不是之前的Eoi
类。这是至关重要的,因为没有这个,您将无法访问user_id
或project_id
之类的内容,因为这些方法在Eoi类中不存在,而只是记录。
我还删除了if条件末尾的?
符号。这些通常用于表示被调用的方法返回一个布尔值,而你只是返回一个整数。我想你实际上会得到一个错误,说方法不存在,但是如果你重命名了,那么你可能想把它们放回去,但正如我所说的那样,它确实违背了ruby编码风格。
另一方面,在语句中使用or
或and
代替||
或&&
可能会在奇怪的情况下使用与您预期的不同。在大多数情况下它很好,但从技术上讲它并不意味着同样的事情。
希望这一切都有所帮助,如果您有任何进一步的问题,请告诉我。
答案 2 :(得分:0)
对于其他人,我不确定这是否是以预期的方式使用Pundit的解决方案,但是它确实会在我的能力范围内生成我想要的流程。
感谢所有帮助过此事的人。我相信我还有很多东西可以学习如何改进这个,但是现在,这是一个有效的解决方案。
总之 - 我现在有两个策略用于1个控制器。
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
项目Eoi政策
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
Eoi控制器索引操作
class EoisController < ApplicationController
before_action :get_project, except: [:index, :show]
before_action :set_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