使用 pundit resolve 方法的嵌套资源范围

Scope for nested resources using pundit resolve method

我指的是我自己的问题 Rails Nested Resources with Pundit Allowing Index 并最终提出了一个可行的解决方案,但是没有更好的解决方案来定义 scope.where(?) 或 scope.select(? ) 在 property_policy 中?如何使用 pundit resolve 方法获取仅属于一笔特定交易的所有属性?

我最后做了什么:

properties_controller.rb

class PropertiesController < ApplicationController
before_action :set_deal, except: [:index, :all]
before_action :set_property, only: [:show, :edit, :update, :destroy]

def all
  @properties = Property.all
  authorize @properties
end

def index
  @deal = Deal.find(params[:deal_id])
  @properties = policy_scope(Deal)
end

def set_deal
  @deal = Deal.find(params[:deal_id])
  # pundit ######
  authorize @deal
  ###############
end
(...)
end

property_policy.rb

class PropertyPolicy < ApplicationPolicy
class Scope < Scope
def resolve
  scope.all if user.admin?
end
def all?
  user_is_admin?
end
def user_is_admin?
  user.try(:admin?)
end 
(...)
end

我更喜欢什么:

properties_controller.rb

def index
  @deal = Deal.find(params[:deal_id])
  @properties = policy_scope(Property) # => for # @properties = @deal.properties
  authorize @deal
end

并且在 property_policy.rb 类似

def resolve
  # scope.where(???) if user.admin? # only an admin user can see the @deal.properties
  # or any other solution using scope
 end

提醒一下,1 笔交易有很多属性,1 笔 属性 属于一个特定的交易。我的路线是嵌套的 deals/id/properties 除了完整的属性列表我有简单的“/properties”。非常感谢您的帮助。

** 更新 **

我终于去了

properties_controller.rb

def index
  @deal = Deal.find(params[:deal_id])
  @properties = policy_scope(@deal.properties)
  authorize @properties, :index?
end

并在 property_policy.rb

class PropertyPolicy < ApplicationPolicy
  class Scope < Scope
    def resolve
      user.admin? ? scope.all : scope.none
    end
  end
  def index?
    user_is_admin?
  end
  def user_is_admin?
    user.try(:admin?)
  end
end

不确定这样是否正确

您要做的是将范围传递给策略 - 而不仅仅是 class。

@properties = policy_scope(@deal.policies)

class PropertiesPolicy
  class Scope < Scope
    def resolve
      user.admin? ? scope.all : scope.none
    end
  end
end

您的控制器的另一个问题是 authorize @deal 将调用 DealsPolicy#index?,这不是您想要的。

要授权要使用模型 class(而不是实例)调用 authorize 的索引操作:

def index
  authorize Property # calls PropertiesPolicy#index?
  @deal = Deal.find(params[:deal_id])
  @properties = policy_scope(@deal.policies)
end

在那种情况下,您实际上不必在 Scope#resolve 方法中做任何特别的事情。只需 return scope 因为此时您可以假设用户是管理员。