1

I have a question about Pundit.

Basically I want to do this:

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

but I don't know how I can pass @restaurant from my controller into my policy.

here's my index method:

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

I tried to do this:

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

with this index method:

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

But I'm getting this error:

Pundit::PolicyScopingNotPerformedError in EmployeesController#index

Community
  • 1
  • 1
Maxim
  • 39
  • 3
  • 11
  • There's a setting pundit has you add where that error gets raised. I.think you need to use the policy_scope syntax, or remove the line: after_action :verify_policy_scoped, only: :index. The docs do mention "However, it tracks if policy_scope is used", so it's unclear that you manually calling it view EmployeePolicy::Scope would be enough to trigger that validation. policy_scope(Employee) – Jay Dorsey Jan 15 '19 at 03:15

1 Answers1

0

It's not clear from your question where you put the Scope class, but it should live inside your EmployeePolicy class. You'll pass in a parameter just like you would to any other class.

I think you are getting this error because you are inadvertently converting your ActiveRecord scope to an Array by using the #select method. Try using ActiveRecord methods instead.

# 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

Your index method should look like this:

# 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

If you are still having trouble, then this post may be instructive.

moveson
  • 5,103
  • 1
  • 15
  • 32