raiseArgumentError, "You need to supply at least one attribute"if attributes.empty? raiseArgumentError, "You need to supply at least one validation"if validations.empty?
defaults[:attributes] = attributes
validations.each do |key, options| nextunless options key = "#{key.to_s.camelize}Validator"
begin validator = key.include?('::') ? key.constantize : const_get(key) rescueNameError raiseArgumentError, "Unknown validator: '#{key}'" end
=> validates_with(validator, defaults.merge(_parse_validates_options(options))) end
args.each do |klass| validator = klass.new(options, &block)
if validator.respond_to?(:attributes) && !validator.attributes.empty? validator.attributes.each do |attribute| _validators[attribute.to_sym] << validator end else _validators[nil] << validator end
if args.all? { |arg| arg.is_a?(Symbol) } options.each_key do |k| unlessVALID_OPTIONS_FOR_VALIDATE.include?(k) raiseArgumentError.new("Unknown key: #{k.inspect}. Valid keys are: #{VALID_OPTIONS_FOR_VALIDATE.map(&:inspect).join(', ')}. Perhaps you meant to call `validates` instead of `validate`?") end end end
if options.key?(:on) options = options.dup options[:if] = Array(options[:if]) options[:if].unshift ->(o) { Array(options[:on]).include?(o.validation_context) } end
# Performs validation on the supplied record. By default this will call # +validates_each+ to determine validity therefore subclasses should # override +validates_each+ with validation logic. defvalidate(record) attributes.each do |attribute| value = record.read_attribute_for_validation(attribute) nextif (value.nil? && options[:allow_nil]) || (value.blank? && options[:allow_blank]) => validate_each(record, attribute, value) end
classTitleValidator < ActiveModel::EachValidator defvalidate_each(record, attribute, value) record.errors.add attribute, 'must be Mr., Mrs., or Dr.'unless%w(Mr. Mrs. Dr.).include?(value) end end