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

时间:2014-02-04 20:09:27

标签: ruby-on-rails activerecord

我有validates_presence_of :price验证,验证失败时返回"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值添加到验证消息中,如下所示:

如果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,这不是我想要的

3 个答案:

答案 0 :(得分:3)

您获得BookVersion的原因是因为此时验证的范围是Class,而不是您要验证的对象。这就是在ActiveModel验证中设置消息的工作原理。如果你真的希望验证能够做你想做的事情,你可以编写类似的东西:

validate :presence_of_price

private

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

答案 1 :(得分:0)

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

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

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

您可以将它放在ActiveRecord :: Base中,这样您就不需要在每个模型中重复它。当然,这会带来性能成本,所以最好只在需要时加入它。

答案 2 :(得分:0)

您可能希望查看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)中翻译它