The I18n module has no way of knowing that post.title
refers to @post.title
. Rails does some of that kind of magic with its form helpers, but that magic does not extend to Pundit.
Here's how the Pundit docs suggest customizing your error messages:
Creating custom error messages
NotAuthorizedError
s provide information on what query (e.g.
:create?
), what record (e.g. an instance of Post
), and what policy
(e.g. an instance of PostPolicy
) caused the error to be raised.
One way to use these query
, record
, and policy
properties is to
connect them with I18n
to generate error messages. Here's how you
might go about doing that.
class ApplicationController < ActionController::Base
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
private
def user_not_authorized(exception)
policy_name = exception.policy.class.to_s.underscore
flash[:error] = t "#{policy_name}.#{exception.query}", scope: "pundit", default: :default
redirect_to(request.referrer || root_path)
end
end
en:
pundit:
default: 'You cannot perform this action.'
post_policy:
update?: 'You cannot edit this post!'
create?: 'You cannot create posts!'
Of course, this is just an example. Pundit is agnostic as to how you implement your error messaging.
From that information we could extrapolate something like the following:
private
def user_not_authorized(exception)
policy_name = exception.policy.class.to_s.underscore
interpolations = exception.query == 'share?' ? { title: @post.title } : {}
flash[:error] = t "#{policy_name}.#{exception.query}", scope: "pundit", default: :default, **interpolations
redirect_to(request.referrer || root_path)
end
And then, in your locales:
en:
pundit:
default: You cannot perform this action.
post_policy:
share?: You cannot share post %{title}!
I don't have an app with Pundit in front of me so I can't test this; it's likely you'll need to finesse it a bit.