Class- and Field-Level Custom Validations

This is a simple example I put together for someone asking how this validation stuff works…
In this example, you can see field-level validation:

  • team must be chosen
  • name is required

And you can see a class/base-level validation:

  • at least one method of contact, a phone or an email:

Simple class example that employs some conditional validations and some regular validations:

class Registrant
  include MongoMapper::Document

  # Attributes ::::::::::::::::::::::::::::::::::::::::::::::::::::::
  key :name, String, :required => true
  key :email, String
  key :phone, String
  # Parent Info
  key :parent_name, String
  key :parent_email, String
  key :parent_phone, String
  key :street, String
  key :street2, String
  key :city, String
  key :state, String
  key :postal_code, String

  # Associations :::::::::::::::::::::::::::::::::::::::::::::::::::::
  key :team_id, ObjectId
  belongs_to :team
...
  # Validations :::::::::::::::::::::::::::::::::::::::::::::::::::::
  validate :validate_team_selection
  validate :validate_parent_contact_method
  validates_presence_of :parent_name, :street, :city, :state, :postal_code,
                                    :if => :parent_info_required?

...

  private

  def parent_info_required?
    season.parent_info_required?
  end

  def validate_parent_contact_method
    # one or the other must be provided
    if parent_phone.empty? and parent_email.empty?
      errors.add_to_base("At least one form of contact must be entered for the parent: phone or email" )
    end
  end

  def validate_contact_method
    # one or the other must be provided
    if phone.empty? and email.empty?
      errors.add_to_base("At least one form of contact must be entered: phone or email" )
    end
  end

  def validate_team_selection
    if registration_setup.require_team_at_signup
      if team_id.nil?
        errors.add(:team, "must be selected" )
      end
    end
  end
end

The above will result in always checking the name, the contacts, and the team assignment. It is actually pulled from a slightly more complex context in that a few conditionals exist to further complicate the validation logic. If you need checking only at certain points in the object life cycle, you can look to things like validate_on_create.

In the case of “Parent Info” being required, additional validations take place.

The “name” validation is a standard, out of the box field-level validation due to “:required => true” being added to the MongoMapper key.

Enjoy!