使用Rails我试图得到一个错误消息,如“歌曲字段不能为空”保存。做以下事情:

validates_presence_of :song_rep_xyz, :message => "can't be empty"

... 只显示“Song Rep XYW不能为空”,这是不好的,因为字段的标题不是用户友好的。如何更改字段本身的标题?我可以更改数据库中字段的实际名称,但我有多个“song”字段,我确实需要特定的字段名称。

我不想破坏rails的验证过程,我觉得应该有办法解决这个问题。


当前回答

我建议安装David Easley最初编写的custom_error_message gem(或作为插件)

它可以让你做以下事情:

validates_presence_of :non_friendly_field_name, :message => "^Friendly field name is blank"

其他回答

一个解决方案可能是改变i18n的默认错误格式:

en:
  errors:
    format: "%{message}"

默认格式:%{attribute} %{message}

一个我从未见过任何人提到过的独特方法!

我能够获得我想要的所有定制的唯一方法是使用after_validation回调来允许我操纵错误消息。

允许正常创建验证消息,您不需要尝试在验证助手中更改它。 创建一个after_validation回调,它将在后端到达视图之前替换该验证消息。 在after_validation方法中,你可以对验证消息做任何你想做的事情,就像一个普通的字符串!您甚至可以使用动态值并将它们插入到验证消息中。


#this could be any validation
validates_presence_of :song_rep_xyz, :message => "whatever you want - who cares - we will replace you later"

after_validation :replace_validation_message

def replace_validation_message
    custom_value = #any value you would like
    errors.messages[:name_of_the_attribute] = ["^This is the replacement message where 
    you can now add your own dynamic values!!! #{custom_value}"]
end

after_validation方法的作用域将比内置的rails验证帮助器大得多,因此您将能够访问正在验证的对象,就像您尝试使用object.file_name一样。这在您试图调用它的验证助手中不起作用。

注意:我们在验证的开始使用^来去掉属性名,就像@Rystraum引用这个gem时指出的那样

在你看来

object.errors.each do |attr,msg|
  if msg.is_a? String
    if attr == :base
      content_tag :li, msg
    elsif msg[0] == "^"
      content_tag :li, msg[1..-1]
    else
      content_tag :li, "#{object.class.human_attribute_name(attr)} #{msg}"
    end
  end
end

当你想重写错误消息而不带属性名时,只需在消息前面加上^ like:

validates :last_name,
  uniqueness: {
    scope: [:first_name, :course_id, :user_id],
    case_sensitive: false,
    message: "^This student has already been registered."
  }

我建议安装David Easley最初编写的custom_error_message gem(或作为插件)

它可以让你做以下事情:

validates_presence_of :non_friendly_field_name, :message => "^Friendly field name is blank"

如果你想把它们都列在一个漂亮的列表中,但又不想使用不友好的名字,你可以这样做……

object.errors.each do |attr,message|
  puts "<li>"+message+"</li>"
end