Class: BetterValidations::ValidatorsList

Inherits:
Object
  • Object
show all
Defined in:
lib/better_validations/validators_list.rb

Overview

Provides a way to merge multiple validators in order to get merged errors from all of them. Usage:

validator = validator_one.merge(validator_two, validator_three)
validator.valid?
validator.errors.detailed_messages

Instance Method Summary collapse

Constructor Details

#initialize(*validators) ⇒ ValidatorsList

Returns a new instance of ValidatorsList.



9
10
11
# File 'lib/better_validations/validators_list.rb', line 9

def initialize(*validators)
  @validators = validators
end

Instance Method Details

#deep_merge(hash_one, hash_two) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/better_validations/validators_list.rb', line 39

def deep_merge(hash_one, hash_two)
  # Use a standard method to do a deep merge by specify
  # a values concatination logic
  hash_one.deep_merge(hash_two) do |_key, this_value, other_value|
    # Arrays has a complex logic - they must be merged
    if this_value.is_a?(Array) || other_value.is_a?(Array)
      merge_arrays(this_value, other_value)
    else
      this_value.nil? ? other_value : this_value
    end
  end
end

#detailed_messages(wrap_attributes_to: nil) ⇒ Object



29
30
31
32
33
34
35
36
37
# File 'lib/better_validations/validators_list.rb', line 29

def detailed_messages(wrap_attributes_to: nil)
  (@invalid_validators || []).reduce({}) do |all_messages, validator|
    messages = validator.errors.detailed_messages(
      wrap_attributes_to: wrap_attributes_to
    )

    deep_merge(all_messages, messages)
  end
end

#errorsObject



13
14
15
# File 'lib/better_validations/validators_list.rb', line 13

def errors
  self
end

#invalid?Boolean

Returns:

  • (Boolean)


25
26
27
# File 'lib/better_validations/validators_list.rb', line 25

def invalid?
  !valid?
end

#merge_arrays(one, two) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/better_validations/validators_list.rb', line 52

def merge_arrays(one, two)
  # If we have arrays of strings it means that we have arrays of errors:
  # ['Error 1', 'Error 2'] and ['Error 3', 'Error 4']. In this case we
  # just concat arrays and get unique values.
  if one.first.is_a?(String) || two.first.is_a?(String)
    return (one + two).uniq
  end

  # Other type of arrays is an array of hashes. Each hash is
  # an object with attributes:
  # [{ id: 1, client_id: 2, key: "String", another_key: {} }]
  merge_arrays_with_errors(one, two)
end

#merge_arrays_with_errors(one, two) ⇒ Object

Merges arrays of hashes to a single array by deep merging items with the same “:id” and “:client_id”.



68
69
70
71
72
# File 'lib/better_validations/validators_list.rb', line 68

def merge_arrays_with_errors(one, two)
  all = one + two
  all = merge_hashes_by_key(all, :id)
  merge_hashes_by_key(all, :client_id)
end

#merge_hashes_by_key(hashes, key) ⇒ Object



74
75
76
77
78
79
80
81
82
83
# File 'lib/better_validations/validators_list.rb', line 74

def merge_hashes_by_key(hashes, key)
  hashes_by_id = hashes.group_by { |hash| hash[key] }
  hashes_by_id.map do |id, hashes_with_id|
    next hashes_with_id if id.nil?

    # Merge all hashes with the same id to the single hash.
    # Wrap to array in order to save a format (hashes_with_id is a array)
    [hashes_with_id.reduce({}) { |result, hash| deep_merge(result, hash) }]
  end.flatten(1)
end

#valid?Boolean

Returns:

  • (Boolean)


17
18
19
20
21
22
23
# File 'lib/better_validations/validators_list.rb', line 17

def valid?
  if @invalid_validators.nil?
    @invalid_validators = @validators.select(&:invalid?)
  end

  @invalid_validators.blank?
end