专家 gem。有没有办法通过 yaml 文件显示记录的特定属性值?

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

我正在玩 pundit gem。我需要在闪信

中显示post的title
#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

我收到的都是完全相同的字符串,没有任何错误和替换

You cannot share post %{post.title}!

有什么建议吗?谢谢

问题是单引号 (') 不允许字符串插值,只有双引号 (") 引号

取自Programming Ruby

Double-quoted strings(...) can substitute the value of any Ruby expression into a string using the sequence #{ expr }. If the expression is just a global variable, a class variable, or an instance variable, you can omit the braces.

I18n 模块无法知道 post.title 指的是 @post.title。 Rails 用它的表单助手做了一些这种魔法,但这种魔法并没有扩展到 Pundit。

Pundit 的文档如下 suggest customizing your error messages:

Creating custom error messages

NotAuthorizedErrors 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.

根据这些信息,我们可以推断出如下内容:

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 的应用程序,所以我无法对此进行测试;您可能需要稍微改进一下。