i'am playing with pundit gem. i need to show post's title
in a flash message
#config/locales/pundit.en.yml
en:
pundit:
default: 'You cannot perform this action.'
post_policy:
share?: 'You cannot share post %{post.title}!'
controller:
#posts_controller.rb
def share
@post = Post.find(params[:id])
authorize @post
@post.share
redirect_to @post
end
all i receive is the exact the same string without any errors and substitutions
You cannot share post %{post.title}!
any suggestions? thanks
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 ofPost
), and what policy (e.g. an instance ofPostPolicy
) caused the error to be raised.One way to use these
query
,record
, andpolicy
properties is to connect them withI18n
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.