views:

386

answers:

4

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.

+1  A: 

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
zetetic
yeah...should have named my column names better to avoid all this mess
Omnipresent
A: 

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
Alex Reisner
but this will show the field name in the error message. I want to move away from that. how can your code be incorporated with the custom messages I have
Omnipresent
I encourage you to look into modifying how Rails renders field error messages (maybe ask another question about how to not prepend the humanized field name to AR error messages). Adding all errors to base is not a great design. Don't replace your car's engine because you don't like the color!
Alex Reisner
A: 

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

Omnipresent
Hey, this is much better!
zetetic
A: 
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
Eric Hill