hash_path 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: efc30720d5e9dc46735cdbcdca64437b58a0e442
4
+ data.tar.gz: 5de1e070a617786d9717242cb421a993afca0341
5
+ SHA512:
6
+ metadata.gz: 9b99483587f78bf847bd8ac51cbb38951fecfe9ba73679e37d3bc39341657904d63e0432daf3f1d6481695e0eb91f0658768232cb71e45e7f993401506efecde
7
+ data.tar.gz: 997d8a91955d890b3657c405c404fd3c60781f1fc886ed3c0e3bfcea343a55be0eca19bca7ae5ea9a4e403279867f1216df8c8326bae176a69cac2c93c7dafc4
data/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ # Change log
2
+
3
+ ## 0.4.0
4
+ ### 2014-11-25
5
+
6
+ - Now at_path and at_path! can look up keys which are symbols, rather than strings.
7
+
8
+ ## 0.3.0
9
+ ### 2012-10-09
10
+
11
+ - Start of the change log. Adds at_path, at_path!, and flatten_key_paths methods to Hash.
data/README.md CHANGED
@@ -2,14 +2,14 @@
2
2
 
3
3
  Provides a simple interface to access hash paths.
4
4
 
5
- The gem was written to help with specs so use in production code will have an
6
- unkonwn performance hit.
5
+ The gem was written to help with specs, so use in production code will have an
6
+ unknown performance hit.
7
7
 
8
8
  ## Installation
9
9
 
10
10
  Add this line to your application's Gemfile:
11
11
 
12
- gem 'path_spec'
12
+ gem 'hash_path'
13
13
 
14
14
  And then execute:
15
15
 
@@ -17,7 +17,7 @@ And then execute:
17
17
 
18
18
  Or install it yourself as:
19
19
 
20
- $ gem install path_spec
20
+ $ gem install hash_path
21
21
 
22
22
  ## Usage
23
23
 
@@ -38,7 +38,7 @@ Given the hash
38
38
  # Or the raise version
39
39
  my_hash.at_path!("foo.bar.baz") #=> 'hai'
40
40
  my_hash.at_path!("foo.bar.barry") #=> raises
41
- my_hash.at_path("not_a_key") #=> raises
41
+ my_hash.at_path!("not_a_key") #=> raises
42
42
 
43
43
 
44
44
  ## Contributing
data/hash_path.gemspec CHANGED
@@ -14,4 +14,6 @@ Gem::Specification.new do |gem|
14
14
  gem.name = "hash_path"
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = HashPath::VERSION
17
+ gem.add_development_dependency 'rspec', '~> 3.1'
18
+ gem.add_development_dependency 'pry'
17
19
  end
@@ -1,3 +1,3 @@
1
1
  module HashPath
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
data/lib/hash_path.rb CHANGED
@@ -9,35 +9,33 @@ module HashPath
9
9
  # @example
10
10
  # my_hash.at_path("foo.bar.baz") # looks in my_hash['foo']['bar']['baz']
11
11
  def at_path(path)
12
- path_keys = normalize_path(path)
13
- current_value = self
14
-
15
- path_keys.each do |key|
16
- return nil unless current_value.respond_to?(:[])
17
- current_value = current_value[key]
18
- end
19
- current_value
12
+ at_path!(path) rescue nil
20
13
  end
21
14
 
22
15
  # Same as at_path but raises when a path is not found
23
16
  # The raise will give a delimited path of where the path went dead
24
17
  # @example
25
- # f = { 'foo' => {'bar' => {'baz' => 'hai'}, "baz" => [1,2] } }
18
+ # f = { 'foo' => {'bar' => {'baz' => 'hai'} }, "baz" => [1,2] }
26
19
  # f.at_path!('foo.not.baz') # Raises, message == 'foo.not'
27
20
  # f.at_path!('not.here.yo') # Raises, message == 'not'
28
21
  # f.at_path!('foo.bar.not') # Raises, message == 'foo.bar.not'
29
22
  # f.at_path!("baz.1") # => 2
30
23
  # @see HashPath#at_path
