Pundit gem. Is there way to show record's specific attribute values over yml file?

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}!'

контроллер:

#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}!

какие-либо предложения? Спасибо

2 ответа

Решение

Модуль I18n не может знать, что post.title относится к @post.title, Rails делает некоторую магию с помощниками, но эта магия не распространяется на Pundit.

Вот как документы Pundit предлагают настроить ваши сообщения об ошибках:

Создание пользовательских сообщений об ошибках

NotAuthorizedErrorпредоставить информацию о том, что запрос (например, :create?) какая запись (например, экземпляр Post) и какую политику (например, экземпляр PostPolicy) вызвало ошибку.

Один из способов использовать эти query, record, а также policy свойства, чтобы связать их с I18n генерировать сообщения об ошибках. Вот как вы можете сделать это.

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!'

Конечно, это всего лишь пример. Pundit не зависит от того, как вы реализуете свои сообщения об ошибках.

Из этой информации мы можем экстраполировать что-то вроде следующего:

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

А потом, в ваших местах:

en:
  pundit:
    default: You cannot perform this action.
    post_policy:
      share?: You cannot share post %{title}!

У меня нет приложения с Pundit передо мной, поэтому я не могу проверить это; скорее всего, вам нужно будет немного уловить это.

Проблема в том, что одинарные (') кавычки не допускают интерполяции строк только двойные (") кавычки

Взято из программирования Ruby

Строки в двойных кавычках (...) могут подставлять значение любого выражения Ruby в строку, используя последовательность #{ expr }. Если выражение является просто глобальной переменной, переменной класса или переменной экземпляра, вы можете опустить фигурные скобки.

Другие вопросы по тегам