module Validation module ClassMethods CAP_NUMBER_REGEX = Regexp.new('^-{0,1}\d*\.{0,1}\d+$') CAP_INTEGER_REGEX = Regexp.new('\-{0,1}A[+-]?\d+\Z') # @example # validates_inclusion_of( :status, :in => VALID_STATUSES ) def validates_inclusion_of(*attributes) options = { message: 'is not in the required range' }.merge!(attributes.extract_options!) validates_each(*attributes) do |object, attribute, value| next if value.nil? && options[:allow_nil] unless options[:in].include?(value) object.errors[attribute] << options[:message] end end end # Will validate all members of a collection are found in a given collection. # @example # validates_inclusion_of_members_of( :categories, :in => VALID_CATEGORIES ) def validates_inclusion_of_members_of(*attributes) options = { message: 'contains members that are not valid' }.merge!(attributes.extract_options!) validates_each(*attributes) do |object, attribute, collection| next if ( collection.nil? && options[:allow_nil]) || ( collection.empty? && options[:allow_empty]) unless collection.all? { |member| options[:in].include?(member) } object.errors[attribute] << options[:message] end end end def validates_length_of_members_of(*attributes) options = { message: 'contains members with incorrect length' }.merge!(attributes.extract_options!) validates_each(*attributes) do |object, attribute, collection| next if ( collection.nil? && options[:allow_nil]) || ( collection.empty? && options[:allow_empty]) unless options[:minimum] && collection.length >= options[:minimum] object.errors[attribute] << options[:message] end end end def validates_validity_of(*attributes) options = { message: 'is not valid' }.merge!(attributes.extract_options!) validates_each(*attributes) do |object, attribute, value| next if value.nil? && options[:allow_nil] unless value && value.valid? object.errors[attribute] << options[:message] end end end def validates_collection_of(*attributes) options = { message: 'contains an invalid element' }.merge!(attributes.extract_options!) validates_each(*attributes) do |object, attribute, collection| next if ( collection.nil? && options[:allow_nil]) || ( collection.empty? && options[:allow_empty]) unless collection.all? { |element| element.valid? } object.errors[attribute] << options[:message] end end end def validates_dependency_of(*attributes) options = { message: 'is dependent on :attribute being defined' }.merge!(attributes.extract_options!) validates_each(*attributes) do |object, attribute, value| next if value.blank? contingent_on_attribute = object.send(options[:on]) contingent_on_attribute_value = options[:with_value] if contingent_on_attribute.nil? || !contingent_on_attribute_value.nil? && contingent_on_attribute_value != contingent_on_attribute object.errors[attribute] << options[:message].gsub(/:attribute/, options[:on].to_s) end end end def validates_conditional_presence_of(*attributes) options = { message: 'is not defined but is required by :contingent_attribute' }.merge!(attributes.extract_options!) validates_each(*attributes) do |object, attribute, value| contingent_attribute_value = object.send(options[:when]) required_contingent_attribute_value = options[:is] next if contingent_attribute_value.nil? || contingent_attribute_value != required_contingent_attribute_value && !options[:is].blank? if value.blank? object.errors[attribute] << options[:message].gsub(/:contingent_attribute/, options[:whenn].to_s) end end end def validates_numericality_of(*attributes) options = { message: 'is not a number or does not meet a conditional requirement', }.merge!(attributes.extract_options!) re = options[:only_integer] ? CAP_INTEGER_REGEX : CAP_NUMBER_REGEX validates_each(*attributes) do |object, attribute, value| next if value.nil? && options[:allow_nil] unless ( value.to_s =~ re) && ( options[:greater_than].nil? || value && value > options[:greater_than]) && ( options[:greater_than_or_equal].nil? || value && value >= options[:greater_than_or_equal]) object.errors[attribute] << options[:message] end end end def validates_responsiveness_of(*attributes) options = { message: 'does not respond to the given method' }.merge!(attributes.extract_options!) validates_each(*attributes) do |object, attribute, _value| next if collection.nil? && options[:allow_nil] unless options[:to].all? { |method_name| object.respond_to?(method_name) } object.errors[attribute] << options [:message] end end end def validates_equality_of_first_and_last(*attributes) options = { message: 'does not have equal first and last elements' }.merge!(attributes.extract_options!) validates_each(*attributes) do |object, attribute, collection| next if collection.nil? && options[:allow_nil] unless collection.first == collection.last object.errors[attribute] << options[:message] end end end end end