All talk but no code...

Pundit and controller based authorization

If we have an Order class, pundit gem will figure out to use the OrderPolicy for authorization. But what if we have multiple domains using the same item?

For example an online auction site, there will be a Seller::OrdersController and a Buyer::OrdersController. They will manage the two sides of the same order. The idea is that, buyer should be allowed to only update via Buyer::OrdersController but not Seller::OrdersController. And vice versa for seller. Obviously we would want to have two sets of policies.

However in Pundit namespaced policy require us to call authorze [:seller, item], in order for it to use the Seller::ItemPolicy. This can become repetitive.

For me, there is less room for error if we have a 1:1 relationship between controller and policy, and a controller can be assumed to use the same policy. So I patched authorize call so policy can be set on the controller level.

Solution

Put the following under ApplicationController as private methods.

In your controller, you can then do this to set policy:

This means all actions under this controller will use Seller::OrderPolicy by default when you call authorize.

If we want to override this, we can also pass in policy_class in authorize:

Note that I made some changes to authorize's method signature: query is a keyword argument now. It also returns the record object (as planned for its 1.2 release).