'Rails validation error message not showing

I am trying to add a custom error message for my model validation. Seen below:

validates :cost, numericality: { greater_than_or_equal_to: 0, message: :custom_error }

My en.yml looks like this:

en:
  activerecord:
    errors:
      messages:
        custom_error: "some error translation"

From everything I have read that should work. However, it only works in some cases. If I do the following it seems to work:

a = Item.new
a.valid? 
 # false
a.errors.messages
 # { :cost=>["some error translation"]}

In a rescue block I am catching that error and printing the message as seen here:

def subtract_costs
  item.cost: -10
  item.valid?
  puts "error: #{item.errors.messages}"
  # Above outputs "error: {:cost=>["some error translation"]}"
rescue StandardError => error
  puts error.message
  # Above outputs "Validation failed:"
end

That message is always coming out to Validation failed: . Does anyone know what could be causing the error message to be blank? I do not have any other locals or translations in my project.



Solution 1:[1]

Edit: I see there is another issue here. Your rescue block is a bit confusing. During your rescue block, you've rescued a Rails runtime error, not a Model validation error (unless you've used #save! or #update! which turn a model validation error into a runtime error by raising it). So error in that context is a runtime error that is not designed to carry model validation error verbiage.

So you've created a situation were "it doesn't work" but in that situation it is not supposed to work. This should make it clearer:

def subtract_costs
  item.cost = -10
  item.valid?
  puts "error: #{item.errors.messages}" # outputs "error: {:cost=>["some error translation"]}"
  puts item.errors.class.name
rescue StandardError => error
  puts error.message # outputs "Validation failed:"
  puts error.class.name
end


You're not looking up the EN locale message properly. You'd do it like this:

validates :cost,
          numericality: { greater_than_or_equal_to: 0,
                          message: I18n.t('activerecord.errors.messages.custom_error') }

Now there are ways to avoid even having to set the message on the validator at all, but you need to get the message in the correct place. Here is the correct place/hierarchy in your EN locale file. This is the correct place for your specific message:

en:
  errors:
    messages:
      greater_than_or_equal_to: 'some error translation'

And in general, here are where to put custom validation error messages (and my preferred verbiage).

en:
  errors:
    format: "%{message}"
    messages:
      accepted:                 "The %{attribute} was not accepted; please accept the %{attribute}."
      blank:                    "The provided %{attribute} is blank; please enter a non-blank %{attribute}."
      confirmation:             "The provided %{attribute} does not match the corresponding entry; please re-check this entry against the original."
      empty:                    "The provided %{attribute} is empty; please enter a non-empty %{attribute}."
      equal_to:                 "The provided %{attribute} is incorrect; please enter exactly %{count}."
      even:                     "The provided %{attribute} is odd; please enter an even %{attribute}."
      exclusion:                "The provided %{attribute} is reserved; please enter a different %{attribute}."
      greater_than:             "The provided %{attribute} is too small; please provide a different %{attribute} greater than %{count}."
      greater_than_or_equal_to: "The provided %{attribute} is too small; please provide a different %{attribute} greater than or equal to %{count}."
      inclusion:                "The chosen %{attribute} is not available; please choose an available option." # Rails 4 and prior.
      inclusion_of:             "The chosen %{attribute} is not available; please choose an available option." # Rails 5 and later.
      invalid:                  "The provided %{attribute} is invalid; please enter a valid %{attribute}."
      in_between:               "The provided %{attribute} is outside of the accepted range; please enter a different %{attribute} within the range of %{min} to %{max}."
      less_than:                "The provided %{attribute} is too large; please provide a different %{attribute} less than %{count}."
      less_than_or_equal_to:    "The provided %{attribute} is too large; please provide a different %{attribute} less than or equal to %{count}."
      not_a_number:             "The provided %{attribute} is not numeric; please enter a numeric %{attribute}."
      odd:                      "The provided %{attribute} is even; please enter an odd %{attribute}."
      record_invalid:           "The %{attribute} is invalid. %{errors}"
      spoofed_media_type:       "The provided %{attribute} is invalid (often due to an incorrect file extension); please provide a valid %{attribute}, including an appropriate file extension."
      too_long:                 "The provided %{attribute} contains more than the %{count} available characters; please shorten the entry."
      too_short:                "The provided %{attribute} contains fewer than the %{count} required characters; please lengthen the entry."
      taken:                    "The provided %{attribute} is already taken; please enter a different %{attribute}."
      wrong_length:             "The provided %{attribute} contains the wrong amount of characters; please adjust the entry to exactly %{count} characters."

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1