depth 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +44 -1
- data/lib/depth/actions.rb +11 -3
- data/lib/depth/enumeration/enumerable.rb +18 -18
- data/lib/depth/enumeration/node.rb +4 -0
- data/lib/depth/traverser.rb +2 -2
- data/lib/depth/version.rb +1 -1
- data/spec/depth/actions_spec.rb +25 -0
- data/spec/depth/enumerable_spec.rb +17 -1
- metadata +2 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 12186cff293335e8e867ec9c826644c4b175160c
         | 
| 4 | 
            +
              data.tar.gz: 1de2bcf3603c3838ae27c95f4b3f4cd3d961ee4b
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: a3d24285ec52b1ac2f878ab29a6287c548794a7e0dfd1e50eb6d4d2e916df996434a404690cb83b58a3ccf36961217843c5e647f76ea4d831749b272ba8c6bd7
         | 
| 7 | 
            +
              data.tar.gz: c65350a161b063d0c855a05a58a9bcfe089cf503f9a462f2ec686f00239de91049233f99154216ddcc7813595125a9f9b83c8a4e6f41f0df488ec7ab991d223d
         | 
    
        data/README.md
    CHANGED
    
    | @@ -71,6 +71,10 @@ Routes can be defined as an array of keys or indeces: | |
| 71 71 | 
             
              ]}
         | 
| 72 72 | 
             
              route = ['$and', 1, '$or', 0, '#otherfeed', 'thing']
         | 
| 73 73 | 
             
              Depth::ComplexHash.new(hash).find(route) # => []
         | 
| 74 | 
            +
             | 
| 75 | 
            +
              # Or with a default
         | 
| 76 | 
            +
              Depth::ComplexHash.new(hash).find(%w(not a route), default: 'hello') # => 'hello'
         | 
| 77 | 
            +
             | 
| 74 78 | 
             
            ```
         | 
| 75 79 |  | 
| 76 80 | 
             
            But there's something cool hidden in the `set` message,
         | 
| @@ -106,6 +110,39 @@ an array, no worries, just say so in the route: | |
| 106 110 | 
             
              route = ['$and', 1, '$or', 0, RouteElement.new('#sup', type: :array), 0]
         | 
| 107 111 | 
             
            ```
         | 
| 108 112 |  | 
| 113 | 
            +
            Find can also perform the same magic if you set the keyword
         | 
| 114 | 
            +
            argument `create` to be true. A default value can also be supplied:
         | 
| 115 | 
            +
             | 
| 116 | 
            +
            ```ruby
         | 
| 117 | 
            +
              hash = { '$and' => [
         | 
| 118 | 
            +
                { '#weather' => { 'something' => [], 'thisguy' => 4 } },
         | 
| 119 | 
            +
                { '$or' => [
         | 
| 120 | 
            +
                  { '#otherfeed' => {'thing' => [] } },
         | 
| 121 | 
            +
                ]}
         | 
| 122 | 
            +
              ]}
         | 
| 123 | 
            +
              route = ['$and', 1, '$or', 0, '#sup', 'thisthing']
         | 
| 124 | 
            +
              Depth::ComplexHash.new(hash).find(route, create: true)
         | 
| 125 | 
            +
              puts hash.inspect #=>
         | 
| 126 | 
            +
              # hash = { '$and' => [
         | 
| 127 | 
            +
              #   { '#weather' => { 'something' => [], 'thisguy' => 4 } },
         | 
| 128 | 
            +
              #   { '$or' => [
         | 
| 129 | 
            +
              #     { '#otherfeed' => {'thing' => [] } },
         | 
| 130 | 
            +
              #     { '#sup' => { } },
         | 
| 131 | 
            +
              #   ]}
         | 
| 132 | 
            +
              # ]}
         | 
| 133 | 
            +
             | 
| 134 | 
            +
              # Or if you supply a default value as well
         | 
| 135 | 
            +
              val = Depth::ComplexHash.new(hash).find(route, create: true, default: 'blargle')
         | 
| 136 | 
            +
              puts val #=> 'blargle'
         | 
| 137 | 
            +
              puts hash.inspect #=>
         | 
| 138 | 
            +
              # hash = { '$and' => [
         | 
| 139 | 
            +
              #   { '#weather' => { 'something' => [], 'thisguy' => 4 } },
         | 
| 140 | 
            +
              #   { '$or' => [
         | 
| 141 | 
            +
              #     { '#otherfeed' => {'thing' => [] } },
         | 
| 142 | 
            +
              #     { '#sup' => { 'thisthing' => 'blargle' } },
         | 
| 143 | 
            +
              #   ]}
         | 
| 144 | 
            +
              # ]}
         | 
| 145 | 
            +
            ```
         | 
