I have two models 'Person' and 'Group' which use Rails' polymorphism to both be of type 'Entity'.
When posting to Entity#update, I do an Entity.find() and receive back either a Person or Group object. Pundit then takes this to authorize against either PersonPolicy or GroupPolicy, but not EntityPolicy.
Is Pundit purposefully matching against object type instead of controller type? It was my impression based on the examples of having 'index?', 'show?', etc. that Pundit would use the name of the controller, not the name of the model, when authorizing.
IIRC, Pundit's authorize helper infers policy names based on the controller name, not the model you pass it. If you want to use a different policy based on the model you have, you can use policy helper as documented in the README near the end of the "Polices" section: https://github.com/elabs/pundit#policies
user = User.first # any user
widget = Widget.first
widget_policy = Pundit::PolicyFinder.new(user, Widget) # => instance of WidgetPolicy
widget_policy = Pundit.policy(user, Widget) # identical to previous line
widget_policy.show?
policy(user, widget).show? # identical to previous line
authorize most definitely does not find policies based on the controller. The code for the finder is quite readable, and shows that the policy inference is based around the record being authorized, not the controller.
The method on the policy to use for authorization is based on the controller action by default.
@cthielen the solution you're after is based on this line. Simply define a policy_class method on your Entity class like this
def policy_class
EntityPolicy
end
Yes, by default we infer it based on the class name, which in your case is Person, so PersonPolicy. Entity is just a superclass, it has no effect on the inference. @deefour's solution is what you should do if you want it to always use EntityPolicy.
All that being said: don't use STI. STI is awful. It should be deprecated and removed from ActiveRecord.
@deefour @jnicklas Thanks for the clarification. TIL!
Thanks!
Most helpful comment
authorizemost definitely does not find policies based on the controller. The code for the finder is quite readable, and shows that the policy inference is based around the record being authorized, not the controller.The method on the policy to use for authorization is based on the controller action by default.
@cthielen the solution you're after is based on this line. Simply define a
policy_classmethod on yourEntityclass like this