class BetterValidations::NestedValidator

Public Instance Methods

validate_each(record, attr_name, value) click to toggle source
# File lib/better_validations/nested_validator.rb, line 2
def validate_each(record, attr_name, value)
  return if value.nil?

  validator = value
  return if validator_valid?(validator)

  add_errors(validator, record, attr_name)
end

Protected Instance Methods

add_errors(validator, record, attr_name) click to toggle source
# File lib/better_validations/nested_validator.rb, line 18
def add_errors(validator, record, attr_name)
  # Should copy all errors from nested object to the record
  # in order to emulate active record nested errors.
  # But in case of list should merge errors of all items together.
  details = if validator.is_a?(Enumerable)
              collect_nested_errors_details(validator)
            else
              validator.errors.details
            end

  add_errors_details(details, record, attr_name)
end
add_errors_details(details, record, attr_name) click to toggle source
# File lib/better_validations/nested_validator.rb, line 31
def add_errors_details(details, record, attr_name)
  details.each do |field_name, errors|
    errors.each do |error|
      record.errors.add("#{attr_name}.#{field_name}",
                        error[:error],
                        error.except(:error))
    end
  end
end
collect_nested_errors_details(validators) click to toggle source
# File lib/better_validations/nested_validator.rb, line 41
def collect_nested_errors_details(validators)
  result = {}

  validators.each do |validator|
    validator.errors.details.each do |field_name, errors|
      # Use set to remove duplicates automalically
      result_errors = result[field_name] || Set.new
      result[field_name] = result_errors + errors
    end
  end

  result.transform_values(&:to_a)
end
validator_valid?(validator) click to toggle source
# File lib/better_validations/nested_validator.rb, line 13
def validator_valid?(validator)
  validators = validator.is_a?(Enumerable) ? validator : [validator]
  validators.map(&:valid?).all?
end