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

时间:2017-02-08 14:40:28

标签: ruby-on-rails scope nested pundit

我指的是我自己的问题Rails Nested Resources with Pundit Allowing Index,最后提出了一个有效的解决方案,但是在property_policy中没有更好的解决方案定义scope.where(?)或scope.select(?)?如何使用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属性属于一个特定交易。我的路线是嵌套的交易/ id /属性,除了我有简单&#34; / properties&#34;的完整属性列表。非常感谢您的帮助。

**更新**

我终于去了

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

不确定这是否正确

1 个答案:

答案 0 :(得分:0)

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

@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?,这不是您想要的。

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

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

在这种情况下,您不必在Scope#resolve方法中做任何特别的事情。只需返回scope,因为您可以假设用户是管理员。