Dan L
Dan L

Reputation: 4439

Rails 4 validation message: removes "_id" from message

# model.rb
validates :employee_id, presence: true, uniqueness: true

When left empty, the error message says "Employee can't be blank" when I want it to say "Employee ID can't be blank".

I resolved this by:

# model.rb
validates :employee_id, presence: { message: " ID can't be blank" }, uniqueness: true

which outputs "Employee ID can' be blank".

However, this isn't a really good solution IMO. I would like some means of customizing the entire message, including the attribute prefix.

Is there a simple way to do this?

Upvotes: 4

Views: 2911

Answers (3)

Vlad Hilko
Vlad Hilko

Reputation: 1244

You can override human_attribute_name and always send default value with id

class MyModel
  def self.human_attribute_name(attribute, options = {})
    super(attribute, { default: attribute.to_s.humanize(keep_id_suffix: true) } )
  end
end

Upvotes: 0

gregb
gregb

Reputation: 782

You can write a custom validation. By doing it that way, you get to define the error message inside the validation method.

The relevant section from Rails Guides is here: Performing Custom Validations

Something like:

Class Paystub

  validate :employee_id_is_not_blank

  def employee_id_is_not_blank
    errors[:base] << "Employee must be a part of the record.") if id.blank?
  end
end

p = Paystub.create
p.errors.full_messages #=> ["Employee must be a part of the record."]

Section 7.4 in the Rails Guides specified using errors[:base]. Error messages shoveled into :base don't require an attribute to be tied to them.

Update: This is not the right answer. See @meagars answer above.

Upvotes: -1

user229044
user229044

Reputation: 239382

There are several "correct" ways to go about this, but you definitely shouldn't do it via the validation itself, or by defining your own validation method.

On a model-by-model level, this is controlled by the class-level human_attribute_name method.

If you want your model's employee_id field to be a special case where the _id postfix isn't truncated, define that special case by overridding human_attribute_name:

class MyModel

  validates :employee_id, presence: true

  def self.human_attribute_name(attr, options = {})
    attr == :employee_id ? 'Employee ID' : super
  end
end

In broader terms, you can redefine human_attribute_name on ActiveRecord::Base to override handling of all _id attributes, but I doubt you want to do this. Generally, it's a good thing that Rails drops the _id postfix.

The second (and probably better) mechanism is to simply rely on localization. ActiveRecord ties into your locale YAML files for just about everything. If you want your employee_id field to humanize to Employee ID regardless of language, you'll need to edit your YAML files.

# config/locales/en.yml

en:
  activerecord:
    attributes:
      employee_id: "Employee ID"

Upvotes: 8

Related Questions