Satya's blog - Ruby on Rails validations

Dec 06 2007 18:06 Ruby on Rails validations

We all know how to validates_presence_of in Rails, right? You can also override the error_messages_for in your helper to customize the errors. Just paste in the source from and start hacking. Make sure it's validating the presence of (model)_id, if it's a lookup table column.

Want to make sure a number of lookup table values actually exist? Say you have a number of columns which are drop-downs, whose values come from lookup tables and you're just storing the lookup IDs ((model)_id) in the previous paragraph) in your "main" table. You can do this:

    validates_each :employer, :type_of_injury_code, :cause_code do |r,a,v|
        check_inclusion_in_list r,a,v

    def self.check_inclusion_in_list(record,attrib,value,model=nil)
        if model.nil?
            model=attrib.to_s.titleize.camelize.gsub(" ","").constantize
        unless value.nil?
            rescue ActiveRecord::ActiveRecordError
                record.errors.add attrib, 'must be selected from list'

The validates_each statement is standard rails; it passes the record, attribute, and value to the block. Here, the block calls check_inclusion_in_list. That function gets the model name based on the attribute name like so:
:cause_code.to_s becomes "cause_code",
"cause_code".titleize becomes "Cause code",
"Cause code".camelize becomes "CauseCode",
the gsub gets rid of spaces, and constantize finds a suitable constant, in this case, the model CauseCode. We can drop the titleize and gsub calls, I forget why they're there.

Next, we run find(value) on the model, and if it can't find record with the given id, an exception is raised and caught, and we add to the record's error stack. Note that a nil value causes this validation to succeed -- you must validates_presence_of :cause_code_id separately!

Tag: rails howto