我需要覆盖专家范围,但我不知道如何

时间:2019-01-11 15:35:39

标签: ruby pundit

我有一个关于Pundit的问题。

基本上我想这样做:

class Scope < Scope
  def resolve
   scope.select {|employee| (employee.restaurant == @restaurant) && employee.actif}
  end
end

但是我不知道如何将@restaurant从我的控制器传递到我的策略中。

这是我的索引方法:

def index
  @restaurant = Restaurant.find(params[:restaurant_id])
  @employees = policy_scope(Employee)
end

我试图这样做:

class Scope
    attr_reader :user, :scope, :record

    def initialize(user, scope, record)
      @user = user
      @scope = scope
      @record = record
    end

    def resolve
      if is_user_manager_or_gerant_or_admin?
        scope.select {|employee| (employee.restaurant == record) && employee.actif}
      end
    end

    private

    def is_user_manager_or_gerant_or_admin?
    user.admin || (user.accreditations.select {|a| a.restaurant == record})[0].role == ("Gérant" || "Manager")
   end
end

使用此索引方法:

def index
  @restaurant = Restaurant.find(params[:restaurant_id])
  @employees = EmployeePolicy::Scope.new(current_user, Employee, @restaurant).resolve
end

但是我遇到了这个错误:

  

EmployeesController#index中的Pundit :: PolicyScopingNotPerformedError

1 个答案:

答案 0 :(得分:0)

从您的问题中尚不清楚将Scope类放在哪里,但是它应该存在于EmployeePolicy类中。您将像向其他任何类一样传递参数。

我认为您收到此错误,是因为您无意间通过使用#select方法将ActiveRecord范围转换为数组。尝试改用ActiveRecord方法。

# app/policies/employee_policy.rb

class EmployeePolicy < ApplicationPolicy
  class Scope
    attr_reader :user, :scope, :restaurant

    def initialize(user, scope, restaurant)
      @user = user
      @scope = scope
      @restaurant = restaurant
    end

    def resolve
      if is_user_manager_or_gerant_or_admin?
        scope.where(restaurant: restaurant).where.not(employee.actif: nil)
      end
    end

    ...

  end
end

您的索引方法应如下所示:

# app/controllers/employees_controller.rb

class EmployeesController < ApplicationController
  def index
    @restaurant = Restaurant.find(params[:restaurant_id])
    @employees = EmployeePolicy::Scope.new(current_user, Employee, @restaurant).resolve
  end
end

如果您仍然遇到问题,那么this post可能很有帮助。