0

I have read several questions on this same topic, but none of them solves my doubts or works for me.

Pundit is unable to find namespaced policies in my code, but I can not understand why. I have a 'backend' namespace, and any time that the items_controller.rb in this 'backend' is called, it uses the app/policies/item_policy.rb, instead of the app/policies/backend/item_policit.rb one.

Any help would be very appreciated please. I have spent many time on this issue.

My app/policies/ directory:

application_policy.rb
backend_policy.rb
item_policy.rb
backend/item_policy.rb

application_policy.rb

class ApplicationPolicy
  attr_reader :user, :record

  def initialize(user, record)
    @user = user
    @record = record
  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

  class Scope
    attr_reader :user, :scope

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

    def resolve
      scope
    end
  end
end

backend_policy.rb

class Backend::ApplicationPolicy < ApplicationPolicy
  attr_reader :user, :record

  def initialize(user, record)
    @user = user
    @record = record
  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

  class Scope
    attr_reader :user, :scope

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

    def resolve
      scope
    end
  end
end

backend/item_policy.rb

class Backend::ItemPolicy < Backend::ApplicationPolicy
  attr_reader :user, :item

  def initialize(user, item)
    @user = user
    @item = item
  end

  def index?
    raise Pundit::NotAuthorizedError, "must be logged in" unless @user.admin?
  end
end

controllers/backend/items_controller.rb

class Backend::ItemsController < Backend::ApplicationController
  before_action :set_item, only: [:show, :edit, :update, :destroy]
  after_action :verify_authorized

  # GET /backend/items
  # GET /backend/items.json
  def index
    @search = Item.search (search_params)
    @items = @search.result().page(params[:page]).per(12)
    authorize Item
  end
....
end
patriciasc
  • 133
  • 1
  • 7

1 Answers1

2

This is how your policy name is extracted in pundit code

def find
  if object.respond_to?(:policy_class)
    object.policy_class
  elsif object.class.respond_to?(:policy_class)
    object.class.policy_class
  else
    klass = if object.respond_to?(:model_name)
      object.model_name
    elsif object.class.respond_to?(:model_name)
      object.class.model_name
    elsif object.is_a?(Class)
      object
    elsif object.is_a?(Symbol)
      object.to_s.classify
    else
      object.class
    end
    "#{klass}Policy"
  end
end

So either add a function "policy_class" to your model or namespace the model itself

Moustafa Samir
  • 2,248
  • 1
  • 25
  • 32