1

I defines a Pundit policy "CompanyPolicy" as stated in the documentation , the scopez gives the expected results ( on :index ) but I get an exception trying to use the company model instance :

 *** NameError Exception: undefined local variable or method `company' for #<CompanyPolicy:

here is the CompanyPolicy.rb

  class CompanyPolicy < ApplicationPolicy

      class Scope
        attr_reader :user, :scope

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

        def resolve
          if user.system_admin?
            scope.all
          else
            Company.none
          end
        end
      end

      def new?
        user.system_admin? ? true : false
      end

      def edit?
        user.system_admin? ? true : false
      end

      def show?
        user.system_admin? ? true : false
      end

      def destroy?
        internal_name = Rails.application.secrets.internal_company_short_name
        # do not destroy the internal company record 
        user.system_admin? && (company[:short_name] !=  internal_name ) ? true : false
      end
  end

and I check it from the Company controller

 def destroy
   authorize @company
   #@company.destroy
   ....
 end

why (company[:short_name] is wrong ?

If I look into the Pundit doc , the example with the PostPolicy , scope and post.published is similar ...

        class PostPolicy < ApplicationPolicy
          class Scope
            attr_reader :user, :scope

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

            def resolve
              if user.admin?
                scope.all
              else
                scope.where(:published => true)
              end
            end
          end

          def update?
            user.admin? or not post.published?
          end
        end
Andrey Deineko
  • 51,333
  • 10
  • 112
  • 145

2 Answers2

1

Take a look into documentation:

Pundit makes the following assumptions about this class:

  • The class has the same name as some kind of model class, only suffixed with the word "Policy".
  • The first argument is a user. In your controller, Pundit will call the current_user method to retrieve what to send into this argument
  • The second argument is some kind of model object, whose authorization you want to check. This does not need to be an ActiveRecord or even an ActiveModel object, it can be anything really.
  • The class implements some kind of query method, in this case update?. Usually, this will map to the name of a particular
    controller action.

That's it really.

Usually you'll want to inherit from the application policy created by the generator, or set up your own base class to inherit from:

class PostPolicy < ApplicationPolicy
  def update?
    user.admin? or not record.published?
  end
end

In the generated ApplicationPolicy, the model object is called record.

Andrey Deineko
  • 51,333
  • 10
  • 112
  • 145
  • Thanks a lot for clarifying it ... In the generated ApplicationPolicy, the model object is called record –  Oct 11 '15 at 13:56
  • Andre or @erwin is there a way to access the 'record' object in the scope class? – geoboy Sep 16 '16 at 05:05
0

just discovered that one should use @record rather than company ( read the a question related to scopes : Implementing scopes in Pundit )

but I don't understand why the Pundit doc does not mention it , and still use a model instance like 'post' for PostPolicy ... can someone enlighten us ?

Community
  • 1
  • 1