Fully custom validation error message with Rails

2018-12-31 14:25发布

Using Rails I'm trying to get an error message like "The song field can't be empty" on save. Doing the following:

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

... only displays "Song Rep XYW can't be empty", which is not good because the title of the field is not user friendly. How can I change the title of the field itself ? I could change the actual name of the field in the database, but I have multiple "song" fields and I do need to have specific field names.

I don't want to hack around rails' validation process and I feel there should be a way of fixing that.

17条回答
临风纵饮
2楼-- · 2018-12-31 15:03

One solution might be to change the i18n default error format:

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

Default is format: %{attribute} %{message}

查看更多
零度萤火
3楼-- · 2018-12-31 15:08

Try this.

class User < ActiveRecord::Base
  validate do |user|
    user.errors.add_to_base("Country can't be blank") if user.country_iso.blank?
  end
end

I found this here.

Here is another way to do it. What you do is define a human_attribute_name method on the model class. The method is passed the column name as a string and returns the string to use in validation messages.

class User < ActiveRecord::Base

  HUMANIZED_ATTRIBUTES = {
    :email => "E-mail address"
  }

  def self.human_attribute_name(attr)
    HUMANIZED_ATTRIBUTES[attr.to_sym] || super
  end

end

The above code is from here

查看更多
人间绝色
4楼-- · 2018-12-31 15:09

In your view

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

When you want to override the error message without the attribute name, simply prepend the message with ^ like so:

validates :last_name,
  uniqueness: {
    scope: [:first_name, :course_id, :user_id],
    case_sensitive: false,
    message: "^This student has already been registered."
  }
查看更多
爱死公子算了
5楼-- · 2018-12-31 15:10

Just do it the normal way:

validates_presence_of :email, :message => "Email is required."

But display it like this instead

<% if @user.errors.any? %>
  <% @user.errors.messages.each do |message| %>
    <div class="message"><%= message.last.last.html_safe %></div>
  <% end %>
<% end %>

Returns

"Email is required."

The localization method is definitely the "proper" way to do this, but if you're doing a little, non-global project and want to just get going fast - this is definitely easier than file hopping.

I like it for the ability to put the field name somewhere other than the beginning of the string:

validates_uniqueness_of :email, :message => "There is already an account with that email."
查看更多
其实,你不懂
6楼-- · 2018-12-31 15:12

Rails3 Code with fully localized messages:

In the model user.rb define the validation

validates :email, :presence => true

In config/locales/en.yml

en:  
  activerecord:
    models: 
      user: "Customer"
    attributes:
      user:
        email: "Email address"
    errors:
      models:
        user:
          attributes:
            email:
              blank: "cannot be empty"
查看更多
萌妹纸的霸气范
7楼-- · 2018-12-31 15:12

Related to the accepted answer and another answer down the list:

I'm confirming that nanamkim's fork of custom-err-msg works with Rails 5, and with the locale setup.

You just need to start the locale message with a caret and it shouldn't display the attribute name in the message.

A model defined as:

class Item < ApplicationRecord
  validates :name, presence: true
end

with the following en.yml:

en:
  activerecord:
    errors:
      models:
        item:
          attributes:
            name:
              blank: "^You can't create an item without a name."

item.errors.full_messages will display:

You can't create an item without a name

instead of the usual Name You can't create an item without a name

查看更多
登录 后发表回答