Module: Rordash::HashUtil

Defined in:
lib/rordash/hash_util.rb

Overview

rubocop:disable Metrics/ModuleLength

Constant Summary collapse

ROOT_PATHS =
%w[. *].freeze

Class Method Summary collapse

Class Method Details

.deep_compact(attrs, each_value_proc: nil) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/rordash/hash_util.rb', line 126

def deep_compact(attrs, each_value_proc: nil)
  result = {}

  dot(attrs, keep_arrays: true) do |k, v|
    value = each_value_proc.respond_to?(:call) ? each_value_proc&.call(k, v) : v.try(:compact)
    next if value.nil?

    set(result, k, value)
  end

  result
end

.deep_key?(obj, key) ⇒ Boolean

Returns:

  • (Boolean)


74
75
76
77
78
79
# File 'lib/rordash/hash_util.rb', line 74

def deep_key?(obj, key)
  return false unless obj.is_a?(::Hash)
  return obj.key?(key) unless key.is_a?(String) && key.include?('.')

  dotted_keys(obj).include?(key)
end

.deep_reject_blank_values(attrs) ⇒ Object



150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/rordash/hash_util.rb', line 150

def deep_reject_blank_values(attrs)
  deep_compact(attrs, each_value_proc: lambda do |_k, v|
    v = v.is_a?(String) ? v.strip : v
    v = v.compact if hash_or_array?(v)
    if v.is_a?(Array)
      v = v.reject do |val|
        val = val.is_a?(String) ? val.strip : val
        val.blank?
      end
    end
    v.blank? ? nil : v
  end)
end

.deep_symbolize_keys(obj) ⇒ Object



164
165
166
167
168
169
# File 'lib/rordash/hash_util.rb', line 164

def deep_symbolize_keys(obj)
  return obj unless hash_or_array?(obj)
  return obj.deep_symbolize_keys if obj.is_a?(::Hash)

  obj.map { |item| item.is_a?(::Hash) ? item.deep_symbolize_keys : item }
end

.digest(obj) ⇒ Object



171
172
173
# File 'lib/rordash/hash_util.rb', line 171

def digest(obj)
  Digest::SHA1.base64digest Marshal.dump(obj)
end

.dot(hash, keep_arrays: true, &block) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/rordash/hash_util.rb', line 59

def dot(hash, keep_arrays: true, &block)
  return Dottie.flatten(hash) unless keep_arrays

  results = {}
  Dottie.flatten(hash, intermediate: true).each do |k, v|
    next if RegexUtil.match?(:dotted_index, k)
    next if v.is_a?(::Hash)

    value = block ? yield(k, v) : v
    results.merge!(k => value)
  end

  results
end

.dotted_keys(obj, keep_arrays: true) ⇒ Object



81
82
83
# File 'lib/rordash/hash_util.rb', line 81

def dotted_keys(obj, keep_arrays: true)
  dot(obj, keep_arrays: keep_arrays).keys
end

.from_string(json_str) ⇒ Object



9
10
11
12
13
# File 'lib/rordash/hash_util.rb', line 9

def from_string(json_str)
  return json_str unless json_str.is_a?(String)

  Oj.load(json_str, symbol_keys: true)
end

.get(obj, path, default: nil) ⇒ Object



27
28
29
30
31
32
33
34
# File 'lib/rordash/hash_util.rb', line 27

def get(obj, path, default: nil)
  return obj if ROOT_PATHS.include?(path)

  value = R_.get(obj, path.to_s)
  return default if value.nil?

  value
end

.get_first_present(obj, dotted_paths) ⇒ Object



36
37
38
39
40
41
42
43
# File 'lib/rordash/hash_util.rb', line 36

def get_first_present(obj, dotted_paths)
  dotted_paths.each do |path|
    value = R_.get(obj, path)
    return value if value.present?
  end

  nil
end

.group_by(obj, key_or_proc) ⇒ Object



49
50
51
52
53
54
55
56
57
# File 'lib/rordash/hash_util.rb', line 49

def group_by(obj, key_or_proc)
  proc = if key_or_proc.is_a?(Proc)
           key_or_proc
         else
           ->(hash) { R_.get(hash, key_or_proc.to_s) }
         end

  R_.group_by(obj, proc)
end

.hash_or_array?(obj) ⇒ Boolean

Returns:

  • (Boolean)


175
176
177
# File 'lib/rordash/hash_util.rb', line 175

def hash_or_array?(obj)
  obj.is_a?(::Hash) || obj.is_a?(Array)
end

.pick(hash, paths, keep_arrays: true) ⇒ Object

rubocop:disable Metrics/MethodLength,Metrics/PerceivedComplexity,Metrics/CyclomaticComplexity,Metrics/AbcSize



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/rordash/hash_util.rb', line 86

def pick(hash, paths, keep_arrays: true)
  all_paths = paths.is_a?(Array) ? paths.map(&:to_s) : [paths.to_s]
  has_deep_paths = all_paths.any? { |path| path.include?('.') }

  results = {}
  dotted_hash = has_deep_paths ? Dottie.flatten(hash, intermediate: true) : hash
  filtered_keys = dotted_hash.keys.select { |path| all_paths.include?(path.to_s) }
  filtered_dotted_hash = dotted_hash.slice(*filtered_keys)

  return filtered_dotted_hash unless has_deep_paths

  if keep_arrays
    filtered_dotted_hash.each_pair { |k, v| Utils::HashUtil.set(results, k, v) }
    return results
  else
    filtered_dotted_hash.each_pair do |dotted_key, val|
      stringify_dotted_key = dotted_key.to_s
      next if all_paths.exclude?(stringify_dotted_key)

      should_reconstruct_array = RegexUtil.match?(:dotted_index, stringify_dotted_key)
      key = should_reconstruct_array ? dotted_key.split('[').first : dotted_key
      value = should_reconstruct_array ? (results[key] || []).push(val) : val

      results.merge!(key => value)
    end
  end

  undot(results)
end

.pretty(obj) ⇒ Object



21
22
23
24
25
# File 'lib/rordash/hash_util.rb', line 21

def pretty(obj)
  return obj unless hash_or_array?(obj)

  JSON.pretty_generate(obj)
end

.reject_blank_values(obj) ⇒ Object



139
140
141
142
143
144
145
146
147
148
# File 'lib/rordash/hash_util.rb', line 139

def reject_blank_values(obj)
  return obj unless hash_or_array?(obj)

  obj.compact.reduce({}) do |memo, (k, v)|
    v = v.is_a?(String) ? v.strip : v
    next memo if !hash_or_array?(v) && v.blank?

    memo.merge(k => v)
  end
end

.set(hash, path, value) ⇒ Object



45
46
47
# File 'lib/rordash/hash_util.rb', line 45

def set(hash, path, value)
  R_.set(hash, path.to_s, value)
end

.to_str(obj) ⇒ Object



15
16
17
18
19
# File 'lib/rordash/hash_util.rb', line 15

def to_str(obj)
  return Oj.dump(obj.deep_stringify_keys) if hash_or_array?(obj)

  obj.to_s
end

.undot(hash, &block) ⇒ Object

rubocop:enable Metrics/MethodLength,Metrics/PerceivedComplexity,Metrics/CyclomaticComplexity,Metrics/AbcSize



117
118
119
120
121
122
123
124
# File 'lib/rordash/hash_util.rb', line 117

def undot(hash, &block)
  results = {}
  Dottie.flatten(hash, { intermediate: false }).each do |k, v|
    value = block ? yield(k, v) : v
    set(results, k, value)
  end
  results
end