ActiveRecord:如何将属性值插入自定义validation错误消息?

我有一个validates_presence_of :pricevalidation,当validation失败时返回"Book version price can't be blank"错误。

 class BookVersion < ActiveRecord::Base attr_accessible :name, :book_id, :instock, :isbn, :price, :famis_price, :famis_number, :weight_in_pounds, :width, :height, :thickness validates_presence_of :price, message: "can't be blank" 

但是,我想将BookVersion的name值添加到validation消息中,如下所示:

如果book_version.name返回“LB”:

Book version LB price can't be blank

所以我想做的事情如下:

 validates_presence_of :price, message: "#{self.name} can't be blank" 

但那就是返回Book version price BookVersion can't be blank ,这不是我想要的

你得到BookVersion的原因是因为此时validation的范围是Class,而不是你要validation的对象。 这就是在ActiveModelvalidation中设置消息的工作原理。 如果你真的想让validation做你想做的事,你可以写下这样的东西:

 validate :presence_of_price private def presence_of_price errors.add(:price, "for #{self.name} can't be blank") if price.blank? end 

一种选择是在模型中进行自己的插值:

 after_validation do |record| record.errors.messages.each do |k, v| v.each do |message| message.gsub!(/@{(?[^}]*))}/, __send__(col)) end end end 

因此,除了Ruby插值( #{...} )和ActiveModelvalidation插值( %{...} )之外,您现在还有第三种插值语法 – @{...}的选择是任意的,但是, IMO,非常适合这种模式。

您可以将它放在ActiveRecord :: Base中,这样就不需要在每个模型中重复它。 当然,这是一种性能成本,所以最好只在需要的地方包含它。

您可能希望查看full_messages方法。

所以你保留你的: validates_presence_of :price, message: "can't be blank"

如果您想显示错误,可以使用Book version #{book_version.name} #{book_version.errors.full_messages.to_sentence}

您可能希望使用符号作为消息( validates_presence_of :price, message: :cant_be_blank ),因此您可以在语言环境文件中将其翻译( activerecord.errors.messages.cant_be_blank