custom error message for valid numericality of in rails
I wanted to have custom error messages for my field names. I stumbled upon another SO question
So I added something like this:
class Product < ActiveRecord::Base
validate do |prod|
prod.errors.add_to_base("Product price can't be blank") if prod.prod_price.blank?
end
end
But I also want to check the numericality of prod_price. If I just add
validate_numericality_of :prod_price
and product price is empty then both the error messages show up (empty and is not a number).
How can I just have 'is not a number' error message show up only when product price is NOT empty?
I tried doing
class Product < ActiveRecord::Base
validate do |prod|
prod.errors.add_to_base("Product price can't be blank") if prod.prod_price.blank?
if !prod.prod_price.blank?
prod.errors.add_to_base("Product price must be a number") if prod.prod_price.<whatdo i put here>
end
end
end
Also, How can I have a custom message for 'is not 开发者_如何学编程a number'. I want to hide showing my column name to the user.
The currently accepted answer works, but here's a data driven way to do it using Rails' i18n:
Adding allow_blank: true
to validates_numericality_of
will take care of the empty problem.
Then you can use i18n to automatically translate attribute names for you (docs here).
For prod_price
you'd just add this to en.yml
:
en:
activerecord:
attributes:
product:
prod_price: "Product price"
Now for the must be a number part, we can use i18n again. From the docs:
Active Record validation error messages can also be translated easily. Active Record gives you a couple of namespaces where you can place your message translations in order to provide different messages and translation for certain models, attributes, and/or validations.
There's a handy table of those namespaces here, where you can see that the message for a numericality validataion is not_a_number
.
So now we can add that to en.yml
thus:
en:
activerecord:
errors:
models:
product:
attributes:
prod_price:
not_a_number: "must be a number"
Now when the validation fails it'll concatenate the two, to give you: Product price must be a number.
You can have custom messages without writing your own validate method. Just add :message
:
validates_presence_of :prod_price, :message => "Product price can't be blank"
If you want to skip the numericality validation when prod_price
is not present, add :allow_nil:
validates_presence_of :prod_price, :message => "Product price can't be blank"
validates_numericality_of :prod_price, :allow_nil => true
Then the numericality check will not run when prod_price
is missing.
EDIT:
Wait, you don't want the field name to show up in the error message, do you? I missed that. So you'll need the custom validation after all.
EDIT #2:
Ok how about this then:
protected
def validate
if prod_price.blank?
errors.add "Product price can't be blank"
else
begin
Integer(attributes_before_type_cast["prod_price"])
rescue ArgumentError
errors.add "Product price must be a number"
end
end
end
For a lot of reasons, unless you need to do something unusual, you should be attaching error messages to specific fields (it's easier to do unit tests, easier to modify errors later, you can display markers next to invalid fields if you want, etc). I think what you want to do can be accomplished with this:
class Product < ActiveRecord::Base
validates_numericality_of :name, :if => lambda{ |obj| obj.prod_price? }
validates_presence_of :name
end
I took this approach from the other SO question
class User < ActiveRecord::Base
HUMANIZED_ATTRIBUTES = {
:email => "E-mail address"
}
def self.human_attribute_name(attr)
HUMANIZED_ATTRIBUTES[attr.to_sym] || super
end
end
this way I dont have to write custom message for each field. I just change the fild name presented to the user
if prod.prod_price.blank?
prod.errors.add_to_base("Product price can't be blank")
elsif prod.prod_price.match(/[^\d]/)
prod.errors.add_to_base("Product price must be a number")
end
精彩评论