2

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? %>
tadman
  • 208,517
  • 23
  • 234
  • 262
vince
  • 2,374
  • 4
  • 23
  • 39
  • Are you asking "Why does `authorize` take options that `policy` does not?" – tadman Aug 04 '20 at 19:03
  • Yes. I need something identical and was happy see that authorize takes options that let you override the policy class in the controller but I'm not able to similarly override the policy class in the view using the [corresponding] policy function – vince Aug 04 '20 at 19:18
  • If you don't get an answer here, might be worth engaging on a Pundit-specific forum or in the Issues on that project to request the feature. – tadman Aug 04 '20 at 19:29

1 Answers1

2

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.

max
  • 96,212
  • 14
  • 104
  • 165
  • 1
    thank you, that makes sense. I could just do this then `<% if PublicationPolicy.new(current_user, @publication).create? %>` – vince Aug 04 '20 at 21:15
  • 1
    Yes, but you should probably be passing the policy as a local or instance variable from the controller as you should keep views as simple as possible. – max Aug 04 '20 at 21:18