开发者

Rails 3 custom formatted validation errors?

With this model:

validates_presence_of :email, :message => "We need your email address"

as a rather contrived example. The error comes out as:

Email We need your email address

How can I provide the format myself?

I looked at the source code of ActiveModel::Errors#full_messages and it does this:

def fu开发者_JAVA技巧ll_messages
  full_messages = []

  each do |attribute, messages|
    messages = Array.wrap(messages)
    next if messages.empty?

    if attribute == :base
      messages.each {|m| full_messages << m }
    else
      attr_name = attribute.to_s.gsub('.', '_').humanize
      attr_name = @base.class.human_attribute_name(attribute, :default => attr_name)
      options = { :default => "%{attribute} %{message}", :attribute => attr_name }

      messages.each do |m|
        full_messages << I18n.t(:"errors.format", options.merge(:message => m))
      end
    end
  end

  full_messages
end

Notice the :default format string in the options? So I tried:

validates_presence_of :email, :message => "We need your email address", :default => "something"

But then the error message actually appears as:

Email something

So then I tried including the interpolation string %{message}, thus overriding the %{attribute} %{message} version Rails uses by default. This causes an Exception:

I18n::MissingInterpolationArgument in SubscriptionsController#create

missing interpolation argument in "%{message}" ({:model=>"Subscription", :attribute=>"Email", :value=>""} given

Yet if I use the interpolation string %{attribute}, it doesn't error, it just spits out the humanized attribute name twice.

Anyone got any experience with this? I could always have the attribute name first, but quite often we need some other string (marketing guys always make things more complicated!).


Errors on :base are not specific to any attribute, so the humanized attribute name is not appended to the message. This allows us to add error messages about email, but not attach them to the email attribute, and get the intended result:

class User < ActiveRecord::Base
  validate :email_with_custom_message
  ...
  private

  def email_with_custom_message
    errors.add(:base, "We need your email address") if
      email.blank?
  end
end


Using internationalization for this is probably your best bet. Take a look at

http://guides.rubyonrails.org/i18n.html#translations-for-active-record-models

Particularly this section:

5.1.2 Error Message Interpolation

The translated model name, translated attribute name, and value are always available for interpolation.

So, for example, instead of the default error message "can not be blank" you could use the attribute name like this : "Please fill in your %{attribute}"

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