Search code examples
ruby-on-railsrubyrubygemsruby-on-rails-6pundit

How to override policy class in view


I'm trying to use the Pundit gem which lets you override the policy class in the controller like this

def create
  @publication = find_publication # @publication.class => Post
  authorize @publication, policy_class: PublicationPolicy
  @publication.publish!
  redirect_to @publication
end

I tried to override the policy class in the view as well like below but got an error unknown keyword: :policy_class

<% if policy(@publication, policy_class: PublicationPolicy).create? %>

Solution

  • policy is just a shortcut to look up a policy based on the resource that you pass to it.

    # Retrieves the policy for the given record.
    #
    # @see https://github.com/varvet/pundit#policies
    # @param user [Object] the user that initiated the action
    # @param record [Object] the object we're retrieving the policy for
    # @raise [InvalidConstructorError] if the policy constructor called incorrectly
    # @return [Object, nil] instance of policy class with query methods
    def policy(user, record)
      policy = PolicyFinder.new(record).policy
      policy&.new(user, pundit_model(record))
    rescue ArgumentError
      raise InvalidConstructorError, "Invalid #<#{policy}> constructor is called"
    end
    

    Its really just short for MyPolicy.new(user, record). Adding a policy_class option to it would just be utterly pointless. Why dynamically lookup something if you already know what you want?

    authorize on will both raise a NotAuthorizedError if not permitted and dynamically figure out the action you're trying to perform so it makes sense to have that option.