Module: EasyFormat

Defined in:
lib/easy_format/date_time.rb,
lib/easy_format/validation.rb,
lib/easy_format/file_system.rb,
lib/easy_format/data_type_helper.rb

Defined Under Namespace

Modules: DateTime, Directory, File, Hash

Class Method Summary collapse

Class Method Details

.deep_diff(base, comparison) ⇒ Object

Deep diff two structures For a hash, returns keys found in both hashes where the values don’t match. If a key exists in the base, but NOT the comparison, it is NOT considered a difference so that it can be a one way comparison. For an array, returns an array with values found in the comparison array but not in the base array.



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/easy_format/data_type_helper.rb', line 116

def deep_diff(base, comparison)
  EasyFormat::Hash.log_deprecation('EasyFormat', __method__)
  if base.nil? # if base is nil, entire comparison object is different
    return comparison.is_a?(Hash) ? comparison.dup : comparison
  end

  case comparison
  when nil
    {}
  when ::Hash
    differing_values = {}
    base = base.dup
    comparison.each do |src_key, src_value|
      difference = deep_diff(base[src_key], src_value)
      differing_values[src_key] = difference unless difference == :no_diff
    end
    differing_values.reject { |_k, v| v.is_a?(::Hash) && v.empty? }
  when ::Array
    difference = comparison - base
    difference.empty? ? :no_diff : difference
  else
    base == comparison ? :no_diff : comparison
  end
end

.deep_diff_by_key(base, comparison, keep_values: false) ⇒ Object

Identifies what keys in the comparison hash are missing from base hash. Optionally keep the values from the comparison hash, otherwise assigns the missing keys a value of :missing_key



99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/easy_format/data_type_helper.rb', line 99

def deep_diff_by_key(base, comparison, keep_values: false)
  EasyFormat::Hash.log_deprecation('EasyFormat', __method__)
  missing_keys = {}
  if comparison.is_a?(::Hash)
    compared_keys = base.is_a?(::Hash) ? comparison.keys - base.keys : comparison.keys # Determine what keys the comparison has that the base doesn't
    compared_keys.each { |k| missing_keys[k] = keep_values ? comparison[k] : :missing_key } # Save the missing keys
    comparison.each do |k, v|
      missing_keys[k] = deep_diff_by_key(base[k], v, keep_values: keep_values) if v.is_a?(::Hash) # Recurse to find more missing keys if the hash goes deeper
    end
  end
  missing_keys.reject { |_k, v| v.is_a?(::Hash) && v.empty? } # Remove any empty hashes as there were no missing keys in them
end

.deep_merge(base, override, boolean_or: false, left_outer_join_depth: 0) ⇒ Object

Deep merge two structures

boolean_or: use a boolean || operator on the base and override if they are not a Hash or Array
Left outer join: Only merge keys that already exist in the base


68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/easy_format/data_type_helper.rb', line 68

def deep_merge(base, override, boolean_or: false, left_outer_join_depth: 0)
  EasyFormat::Hash.log_deprecation('EasyFormat', __method__)
  left_outer_join_depth -= 1 # decrement left_outer_join_depth for recursion
  if base.nil?
    return nil if left_outer_join_depth >= 0
    return override.is_a?(Hash) ? override.dup : override
  end

  case override
  when nil
    base = base.dup if base.is_a?(Hash) # duplicate hash to avoid modification by reference issues
    base # if override doesn't exist, simply return the existing value
  when ::Hash
    base = base.dup
    override.each do |src_key, src_value|
      next if base[src_key].nil? && left_outer_join_depth >= 0 # if this is a left outer join and the key does not exist in the base, skip it
      base[src_key] = base[src_key] ? deep_merge(base[src_key], src_value, boolean_or: boolean_or, left_outer_join_depth: left_outer_join_depth) : src_value # Recurse if both are Hash
    end
    base
  when ::Array
    base |= override
    base
  when ::String, ::Integer, ::Time, ::TrueClass, ::FalseClass
    boolean_or ? base || override : override
  else
    throw "Implementation for deep merge of type #{override.class} is missing."
  end
end

.deep_reject(hash, &block) ⇒ Object

Reject hash keys however deep they are. Provide a block and if it evaluates to true for a given key/value pair, it will be rejected.



142
143
144
145
146
147
148
# File 'lib/easy_format/data_type_helper.rb', line 142

def deep_reject(hash, &block)
  EasyFormat::Hash.log_deprecation('EasyFormat', __method__)
  hash.each_with_object({}) do |(k, v), h|
    next if yield(k, v) # reject the current key/value pair by skipping it if the block given evaluates to true
    h[k] = v.is_a?(::Hash) ? deep_reject(v, &block) : v # recursively go up the hash tree or keep the value if it's not a hash.
  end
end

.deep_reject_by_hash(base, comparison) ⇒ Object

Deep diff two Hashes Remove any keys in the first hash also contained in the second hash If a key exists in the base, but NOT the comparison, it is kept.



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/easy_format/data_type_helper.rb', line 153

def deep_reject_by_hash(base, comparison)
  EasyFormat::Hash.log_deprecation('EasyFormat', __method__)
  return nil if base.nil?

  case comparison
  when ::Hash
    return base unless base.is_a?(::Hash) # if base is not a hash but the comparison is, return the base
    base = base.dup
    comparison.each do |src_key, src_value|
      base[src_key] = deep_reject_by_hash(base[src_key], src_value) # recurse to the leaf
      base[src_key] = nil if base[src_key].is_a?(::Hash) && base[src_key].empty? # set leaves to nil if they are empty hashes
    end
    base.reject { |_k, v| v.nil? } # reject any leaves that were set to nil
  else # rubocop:disable Style/EmptyElse - for clarity
    nil # drop the value if we have reached a leaf in the comparison hash
  end
end

.reject_keys_with_nil_values(base) ⇒ Object



171
172
173
174
# File 'lib/easy_format/data_type_helper.rb', line 171

def reject_keys_with_nil_values(base)
  EasyFormat::Hash.log_deprecation('EasyFormat', __method__)
  deep_reject(base) { |_k, v| v.nil? }
end

.validate_parameters(method, method_binding, optional_parameters = []) ⇒ Object

Optional parameters should be an array of symbols or strings rubocop:disable Security/Eval



6
7
8
9
10
11
12
13
# File 'lib/easy_format/validation.rb', line 6

def validate_parameters(method, method_binding, optional_parameters = [])
  method.parameters.each do |parameter|
    parameter_name = parameter.last.to_s
    next if optional_parameters.any? { |o| o.to_s.casecmp(parameter_name) == 0 }
    parameter_value = eval(parameter_name, method_binding)
    raise "#{parameter_name} is a required parameter for #{caller[2][/`.*'/][1..-2]}!" if parameter_value.nil? || (parameter_value.respond_to?(:empty?) && parameter_value.empty?)
  end
end