module Nuggets::Hash::UnrollMixin
Public Instance Methods
unroll(*value_keys) → anArray
click to toggle source
unroll(*value_keys, sort_by: ...) → anArray
unroll(*value_keys) { |value_hash| ... } → anArray
“Unrolls” a nested hash, so that each path through hash results in a row that is, e.g., suitable for use with CSV.
Note that from the final hash (“value hash”) only the values are used, namely, if value_keys
are given, the values at those keys are returned. If a block is given, the value_hash
is passed to that block for any additional processing or sanitization.
If sort_by
is given, all hashes are passed through that block for sorting before being put into the result array.
Examples:
{ foo: { bar: { a: { x: 1, y: 2 }, b: { x: 0, y: 3 } } } }.unroll #=> [[:foo, :bar, :b, 3, 0], [:foo, :bar, :a, 2, 1]] { foo: { bar: { a: { x: 1, y: 2 }, b: { x: 0, y: 3 } } } }.unroll(sort_by: :to_s) #=> [[:foo, :bar, :a, 1, 2], [:foo, :bar, :b, 0, 3]] { foo: { bar: { a: { x: 1, y: 2 }, b: { x: 0, y: 3 } } } }.unroll { |data| data[:x] = nil; data[:y] *= 2 } #=> [[:foo, :bar, :b, 6, nil], [:foo, :bar, :a, 4, nil]]
# File lib/nuggets/hash/unroll_mixin.rb 57 def unroll(*value_keys, &block) 58 args = value_keys.dup 59 options = value_keys.last.is_a?(::Hash) ? value_keys.pop : {} 60 61 sort_proc = if options.key?(:sort_by) 62 lambda { sort_by(&options[:sort_by]) } 63 elsif options.key?(:sort) 64 options[:sort] == true ? lambda { sort } : lambda { sort(&options[:sort]) } 65 end 66 67 rows = [] 68 69 if values.first.is_a?(self.class) # if any is, then all are 70 (sort_proc ? sort_proc.call : self).each { |key, value| 71 value.unroll(*args, &block).each { |row| rows << [key, *row] } 72 } 73 else 74 block[self] if block 75 76 rows << if value_keys.empty? 77 sort_proc ? sort_proc.call.map { |key, value| value } : values 78 else 79 values_at(*value_keys) 80 end 81 end 82 83 rows 84 end