aha 1.0.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 +7 -0
- data/MIT-LICENSE +22 -0
- data/README.md +31 -0
- data/lib/aha/augmented_hash.rb +186 -0
- data/lib/aha/helper.rb +28 -0
- data/lib/aha/version.rb +3 -0
- data/lib/aha.rb +40 -0
- data/spec/lib/aha_spec.rb +54 -0
- data/spec/spec_helper.rb +10 -0
- metadata +121 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bb3f97c109690791bca8f2838ac07cc21aa40e0a
|
4
|
+
data.tar.gz: 14ade28b15cff210f3b416db650ec9128d9e381e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 32234582b85e179aba8baa33540a57e66fe8f101bad71eebacb352319db29b0b59a28fe6b426755b52557426ed96cd4d11d052bd9eac1e08e80e22ef0634478e
|
7
|
+
data.tar.gz: 513d4cb0a36dc4d93e04a985b093ef02cbcd85365aee380923cfb9c476f3107f6cee89d76fe7358bae43f5ac67f66d1e239055f1d08f449bcddd4314d03fbd2a
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Mike Jackson
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# Aha
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'aha'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install aha
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
TODO: Write usage instructions here
|
24
|
+
|
25
|
+
## Contributing
|
26
|
+
|
27
|
+
1. Fork it ( https://github.com/[my-github-username]/aha/fork )
|
28
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
29
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
30
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
31
|
+
5. Create a new Pull Request
|
@@ -0,0 +1,186 @@
|
|
1
|
+
require 'aha/helper'
|
2
|
+
|
3
|
+
module Aha
|
4
|
+
# Public: Provides functionality for dealing with nested hashes.
|
5
|
+
#
|
6
|
+
# Nested keys are represented by an array where the first element represents the
|
7
|
+
# the key to access the sub hash and the rest represent keys for that hash.
|
8
|
+
#
|
9
|
+
# These arrays can be nested allowing us to represent keys for an arbitrarily
|
10
|
+
# nested hash. This way of representing keys is used throughout Aha and is
|
11
|
+
# heavily inspired by the Prismatic's Clojure fnk style destructuring as seen
|
12
|
+
# here: https://github.com/Prismatic/plumbing/tree/master/src/plumbing/fnk
|
13
|
+
#
|
14
|
+
# For example:
|
15
|
+
#
|
16
|
+
# Given the hash {a: 'hello', b: {c: 'augmented', d: {e: 'hash'}}}
|
17
|
+
# the keys :a, [:b, :c, [:d, :e]] would correspond to the values
|
18
|
+
# 'hello', 'augmented', 'hash'
|
19
|
+
module AugmentedHash
|
20
|
+
extend self
|
21
|
+
|
22
|
+
# Public: Similar to Hash#values_at except that it supports nested key
|
23
|
+
# syntax and is primarily intented to be used for destructuring assignment.
|
24
|
+
#
|
25
|
+
# hash - The nested hash to extract values from.
|
26
|
+
# keys - They keys corresponding to the values to be extracted. Supports
|
27
|
+
# nested key syntax.
|
28
|
+
#
|
29
|
+
# Examples:
|
30
|
+
#
|
31
|
+
# h = {'a' => 3, :b => {:c => 2, 'd' => {:e => 1}}}
|
32
|
+
# value_1, value_2, value_3 = vals_at h, 'a', [:b, :c, ['d', :e]]
|
33
|
+
#
|
34
|
+
# value_1
|
35
|
+
# # => 3
|
36
|
+
# value_2
|
37
|
+
# # => 2
|
38
|
+
# value_3
|
39
|
+
# # => 1
|
40
|
+
#
|
41
|
+
# Returns an array of values corresponding to the given keys.
|
42
|
+
def vals_at(hash, *keys)
|
43
|
+
result = Aha::Helper::extract_option(:acc, keys) || []
|
44
|
+
|
45
|
+
result.tap do |acc|
|
46
|
+
keys.each do |k|
|
47
|
+
if k.is_a? Array
|
48
|
+
subkey, *keys = k
|
49
|
+
vals_at(hash[subkey], *keys, {acc: acc})
|
50
|
+
else
|
51
|
+
acc << hash[k]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Public: Retrieves a value from a nested hash. Equivalent to
|
58
|
+
# hash[k1][..][kn]
|
59
|
+
#
|
60
|
+
# hash - The hash to retrieve the value from.
|
61
|
+
# keys - The keys to the value in order of depth.
|
62
|
+
#
|
63
|
+
# Examples:
|
64
|
+
#
|
65
|
+
# h = {:a => {'b' => {:c => 'value'}}}
|
66
|
+
# get_in h, :a, 'b', :c
|
67
|
+
# # => 'value'
|
68
|
+
#
|
69
|
+
# Returns the value if it exists and nil otherwise
|
70
|
+
def get_in(hash, *keys)
|
71
|
+
keys.reduce(hash) { |acc, k| acc[k] }
|
72
|
+
end
|
73
|
+
|
74
|
+
# Public: Sets a value within a nested hash. Equivalent to
|
75
|
+
# hash[k1][..][kn] = val
|
76
|
+
#
|
77
|
+
# hash - The nested hash to set the value in.
|
78
|
+
# keys - The keys to the value to set in order of depth.
|
79
|
+
# val - The new value to set.
|
80
|
+
#
|
81
|
+
# Examples:
|
82
|
+
#
|
83
|
+
# h = {:a => {'b' => {:c => 'value'}}}
|
84
|
+
# put_in! h, :a, 'b', :c, 'new_value'
|
85
|
+
# h
|
86
|
+
# # => {:a => {'b' => {:c => 'new_value'}}}
|
87
|
+
#
|
88
|
+
# Returns nothing.
|
89
|
+
def put_in!(hash, *keys, val)
|
90
|
+
last_key = keys.pop
|
91
|
+
get_in(hash, *keys)[last_key] = val
|
92
|
+
end
|
93
|
+
|
94
|
+
# Public: Updates a value within a nested hash.
|
95
|
+
#
|
96
|
+
# hash - The nested hash to update the value in.
|
97
|
+
# keys - The keys to the current value in order of depth
|
98
|
+
# block - A required block that is given the current value and should return
|
99
|
+
# the updated value to be set.
|
100
|
+
#
|
101
|
+
# Examples:
|
102
|
+
#
|
103
|
+
# h = {:a => {'b' => {:c => 33}}}
|
104
|
+
# update_in!(h, :a, 'b', :c) { |v| v + 9}
|
105
|
+
# h
|
106
|
+
# # => {:a => {'b' => {:c => 42}}}
|
107
|
+
#
|
108
|
+
# Returns nothing.
|
109
|
+
def update_in!(hash, *keys)
|
110
|
+
put_in!(hash, *keys, yield(get_in(hash, *keys))) if block_given?
|
111
|
+
end
|
112
|
+
|
113
|
+
# Public: Deletes a value within a nested hash. Equivalent to
|
114
|
+
# hash[k1][..][kn-1].delete(kn)
|
115
|
+
#
|
116
|
+
# hash - The nested hash to delete the value in.
|
117
|
+
# keys - They keys to the value to delete in order of depth.
|
118
|
+
#
|
119
|
+
# Examples:
|
120
|
+
#
|
121
|
+
# h = {:a => {'b' => {:c => 'hello', :d => 'world'}}}
|
122
|
+
# delete_in! h, :a, 'b', :c
|
123
|
+
# h
|
124
|
+
# # => {:a => {'b' => {:d => 'world'}}}
|
125
|
+
#
|
126
|
+
# Returns nothing.
|
127
|
+
def delete_in!(hash, *keys)
|
128
|
+
last_key = keys.pop
|
129
|
+
get_in(hash, *keys).delete last_key
|
130
|
+
end
|
131
|
+
|
132
|
+
# Public: Removes the excluded keys from the hash.
|
133
|
+
#
|
134
|
+
# hash - The hash to exclude keys from.
|
135
|
+
# keys - The keys to be excluded from the hash. Supports nested key syntax.
|
136
|
+
#
|
137
|
+
# Examples:
|
138
|
+
#
|
139
|
+
# h = {:a => {'b' => {:c => 'hello', :d => 'augmented'}}, :e => 'hash'}
|
140
|
+
# exclude! h, [:a, ['b', :d]], :e
|
141
|
+
# h
|
142
|
+
# # => {:a => {'b' => {:c => 'hello'}}}
|
143
|
+
#
|
144
|
+
# Returns nothing.
|
145
|
+
def exclude!(hash, *keys)
|
146
|
+
keys.each do |k|
|
147
|
+
if k.is_a? Array
|
148
|
+
subkey, *keys = k
|
149
|
+
exclude!(hash[subkey], *keys)
|
150
|
+
else
|
151
|
+
hash.delete k
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Public: Creates a new hash consisting only keys given and their
|
157
|
+
# corresponding values.
|
158
|
+
#
|
159
|
+
# hash - The hash to base the result on.
|
160
|
+
# keys - The keys that the new hash will contain. Supports nested key
|
161
|
+
# syntax.
|
162
|
+
#
|
163
|
+
# Examples:
|
164
|
+
#
|
165
|
+
# h = {:a => {'b' => {:c => 'hello', :d => 'augmented'}}, :e => 'hash'}
|
166
|
+
# only h, [:a, ['b', :d]]
|
167
|
+
# # => {:a => {'b' => {:d => 'augmented'}}}
|
168
|
+
#
|
169
|
+
# Returns the new, smaller hash.
|
170
|
+
def only(hash, *keys)
|
171
|
+
result = {}
|
172
|
+
|
173
|
+
result.tap do |r|
|
174
|
+
keys.each do |k|
|
175
|
+
if k.is_a? Array
|
176
|
+
subkey, *keys = k
|
177
|
+
r[subkey] = only(hash[subkey], *keys)
|
178
|
+
else
|
179
|
+
r[k] = hash[k]
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
end
|
data/lib/aha/helper.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Aha
|
2
|
+
# Internal: Provides helper methods for the rest of the Aha library.
|
3
|
+
module Helper
|
4
|
+
extend self
|
5
|
+
|
6
|
+
# Internal: Extracts an option from the options hash if it exists in the method args.
|
7
|
+
#
|
8
|
+
# option_key - A symbol corresponding to a key in the options hash.
|
9
|
+
# args - An array containing a number of args followed by an optional options hash.
|
10
|
+
#
|
11
|
+
# Examples:
|
12
|
+
#
|
13
|
+
# args_with_options = [:a, :b, :c, :d, {:key => :option}]
|
14
|
+
# args_without_options = [:a, :b, :c, :d]
|
15
|
+
#
|
16
|
+
# extract_option :key, args_with_options
|
17
|
+
# # => :option
|
18
|
+
#
|
19
|
+
# extract_option :key, args_without_options
|
20
|
+
# # => nil
|
21
|
+
#
|
22
|
+
# Returns the option value if it exists and nil otherwise.
|
23
|
+
def extract_option(option_key, args)
|
24
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
25
|
+
options[option_key]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/aha/version.rb
ADDED
data/lib/aha.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'aha/version'
|
2
|
+
require 'aha/augmented_hash'
|
3
|
+
|
4
|
+
# Extends Hash with functionality from Aha::AugmentedHash.
|
5
|
+
#
|
6
|
+
# Methods are implemented by delegating to AugmentedHash on an individual method
|
7
|
+
# basis. Using module methods as opposed to a mixing in a module is preferrable
|
8
|
+
# as it allows us to include functionality in a piecemeal manner if necessary
|
9
|
+
# and supports minimal changes to the core Hash class.
|
10
|
+
#
|
11
|
+
# For more information see Aha::AugmentedHash.
|
12
|
+
class Hash
|
13
|
+
def vals_at(*keys)
|
14
|
+
Aha::AugmentedHash::vals_at(self, *keys)
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_in(*keys)
|
18
|
+
Aha::AugmentedHash::get_in(self, *keys)
|
19
|
+
end
|
20
|
+
|
21
|
+
def put_in!(*args)
|
22
|
+
Aha::AugmentedHash::put_in!(self, *args)
|
23
|
+
end
|
24
|
+
|
25
|
+
def update_in!(*keys, &block)
|
26
|
+
Aha::AugmentedHash::update_in!(self, *keys, &block)
|
27
|
+
end
|
28
|
+
|
29
|
+
def delete_in!(*keys)
|
30
|
+
Aha::AugmentedHash::delete_in!(self, *keys)
|
31
|
+
end
|
32
|
+
|
33
|
+
def exclude!(*keys)
|
34
|
+
Aha::AugmentedHash::exclude!(self, *keys)
|
35
|
+
end
|
36
|
+
|
37
|
+
def only(*keys)
|
38
|
+
Aha::AugmentedHash::only(self, *keys)
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'aha'
|
3
|
+
|
4
|
+
describe Hash do
|
5
|
+
before(:each) do
|
6
|
+
@data = {:name => 'Oculus VR',
|
7
|
+
:founders => ['Palmer Luckey', 'Brendan Iribe', 'Michael Antonov', 'Nate Mitchell', 'Jack McCauley'],
|
8
|
+
:ceo => {'name' => 'Brendan Iribe'},
|
9
|
+
'cto' => {:name => 'John Carmack',
|
10
|
+
'age' => 44,
|
11
|
+
:spouse => {:name => 'Katherine Anna Kang'}}}
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should destructure nested hashes' do
|
15
|
+
company_name, ceo_name, cto_name, cto_age, cto_spouse_name =
|
16
|
+
@data.vals_at(:name, [:ceo, 'name'], ['cto', :name, 'age', [:spouse, :name]])
|
17
|
+
|
18
|
+
company_name.should == 'Oculus VR'
|
19
|
+
ceo_name.should == 'Brendan Iribe'
|
20
|
+
cto_name.should == 'John Carmack'
|
21
|
+
cto_age.should == 44
|
22
|
+
cto_spouse_name.should == 'Katherine Anna Kang'
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should retrieve nested values' do
|
26
|
+
@data.get_in('cto', :spouse, :name).should == 'Katherine Anna Kang'
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should set nested values' do
|
30
|
+
@data.put_in! 'cto', :name, 'Alan Kay'
|
31
|
+
@data['cto'][:name].should == 'Alan Kay'
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should updated nested values' do
|
35
|
+
@data.update_in!('cto', 'age') { |age| age + 5 }
|
36
|
+
@data['cto']['age'].should == 49
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should delete nested values' do
|
40
|
+
@data.delete_in! 'cto', :spouse
|
41
|
+
@data['cto'][:spouse].should be_nil
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should exclude keys in nested hashes' do
|
45
|
+
@data.exclude! :founders, :ceo, ['cto', 'age', :spouse]
|
46
|
+
@data.should == {:name => 'Oculus VR', 'cto' => {:name => 'John Carmack'}}
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should return a new hash from given keys' do
|
50
|
+
@data.only(:name, ['cto', [:spouse, :name]]). should ==
|
51
|
+
{:name => 'Oculus VR',
|
52
|
+
'cto' => {:spouse => {:name => 'Katherine Anna Kang'}}}
|
53
|
+
end
|
54
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
RSpec.configure do |config|
|
2
|
+
config.expect_with :rspec do |expectations|
|
3
|
+
expectations.syntax = [:should, :expect]
|
4
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
5
|
+
end
|
6
|
+
|
7
|
+
config.mock_with :rspec do |mocks|
|
8
|
+
mocks.verify_partial_doubles = true
|
9
|
+
end
|
10
|
+
end
|
metadata
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: aha
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mike Jackson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-09-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: guard
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: guard-rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description:
|
84
|
+
email: occamin@gmail.com
|
85
|
+
executables: []
|
86
|
+
extensions: []
|
87
|
+
extra_rdoc_files: []
|
88
|
+
files:
|
89
|
+
- MIT-LICENSE
|
90
|
+
- README.md
|
91
|
+
- lib/aha.rb
|
92
|
+
- lib/aha/augmented_hash.rb
|
93
|
+
- lib/aha/helper.rb
|
94
|
+
- lib/aha/version.rb
|
95
|
+
- spec/lib/aha_spec.rb
|
96
|
+
- spec/spec_helper.rb
|
97
|
+
homepage: https://rubygems.org/gems/aha
|
98
|
+
licenses:
|
99
|
+
- MIT
|
100
|
+
metadata: {}
|
101
|
+
post_install_message:
|
102
|
+
rdoc_options: []
|
103
|
+
require_paths:
|
104
|
+
- lib
|
105
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 1.9.3
|
110
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
requirements: []
|
116
|
+
rubyforge_project:
|
117
|
+
rubygems_version: 2.2.2
|
118
|
+
signing_key:
|
119
|
+
specification_version: 4
|
120
|
+
summary: A library of Hash extensions to simplify working with nested data.
|
121
|
+
test_files: []
|