| 109 146 | 
             
            ### Enumeration
         | 
| 110 147 |  | 
| 111 148 | 
             
            The messages signatures relating to enumeration are:
         | 
| @@ -116,7 +153,7 @@ The messages signatures relating to enumeration are: | |
| 116 153 | 
             
            * `map` = yields `key_or_index`, `fragment` and `parent_type`, returns a new complex hash
         | 
| 117 154 | 
             
            * `map_values` = yields  `fragment`, returns a new complex hash
         | 
| 118 155 | 
             
            * `map_keys` = yields `key_or_index`, returns a new complex hash
         | 
| 119 | 
            -
            * `map!`, `map_keys!` and `map_keys_and_values!`, returns  | 
| 156 | 
            +
            * `map!`, `map_keys!` and `map_keys_and_values!`, returns the base complex hash
         | 
| 120 157 | 
             
            * `reduce(memo)` = yields `memo`, `key` and `fragment`, returns memo
         | 
| 121 158 | 
             
            * `each_with_object(obj)` = yields `key`, `fragment` and `object`, returns object
         | 
| 122 159 |  | 
| @@ -124,6 +161,12 @@ _Fragment refers to a chunk of the original hash_ | |
| 124 161 |  | 
| 125 162 | 
             
            These, perhaps, require a bit more explanation:
         | 
| 126 163 |  | 
| 164 | 
            +
            _NB_ All of these methods yield an argument at the end
         | 
| 165 | 
            +
            which is the route taken to get to this fragment of the hash,
         | 
| 166 | 
            +
            I've not detailed the use of it here because it's rarely necessary but
         | 
| 167 | 
            +
            it's available in case you have some complex map rules that change
         | 
| 168 | 
            +
            based on where you are in the hash.
         | 
| 169 | 
            +
             | 
| 127 170 | 
             
            #### each
         | 
| 128 171 |  | 
| 129 172 | 
             
            The staple, and arguably the most important, of all the enumeration methods,
         | 
    
        data/lib/depth/actions.rb
    CHANGED
    
    | @@ -14,11 +14,19 @@ module Depth | |
| 14 14 | 
             
                  object[route.last.key] = value
         | 
| 15 15 | 
             
                end
         | 
| 16 16 |  | 
| 17 | 
            -
                def find(route)
         | 
| 17 | 
            +
                def find(route, create: false, default: nil)
         | 
| 18 18 | 
             
                  route = RouteElement.convert_route(route)
         | 