31
24
  def at_path!(path)
32
- path_keys = normalize_path(path)
33
- the_keys, current_value = [], self
25
+ the_keys = []
34
26
 
35
- path_keys.each do |key|
36
- raise(PathNotFound, the_keys.join(DELIMITER)) unless current_value.respond_to?(:[])
27
+ normalize_path(path).reduce(self) do |memo, key|
37
28
  the_keys << key
38
- current_value = current_value[key]
29
+ case key
30
+ when String
31
+ memo.key?(key) ? memo.fetch(key) : memo.fetch(key.to_sym)
32
+ else
33
+ memo.fetch(key)
34
+ end
39
35
  end
40
- current_value
36
+
37
+ rescue => e
38
+ raise(PathNotFound, the_keys.join(DELIMITER))
41
39
  end
42
40
 
43
41
  # Provides flattened hash key paths
@@ -45,10 +43,11 @@ module HashPath
45
43
  case hash_or_obj
46
44
  when Hash
47
45
  hash_or_obj.inject({}) do |h, (k,v)|
48
- full_prefix = [prefix, k].compact.join(".")
46
+ full_prefix = [prefix, k].compact.join(DELIMITER)
49
47
  result = flatten_key_paths(v, full_prefix)
50
- if Hash === result
51
- h.merge! result
48
+ case result
49
+ when Hash
50
+ h.merge!(result)
52
51
  else
53
52
  h[full_prefix] = result
54
53
  end
@@ -60,13 +59,14 @@ module HashPath
60
59
  end
61
60
 
62
61
  private
62
+
63
63
  def normalize_path(path)
64
64
  case path
65
65
  when Array
66
66
  path
67
67
  when String, Symbol
68
68
  path.to_s.split(DELIMITER)
69
- end.map{|key| key =~ /^\d+$/ ? key.to_i : key }
69
+ end.map{|key| key =~ /\A\d+\z/ ? key.to_i : key }
70
70
  end
71
71
  end
72
72
 
@@ -0,0 +1,87 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe HashPath do
4
+ describe '#at_path' do
5
+ it 'returns nil if the key is not found' do
6
+ expect({}.at_path('foo')).to eq(nil)
7
+ end
8
+
9
+ it 'returns a value if it is found' do
10
+ expect({foo: {bar: 5}}.at_path('foo.bar')).to eq(5)
11
+ end
12
+ end
13
+
14
+ describe '#at_path!' do
15
+ it 'looks up a key given by a string' do
16
+ expect({'foo' => 5}.at_path!('foo')).to eq(5)
17
+ end
18
+
19
+ it 'finds a symbol when searching by a string' do
20
+ expect({foo: 5}.at_path!('foo')).to eq(5)
21
+ end
22
+
23
+ it 'looks up a key given by a symbol' do
24
+ expect({foo: 5}.at_path!(:foo)).to eq(5)
25
+ end
26
+
27
+ it 'looks up a symbol key given by an array' do
28
+ expect({foo: 5}.at_path!(['foo'])).to eq(5)
29
+ end
30
+
31
+ it 'looks up a string key given by an array' do
32
+ expect({'foo' => 5}.at_path!(['foo'])).to eq(5)
33
+ end
34
+
35
+ it 'looks up an object key' do
36
+ expect({73 => 5}.at_path!([73])).to eq(5)
37
+ end
38
+
39
+ it 'looks up a second level value' do
40
+ expect({foo: {bar: 5}}.at_path!(['foo', :bar])).to eq(5)
41
+ end
42
+
43
+ it 'raises a nice error when top-level key not found' do
44
+ expect {
45
+ {}.at_path!(['foo', 'bar'])
46
+ }.to raise_error(HashPath::PathNotFound, 'foo')
47
+ end
48
+
49
+ it 'raises a nice error when second-level key not found' do
50
+ expect {
51
+ {foo: {}}.at_path!(['foo', 'bar'])
52
+ }.to raise_error(HashPath::PathNotFound, 'foo.bar')
53
+ end
54
+
55
+ context 'a few more cases' do
56
+ let(:hash) { { 'foo' => {'bar' => {'baz' => 'hai'} }, "baz" => [11,22] } }
57
+
58
+ it 'throws an exception with middle key missing' do
59
+ expect { hash.at_path!('foo.not.baz') }.to raise_error(HashPath::PathNotFound, 'foo.not')
60
+ end
61
+
62
+ it 'throws an exception with first key missing' do
63
+ expect { hash.at_path!('not.here.yo') }.to raise_error(HashPath::PathNotFound, 'not')
64
+ end
65
+
66
+ it 'throws an exception with third key missing' do
67
+ expect { hash.at_path!('foo.bar.not') }.to raise_error(HashPath::PathNotFound, 'foo.bar.not')
68
+ end
69
+
70
+ it 'can traverse an array with a zero-based integer' do
71
+ expect(hash.at_path!('baz.1')).to eq(22)
72
+ end
73
+ end
74
+ end
75
+
76
+ describe '#flatten_key_paths' do
77
+ it 'un-nests hashes' do
78
+ expect({a: 5, b: {c: 7}}.flatten_key_paths).to eq({'a' => 5, 'b.c' => 7})
79
+ end
80
+ end
81
+
82
+ describe 'HashPath::VERSION' do
83
+ it 'is set' do
84
+ expect(HashPath::VERSION).not_to eq(nil)
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,3 @@
1
+ RSpec.configure(&:disable_monkey_patching!)
2
+
3
+ require 'hash_path'
metadata CHANGED
@@ -1,34 +1,52 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: hash_path
3
- version: !ruby/object:Gem::Version
4
- hash: 19
5
- prerelease:
6
- segments:
7
- - 0
8
- - 3
9
- - 0
10
- version: 0.3.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
11
5
  platform: ruby
