DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Snippets has posted 5883 posts at DZone. View Full User Profile

Validates_presence_of_at_least_one_field

12.02.2009
| 2491 views |
  • submit to reddit
        Just drop this in lib/some_file_name.rb and require 'some_file_name' in your environment.rb

This allows you to do validations where you need one of two or more fields to be present.  This also accepts arrays ... see comment in code for use example

#good post on how to do stuff like this  http://www.marklunds.com/articles/one/312

module ActiveRecord
  module Validations
    module ClassMethods

      # Use to check for this, that or this was entered... example:
      #  :validates_presence_of_at_least_one_field :last_name, :company_name  - would require either last_name or company_name to be filled in
      #  also works with arrays
      #  :validates_presence_of_at_least_one_field :email, [:name, :address, :city, :state] - would require email or a mailing type address
      def validates_presence_of_at_least_one_field(*attr_names)
        msg = attr_names.collect {|a| a.is_a?(Array) ? " ( #{a.join(", ")} ) " : a.to_s}.join(", ") +
                    "can't all be blank.  At least one field (set) must be filled in."
        configuration = {
          :on => :save,
          :message => msg }
        configuration.update(attr_names.extract_options!)

        send(validation_method(configuration[:on]), configuration) do |record|
          found = false
          attr_names.each do |a|
            a = [a] unless a.is_a?(Array)
            found = true
            a.each do |attr|
              value = record.respond_to?(attr.to_s) ? record.send(attr.to_s) : record[attr.to_s]
              found = !value.blank?
            end
            break if found
          end
          record.errors.add_to_base(configuration[:message]) unless found
        end
      end

    end
  end
end