ActiveRecord: How to interpolate attribute value to a custom validation errror message?

Deadly 提交于 2019-12-08 06:02:34

问题


I have a validates_presence_of :price validation, which returns a "Book version price can't be blank" error when the validation fails.

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"

However, I want to add the name value of the BookVersion to the validation message like so:

If book_version.name returns "LB":

Book version LB price can't be blank

So I want to do something like:

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

but that is returning Book version price BookVersion can't be blank, which isn't what I want


回答1:


The reason you are getting back BookVersion is because at this point, the validation is scoped to the Class and not the object you are validating. This is just how setting a message in ActiveModel validations works. If you really want the validation to do what you want you could write something like:

validate :presence_of_price

private

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



回答2:


One option is to do your own interpolation in the model:

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

So in addition to Ruby interpolation ( #{...} ) and ActiveModel Validation interpolation ( %{...} ), you now have a third syntax for interpolation--the choice of @{...} is arbitrary but, IMO, fits the pattern nicely.

You can put this in ActiveRecord::Base, so that you don't need to repeat it in each model. There's a performance cost, of course, so it might be better to just include this where needed.




回答3:


You might want to look at the full_messages method.

So you keep your: validates_presence_of :price, message: "can't be blank"

And where you want to display the error, you use something like Book version #{book_version.name} #{book_version.errors.full_messages.to_sentence}

You might want to use a symbol as message (validates_presence_of :price, message: :cant_be_blank) instead, so you can translate it in the locale file (activerecord.errors.messages.cant_be_blank)



来源:https://stackoverflow.com/questions/21562344/activerecord-how-to-interpolate-attribute-value-to-a-custom-validation-errror-m

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!