12
- authors:
6
+ authors:
13
7
  - Daniel Neighman
14
8
  autorequire:
15
9
  bindir: bin
16
10
  cert_chain: []
17
-
18
- date: 2012-10-10 00:00:00 Z
19
- dependencies: []
20
-
11
+ date: 2014-12-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.1'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
21
41
  description: Easy path navigation for hashes
22
- email:
42
+ email:
23
43
  - dneighman@squareup.com
24
44
  executables: []
25
-
26
45
  extensions: []
27
-
28
46
  extra_rdoc_files: []
29
-
30
- files:
31
- - .gitignore
47
+ files:
48
+ - ".gitignore"
49
+ - CHANGELOG.md
32
50
  - Gemfile
33
51
  - LICENSE
34
52
  - README.md
@@ -36,38 +54,32 @@ files:
36
54
  - hash_path.gemspec
37
55
  - lib/hash_path.rb
38
56
  - lib/hash_path/version.rb
39
- homepage: ""
57
+ - spec/hash_path_spec.rb
58
+ - spec/spec_helper.rb
59
+ homepage: ''
40
60
  licenses: []
41
-
61
+ metadata: {}
42
62
  post_install_message:
43
63
  rdoc_options: []
44
-
45
- require_paths:
64
+ require_paths:
46
65
  - lib
47
- required_ruby_version: !ruby/object:Gem::Requirement
48
- none: false
49
- requirements:
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
50
68
  - - ">="
51
- - !ruby/object:Gem::Version
52
- hash: 3
53
- segments:
54
- - 0
55
- version: "0"
56
- required_rubygems_version: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
59
73
  - - ">="
60
- - !ruby/object:Gem::Version
61
- hash: 3
62
- segments:
63
- - 0
64
- version: "0"
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
65
76
  requirements: []
66
-
67
77
  rubyforge_project:
68
- rubygems_version: 1.8.24
78
+ rubygems_version: 2.2.2
69
79
  signing_key:
70
- specification_version: 3
80
+ specification_version: 4
71
81
  summary: Easy path navigation for hashes. Useful in specs
72
- test_files: []
73
-
82
+ test_files:
83
+ - spec/hash_path_spec.rb
84
+ - spec/spec_helper.rb
85
+ has_rdoc: