Module: Rucursive::CoreExt::Object

Defined in:
lib/rucursive/core_ext.rb

Instance Method Summary collapse

Instance Method Details

#compound?Boolean

Returns:

  • (Boolean)

4
5
6
# File 'lib/rucursive/core_ext.rb', line 4

def compound?
  is_a?(Array) || is_a?(Hash)
end

#recurse(&block) ⇒ Object

Recursively traverse a compound data structure and call a supplied block on each value or key/value pair, allowing it to modify the returned data structure as it goes. It does NOT modify the existing data structure.

Required arguments: A block that is called on each element of the data

structure

Return value: A new data structure including any modifications made by

the supplied block.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/rucursive/core_ext.rb', line 19

def recurse(&block)
  if is_a?(Array)
    map do |o|
      if o.compound?
        o.recurse(&block)
      else
        block.call(o.dup) if block.arity == 1
        block.call(nil, o.dup) if block.arity == 2
        block.call(nil, o.dup, :array) if block.arity == 3
      end
    end
  elsif is_a?(Hash)
    new_hash = {}
    each_pair do |k,v|
      if v.compound?
        result = block.call(k, v.dup.freeze) if block.arity == 2
        result = block.call(k, v.dup.freeze, :hash) if block.arity == 3
        if result.is_a?(Hash)
          new_key = result.keys.first
        elsif result.is_a?(Array)
          new_key = result.first
        else
          new_key = result
        end
        new_hash[new_key] = v.recurse(&block)
      else
        begin
          v_param = v.dup
        rescue
          v_param = v
        end
        result = block.call(k, v_param) if block.arity == 2
        result = block.call(k, v_param, :hash) if block.arity == 3
        if result.is_a?(Hash)
          new_hash.merge! result
        elsif result.is_a?(Array)
          new_hash[result.first] = result.second
        else
          new_hash[result] = v
        end
      end
    end
    new_hash
  else
    self
  end
end

#recurse_keys(&block) ⇒ Object

Just like Object#recurse when called on a Hash, but only passes the keys to the supplied block, rather than the keys and values. Recurses through Arrays looking for Hashes, since Arrays don't really have keys.


100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/rucursive/core_ext.rb', line 100

def recurse_keys(&block)
  if is_a?(Array)
    map do |o|
      if o.compound?
        o.recurse_keys(&block)
      else
        o
      end
    end
  elsif is_a?(Hash)
    new_hash = {}
    keys.each do |k|
      new_key = block.call k
      new_hash[new_key] = self[k]
    end
    new_hash.each_pair do |k,v|
      if v.is_a?(Hash)
        new_hash[k] = v.recurse_keys(&block)
      elsif v.is_a?(Array)
        new_ary = v.map do |o|
          o.is_a?(Hash) ? o.recurse_keys(&block) : o
        end
        new_hash[k] = new_ary
      end
    end
    new_hash
  else
    self
  end
end

#recurse_values(&block) ⇒ Object

Just like Object#recurse when called on a Hash, but only passes the values to the supplied block, rather than the keys and values. Behaves the same as Object#recurse on Arrays.


71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/rucursive/core_ext.rb', line 71

def recurse_values(&block)
  if is_a?(Array)
    map do |o|
      if o.compound?
        o.recurse_values(&block)
      else
        block.call o
      end
    end
  elsif is_a?(Hash)
    new_hash = {}
    each_pair do |k,v|
      if v.compound?
        new_hash[k] = v.recurse_values(&block)
      else
        new_hash[k] = block.call v
      end
    end
    new_hash
  else
    self
  end
end