| 19 | 
            -
                  route.reduce(Traverser.new(base)) { |t, route_el|
         | 
| 20 | 
            -
                     | 
| 19 | 
            +
                  parent = route[0 ... -1].reduce(Traverser.new(base)) { |t, route_el|
         | 
| 20 | 
            +
                    if create
         | 
| 21 | 
            +
                      t.next_or_create(route_el.key) { route_el.create }
         | 
| 22 | 
            +
                    else
         | 
| 23 | 
            +
                      t.next(route_el.key)
         | 
| 24 | 
            +
                    end
         | 
| 21 25 | 
             
                  }.object
         | 
| 26 | 
            +
                  object = parent ? parent[route.last.key] : nil
         | 
| 27 | 
            +
                  return object unless object.nil?
         | 
| 28 | 
            +
                  return parent[route.last.key] = default if create && default
         | 
| 29 | 
            +
                  default
         | 
| 22 30 | 
             
                end
         | 
| 23 31 |  | 
| 24 32 | 
             
                def alter(route, key: nil, value: nil)
         | 
| @@ -8,9 +8,9 @@ module Depth | |
| 8 8 | 
             
                  #:nocov:
         | 
| 9 9 |  | 
| 10 10 | 
             
                  def each_with_object(object, &block)
         | 
| 11 | 
            -
                    object.tap do | | 
| 12 | 
            -
                      each do |key, fragment|
         | 
| 13 | 
            -
                        block.call(key, fragment,  | 
| 11 | 
            +
                    object.tap do |obj|
         | 
| 12 | 
            +
                      each do |key, fragment, route|
         | 
| 13 | 
            +
                        block.call(key, fragment, obj, route)
         | 
| 14 14 | 
             
                      end
         | 
| 15 15 | 
             
                    end
         | 
| 16 16 | 
             
                  end
         | 
| @@ -18,11 +18,11 @@ module Depth | |
| 18 18 | 
             
                  def select(&block)
         | 
| 19 19 | 
             
                    new_q = self.class.new(base.class.new)
         | 
| 20 20 | 
             
                    routes_to_delete = []
         | 
| 21 | 
            -
                    enumerate do |node|
         | 
| 21 | 
            +
                    enumerate do |node, route|
         | 
| 22 22 | 
             
                      key = node.parent_key
         | 
| 23 23 | 
             
                      existing = new_q.find(node.route)
         | 
| 24 24 | 
             
                      fragment = existing.nil? ? node.fragment : existing
         | 
| 25 | 
            -
                      keep = block.call(key, fragment)
         | 
| 25 | 
            +
                      keep = block.call(key, fragment, route)
         | 
| 26 26 | 
             
                      if keep
         | 
| 27 27 | 
             
                        new_q.alter(node.route, key: key, value: fragment)
         | 
| 28 28 | 
             
                      else
         | 
| @@ -34,12 +34,12 @@ module Depth | |
| 34 34 | 
             
                  end
         | 
| 35 35 |  | 
| 36 36 | 
             
                  def reject(&block)
         | 
| 37 | 
            -
                    select{ |key, fragment| !block.call(key, fragment) }
         | 
| 37 | 
            +
                    select{ |key, fragment, route| !block.call(key, fragment, route) }
         | 
| 38 38 | 
             
                  end
         | 
| 39 39 |  | 
| 40 40 | 
             
                  def reduce(memo, &block)
         | 
| 41 | 
            -
                    each do |key, fragment|
         | 
| 42 | 
            -
                      memo = block.call(memo, key, fragment)
         | 
| 41 | 
            +
                    each do |key, fragment, route|
         | 
| 42 | 
            +
                      memo = block.call(memo, key, fragment, route)
         | 
| 43 43 | 
             
                    end
         | 
| 44 44 | 
             
                    memo
         | 
| 45 45 | 
             
                  end
         | 
| @@ -60,36 +60,36 @@ module Depth | |
| 60 60 | 
             
                  end
         | 
| 61 61 |  | 
| 62 62 | 
             
                  def map_keys(&block)
         | 
| 63 | 
            -
                    map do |key, fragment|
         | 
| 64 | 
            -
                      [block.call(key), fragment]
         | 
| 63 | 
            +
                    map do |key, fragment, route|
         | 
| 64 | 
            +
                      [block.call(key, route), fragment]
         | 
| 65 65 | 
             
                    end
         | 
| 66 66 | 
             
                  end
         | 
| 67 67 |  | 
| 68 68 | 
             
                  def map_values(&block)
         | 
| 69 | 
            -
                    map do |key, fragment,  | 
| 70 | 
            -
                      [key, block.call(fragment)]
         | 
| 69 | 
            +
                    map do |key, fragment, route|
         | 
| 70 | 
            +
                      [key, block.call(fragment, route)]
         | 
| 71 71 | 
             
                    end
         | 
| 72 72 | 
             
                  end
         | 
| 73 73 |  | 
| 74 74 | 
             
                  def map(&block)
         | 
| 75 | 
            -
                    node_map do |node, new_q|
         | 
| 75 | 
            +
                    node_map do |node, new_q, route|
         | 
| 76 76 | 
             
                      orig_key = node.parent_key
         | 
| 77 77 | 
             
                      existing = new_q.find(node.route)
         | 
| 78 78 | 
             
                      orig_fragment = existing.nil? ? node.fragment : existing
         | 
| 79 | 
            -
                      block.call(orig_key, orig_fragment)
         | 
| 79 | 
            +
                      block.call(orig_key, orig_fragment, route)
         | 
| 80 80 | 
             
                    end
         | 
| 81 81 | 
             
                  end
         | 
| 82 82 |  | 
| 83 83 | 
             
                  def each(&block)
         | 
| 84 | 
            -
                    enumerate { |node| block.call(node.parent_key, node.fragment) }
         | 
| 84 | 
            +
                    enumerate { |node, route| block.call(node.parent_key, node.fragment, route) }
         | 
| 85 85 | 
             
                  end
         | 
| 86 86 |  | 
| 87 87 | 
             
                  private
         | 
| 88 88 |  | 
| 89 89 | 
             
                  def node_map(&block)
         | 
| 90 90 | 
             
                    new_q = self.class.new(base.class.new)
         | 
| 91 | 
            -
                    enumerate do |node|
         | 
| 92 | 
            -
                      key, val = block.call(node, new_q)
         | 
| 91 | 
            +
                    enumerate do |node, route|
         | 
| 92 | 
            +
                      key, val = block.call(node, new_q, route)
         | 
| 93 93 | 
             
                      new_q.alter(node.route, key: key, value: val)
         | 
| 94 94 | 
             
                    end
         | 
| 95 95 | 
             
                    new_q
         | 
| @@ -102,7 +102,7 @@ module Depth | |
| 102 102 | 
             
                      if current.next?
         | 
| 103 103 | 
             
                        current = current.next
         | 
| 104 104 | 
             
                      elsif !current.root?
         | 
| 105 | 
            -
                        yield(current)
         | 
| 105 | 
            +
                        yield(current, current.humanized_route)
         | 
| 106 106 | 
             
                        current = current.parent
         | 
| 107 107 | 
             
                      end
         | 
| 108 108 | 
             
                    end while !current.root? || current.next?
         | 
    
        data/lib/depth/traverser.rb
    CHANGED
    
    | @@ -9,12 +9,12 @@ module Depth | |
| 9 9 | 
             
                end
         | 
| 10 10 |  | 
| 11 11 | 
             
                def next(key_or_index)
         | 
| 12 | 
            -
                  return Traverser.new(nil) if object.nil? | 
| 12 | 
            +
                  return Traverser.new(nil) if object.nil?
         | 
| 13 13 | 
             
                  Traverser.new(object[key_or_index])
         | 
| 14 14 | 
             
                end
         | 
| 15 15 |  | 
| 16 16 | 
             
                def next_or_create(key_or_index, &block)
         | 
| 17 | 
            -
                  return Traverser.new(nil) if object.nil? | 
| 17 | 
            +
                  return Traverser.new(nil) if object.nil?
         | 
| 18 18 | 
             
                  object[key_or_index] = block.call if object[key_or_index].nil?
         | 
| 19 19 | 
             
                  Traverser.new(object[key_or_index])
         | 
| 20 20 | 
             
                end
         | 
    
        data/lib/depth/version.rb
    CHANGED
    
    
    
        data/spec/depth/actions_spec.rb
    CHANGED
    
    | @@ -102,6 +102,31 @@ module Depth | |
| 102 102 | 
             
                end
         | 
| 103 103 |  | 
| 104 104 | 
             
                describe '#find' do
         | 
| 105 | 
            +
                  context 'with create true' do
         | 
| 106 | 
            +
                    it 'should create the route if it needs to' do
         | 
| 107 | 
            +
                      route = [['$yo', :array], 0, '$thing']
         | 
| 108 | 
            +
                      expect {
         | 
| 109 | 
            +
                        subject.find(route, create: true)
         | 
| 110 | 
            +
                      }.to change { subject.base['$yo'] }.to( [{}] )
         | 
| 111 | 
            +
                    end
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                    context 'with a default value' do
         | 
| 114 | 
            +
                      it 'should create the route and value it needs to' do
         | 
| 115 | 
            +
                        route = [['$yo', :array], 0, '$thing']
         | 
| 116 | 
            +
                        expect {
         | 
| 117 | 
            +
                          subject.find(route, create: true, default: 4)
         | 
| 118 | 
            +
                        }.to change { subject.base['$yo'] }.to( [{'$thing' => 4}] )
         | 
| 119 | 
            +
                      end
         | 
| 120 | 
            +
                    end
         | 
| 121 | 
            +
                  end
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                  context 'with a default value and a missing route' do
         | 
| 124 | 
            +
                    it 'should return the default' do
         | 
| 125 | 
            +
                      route = ['$yo', 0, '$thing']
         | 
| 126 | 
            +
                      expect(subject.find(route, default: 'blah')).to eq 'blah'
         | 
| 127 | 
            +
                    end
         | 
| 128 | 
            +
                  end
         | 
| 129 | 
            +
             | 
| 105 130 | 
             
                  it 'should let me find an existing value' do
         | 
| 106 131 | 
             
                    route = [['$and', :array], [0, :hash],
         | 
| 107 132 | 
             
                             ['#weather', :hash], ['something', :array]]
         | 
| @@ -157,7 +157,7 @@ module Depth::Enumeration | |
| 157 157 |  | 
| 158 158 | 
             
                  context 'with alteration' do
         | 
| 159 159 | 
             
                    let(:result) do
         | 
| 160 | 
            -
                      subject.map do |k, v|
         | 
| 160 | 
            +
                      subject.map do |k, v, r|
         | 
| 161 161 | 
             
                        next [k, v] unless k.is_a?(String)
         | 
| 162 162 | 
             
                        ["#{k}Altered", 'redacted']
         | 
| 163 163 | 
             
                      end
         | 
| @@ -218,6 +218,22 @@ module Depth::Enumeration | |
| 218 218 | 
             
                end
         | 
| 219 219 |  | 
| 220 220 | 
             
                describe '#each' do
         | 
| 221 | 
            +
                  it 'should keep track of where we are' do
         | 
| 222 | 
            +
                    routes = []
         | 
| 223 | 
            +
                    subject.each do |_, _, route|
         | 
| 224 | 
            +
                      routes << route
         | 
| 225 | 
            +
                    end
         | 
| 226 | 
            +
             | 
| 227 | 
            +
                    expected = [
         | 
| 228 | 
            +
                      ["$and", 0, "#weather", "something"], ["$and", 0, "#weather"],
         | 
| 229 | 
            +
                      ["$and", 0], ["$and", 1, "$or", 0, "#otherfeed", "thing"],
         | 
| 230 | 
            +
                      ["$and", 1, "$or", 0, "#otherfeed"], ["$and", 1, "$or", 0],
         | 
| 231 | 
            +
                      ["$and", 1, "$or"], ["$and", 1], ["$and"]
         | 
| 232 | 
            +
                    ]
         | 
| 233 | 
            +
             | 
| 234 | 
            +
                    expect(routes).to eq(expected)
         | 
| 235 | 
            +
                  end
         | 
| 236 | 
            +
             | 
| 221 237 | 
             
                  it 'should sort through all keys and values' do
         | 
| 222 238 | 
             
                    enumerated = []
         | 
| 223 239 | 
             
                    subject.each do |key, fragment|
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: depth
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.3.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Max
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2016-03-01 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bundler
         |