collapsium 0.1.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/.codeclimate.yml +34 -0
- data/.gitignore +39 -0
- data/.rspec +2 -0
- data/.rubocop.yml +75 -0
- data/.travis.yml +8 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +62 -0
- data/LICENSE +30 -0
- data/README.md +48 -0
- data/Rakefile +25 -0
- data/collapsium.gemspec +45 -0
- data/lib/collapsium.rb +16 -0
- data/lib/collapsium/indifferent_access.rb +34 -0
- data/lib/collapsium/pathed_access.rb +139 -0
- data/lib/collapsium/recursive_merge.rb +57 -0
- data/lib/collapsium/uber_hash.rb +36 -0
- data/lib/collapsium/version.rb +12 -0
- data/spec/indifferent_access_spec.rb +26 -0
- data/spec/pathed_access_spec.rb +100 -0
- data/spec/recursive_merge_spec.rb +70 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/uber_hash_spec.rb +44 -0
- metadata +157 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 380030070f1838be3f5a7955fcd6e146398653f7
|
|
4
|
+
data.tar.gz: 18862980c22abb357b61c26d867a21d397c4faef
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: c5be77bf133c4042d193a4f10c4dafbbc2805da3dc4497b29e11802d33a4b34726a2af79642d9f6423f9de14746a46d2a3acc7ff655d1e14d1ba11ca68ba3055
|
|
7
|
+
data.tar.gz: 55fa9036b582b1cb8f708c1d384e006b2bf822253ed213eff8204fbeae2e4a159b578ac6a1330ac380ab75b875f637e8cf4385ed8c57760ce0888e3e10d8d29c
|
data/.codeclimate.yml
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
engines:
|
|
3
|
+
bundler-audit:
|
|
4
|
+
enabled: true
|
|
5
|
+
duplication:
|
|
6
|
+
enabled: true
|
|
7
|
+
exclude_fingerprints:
|
|
8
|
+
- d85d6f12c93d79ccd43868b8315d8816
|
|
9
|
+
- a8e2b4ccb258f16eda697c5f98e21823
|
|
10
|
+
- 442a316695836b4f4693fe3786cd3396
|
|
11
|
+
- 1c24bb5da72323796b645814cc006684
|
|
12
|
+
- 4ff1112a73f7be30ecefa7bd90fdbf5a
|
|
13
|
+
config:
|
|
14
|
+
languages:
|
|
15
|
+
- ruby
|
|
16
|
+
- javascript
|
|
17
|
+
- python
|
|
18
|
+
- php
|
|
19
|
+
fixme:
|
|
20
|
+
enabled: true
|
|
21
|
+
rubocop:
|
|
22
|
+
enabled: true
|
|
23
|
+
ratings:
|
|
24
|
+
paths:
|
|
25
|
+
- Gemfile.lock
|
|
26
|
+
- "**.inc"
|
|
27
|
+
- "**.js"
|
|
28
|
+
- "**.jsx"
|
|
29
|
+
- "**.module"
|
|
30
|
+
- "**.php"
|
|
31
|
+
- "**.py"
|
|
32
|
+
- "**.rb"
|
|
33
|
+
exclude_paths:
|
|
34
|
+
- spec/
|
data/.gitignore
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
*.gem
|
|
2
|
+
*.rbc
|
|
3
|
+
/.config
|
|
4
|
+
/coverage/
|
|
5
|
+
/InstalledFiles
|
|
6
|
+
/pkg/
|
|
7
|
+
/spec/reports/
|
|
8
|
+
/spec/examples.txt
|
|
9
|
+
/test/tmp/
|
|
10
|
+
/test/version_tmp/
|
|
11
|
+
/tmp/
|
|
12
|
+
|
|
13
|
+
## Specific to RubyMotion:
|
|
14
|
+
.dat*
|
|
15
|
+
.repl_history
|
|
16
|
+
build/
|
|
17
|
+
|
|
18
|
+
## Documentation cache and generated files:
|
|
19
|
+
/.yardoc/
|
|
20
|
+
/_yardoc/
|
|
21
|
+
/doc/
|
|
22
|
+
/rdoc/
|
|
23
|
+
|
|
24
|
+
## Environment normalization:
|
|
25
|
+
/.bundle/
|
|
26
|
+
/vendor/bundle
|
|
27
|
+
/lib/bundler/man/
|
|
28
|
+
|
|
29
|
+
# for a library or gem, you might want to ignore these files since the code is
|
|
30
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
31
|
+
# Gemfile.lock
|
|
32
|
+
# .ruby-version
|
|
33
|
+
# .ruby-gemset
|
|
34
|
+
|
|
35
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
|
36
|
+
.rvmrc
|
|
37
|
+
|
|
38
|
+
# Editor files
|
|
39
|
+
.*.sw*
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
TargetRubyVersion: 2.2
|
|
3
|
+
|
|
4
|
+
# Metrics
|
|
5
|
+
|
|
6
|
+
Metrics/LineLength:
|
|
7
|
+
Max: 83
|
|
8
|
+
Details: >-
|
|
9
|
+
Line length of 80 is ideal for readability and compatibility; we'll accept
|
|
10
|
+
an extra 3 for minor edge cases.
|
|
11
|
+
|
|
12
|
+
Metrics/MethodLength:
|
|
13
|
+
Max: 35
|
|
14
|
+
|
|
15
|
+
Metrics/BlockNesting:
|
|
16
|
+
Max: 5
|
|
17
|
+
|
|
18
|
+
Metrics/AbcSize:
|
|
19
|
+
Max: 50
|
|
20
|
+
|
|
21
|
+
Metrics/PerceivedComplexity:
|
|
22
|
+
Max: 15
|
|
23
|
+
|
|
24
|
+
Metrics/CyclomaticComplexity:
|
|
25
|
+
Max: 15
|
|
26
|
+
|
|
27
|
+
Metrics/ClassLength:
|
|
28
|
+
Max: 300
|
|
29
|
+
|
|
30
|
+
Metrics/ModuleLength:
|
|
31
|
+
Max: 300
|
|
32
|
+
|
|
33
|
+
# Style
|
|
34
|
+
|
|
35
|
+
Style/StringLiterals:
|
|
36
|
+
Enabled: false
|
|
37
|
+
|
|
38
|
+
Style/ConditionalAssignment:
|
|
39
|
+
Enabled: false
|
|
40
|
+
|
|
41
|
+
Style/EmptyLinesAroundModuleBody:
|
|
42
|
+
Enabled: false
|
|
43
|
+
|
|
44
|
+
Style/AndOr:
|
|
45
|
+
Enabled: false
|
|
46
|
+
|
|
47
|
+
Style/Not:
|
|
48
|
+
Enabled: false
|
|
49
|
+
|
|
50
|
+
Style/NegatedIf:
|
|
51
|
+
Enabled: false
|
|
52
|
+
|
|
53
|
+
Style/RedundantReturn:
|
|
54
|
+
Enabled: false
|
|
55
|
+
|
|
56
|
+
Style/IfUnlessModifier:
|
|
57
|
+
Enabled: false
|
|
58
|
+
|
|
59
|
+
Style/TrailingCommaInLiteral:
|
|
60
|
+
Enabled: false
|
|
61
|
+
|
|
62
|
+
Style/FirstParameterIndentation:
|
|
63
|
+
Enabled: false
|
|
64
|
+
|
|
65
|
+
Style/TrailingUnderscoreVariable:
|
|
66
|
+
Enabled: false
|
|
67
|
+
|
|
68
|
+
Style/NumericLiterals:
|
|
69
|
+
Enabled: false
|
|
70
|
+
|
|
71
|
+
Style/FileName:
|
|
72
|
+
Enabled: false
|
|
73
|
+
|
|
74
|
+
Style/SpaceAfterNot:
|
|
75
|
+
Enabled: false
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
collapsium (0.1.0)
|
|
5
|
+
|
|
6
|
+
GEM
|
|
7
|
+
remote: https://rubygems.org/
|
|
8
|
+
specs:
|
|
9
|
+
ast (2.2.0)
|
|
10
|
+
codeclimate-test-reporter (0.5.0)
|
|
11
|
+
simplecov (>= 0.7.1, < 1.0.0)
|
|
12
|
+
diff-lcs (1.2.5)
|
|
13
|
+
docile (1.1.5)
|
|
14
|
+
json (1.8.3)
|
|
15
|
+
parser (2.3.1.0)
|
|
16
|
+
ast (~> 2.2)
|
|
17
|
+
powerpack (0.1.1)
|
|
18
|
+
rainbow (2.1.0)
|
|
19
|
+
rake (11.1.2)
|
|
20
|
+
rspec (3.4.0)
|
|
21
|
+
rspec-core (~> 3.4.0)
|
|
22
|
+
rspec-expectations (~> 3.4.0)
|
|
23
|
+
rspec-mocks (~> 3.4.0)
|
|
24
|
+
rspec-core (3.4.4)
|
|
25
|
+
rspec-support (~> 3.4.0)
|
|
26
|
+
rspec-expectations (3.4.0)
|
|
27
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
28
|
+
rspec-support (~> 3.4.0)
|
|
29
|
+
rspec-mocks (3.4.1)
|
|
30
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
31
|
+
rspec-support (~> 3.4.0)
|
|
32
|
+
rspec-support (3.4.1)
|
|
33
|
+
rubocop (0.40.0)
|
|
34
|
+
parser (>= 2.3.1.0, < 3.0)
|
|
35
|
+
powerpack (~> 0.1)
|
|
36
|
+
rainbow (>= 1.99.1, < 3.0)
|
|
37
|
+
ruby-progressbar (~> 1.7)
|
|
38
|
+
unicode-display_width (~> 1.0, >= 1.0.1)
|
|
39
|
+
ruby-progressbar (1.8.0)
|
|
40
|
+
simplecov (0.11.2)
|
|
41
|
+
docile (~> 1.1.0)
|
|
42
|
+
json (~> 1.8)
|
|
43
|
+
simplecov-html (~> 0.10.0)
|
|
44
|
+
simplecov-html (0.10.0)
|
|
45
|
+
unicode-display_width (1.0.5)
|
|
46
|
+
yard (0.8.7.6)
|
|
47
|
+
|
|
48
|
+
PLATFORMS
|
|
49
|
+
ruby
|
|
50
|
+
|
|
51
|
+
DEPENDENCIES
|
|
52
|
+
bundler (~> 1.12)
|
|
53
|
+
codeclimate-test-reporter
|
|
54
|
+
collapsium!
|
|
55
|
+
rake (~> 11.1)
|
|
56
|
+
rspec (~> 3.4)
|
|
57
|
+
rubocop (~> 0.40)
|
|
58
|
+
simplecov (~> 0.11)
|
|
59
|
+
yard (~> 0.8)
|
|
60
|
+
|
|
61
|
+
BUNDLED WITH
|
|
62
|
+
1.12.3
|
data/LICENSE
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
Copyright (c) Jens Finkhaeuser (http://finkhaeuser.de/) and other collapsium
|
|
2
|
+
contributors. All rights not covered below are reserved.
|
|
3
|
+
|
|
4
|
+
The MIT +no-false-attribs License (MITNFA)
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to
|
|
8
|
+
deal in the Software without restriction, including without limitation the
|
|
9
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
10
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in
|
|
14
|
+
all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
Distributions of all or part of the Software intended to be used by the
|
|
17
|
+
recipients as they would use the unmodified Software, containing modifications
|
|
18
|
+
that substantially alter, remove, or disable functionality of the Software,
|
|
19
|
+
outside of the documented configuration mechanisms provided by the Software,
|
|
20
|
+
shall be modified such that the Original Author's bug reporting email addresses
|
|
21
|
+
and urls are either replaced with the contact information of the parties
|
|
22
|
+
responsible for the changes, or removed entirely.
|
|
23
|
+
|
|
24
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
25
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
26
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
27
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
28
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
29
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
30
|
+
IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# collapsium
|
|
2
|
+
*Provides various Hash extensions, and an UberHash class that uses them all.*
|
|
3
|
+
|
|
4
|
+
Ruby's Hash is a pretty nice class, but various extensions are commonly (or not
|
|
5
|
+
so commonly) used to make it even more convenient. The most notable would
|
|
6
|
+
probably be [ActiveSupport::HashWithIndifferentAccess](http://apidock.com/rails/ActiveSupport/HashWithIndifferentAccess).
|
|
7
|
+
|
|
8
|
+
That example, unfortunately, has all the problems of requring the kitchen sink
|
|
9
|
+
that is ActiveSupport...
|
|
10
|
+
|
|
11
|
+
[](https://badge.fury.io/rb/collapsium)
|
|
12
|
+
[](https://travis-ci.org/jfinkhaeuser/collapsium)
|
|
13
|
+
[](https://codeclimate.com/github/jfinkhaeuser/collapsium)
|
|
14
|
+
[](https://codeclimate.com/github/jfinkhaeuser/collapsium/coverage)
|
|
15
|
+
|
|
16
|
+
# Functionality
|
|
17
|
+
|
|
18
|
+
- The `IndifferentAccess` module provides support for indifferent access via a
|
|
19
|
+
`#default_proc`:
|
|
20
|
+
|
|
21
|
+
```ruby
|
|
22
|
+
x = { foo: 42 }
|
|
23
|
+
x.default_proc = ::Collapsium::IndifferentAccess::DEFAULT_PROC
|
|
24
|
+
x['foo'] # => 42
|
|
25
|
+
```
|
|
26
|
+
- The `RecursiveMerge` module provides a `#recursive_merge` function which merges
|
|
27
|
+
Hashes recursively:
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
x = { foo: { bar: 42 } }
|
|
31
|
+
x.extend(::Collapsium::RecursiveMerge)
|
|
32
|
+
x.recursive_merge(foo: { baz: 'quux' })
|
|
33
|
+
# => {
|
|
34
|
+
# foo: {
|
|
35
|
+
# bar: 42,
|
|
36
|
+
# baz: 'quux',
|
|
37
|
+
# },
|
|
38
|
+
# }
|
|
39
|
+
```
|
|
40
|
+
- The `PathedAccess` module provides a pathed access method to nested Hashes:
|
|
41
|
+
|
|
42
|
+
```ruby
|
|
43
|
+
x = { "foo" => { "bar" => 42 } }
|
|
44
|
+
x.extend(::Collapsium::PathedAccess)
|
|
45
|
+
x["foo.bar"] # => 42
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Finally, the `UberHash` class just includes all of the above.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Rubocop
|
|
2
|
+
require 'rubocop/rake_task'
|
|
3
|
+
RuboCop::RakeTask.new(:rubocop)
|
|
4
|
+
|
|
5
|
+
# Rspec
|
|
6
|
+
require 'rspec/core/rake_task'
|
|
7
|
+
RSpec::Core::RakeTask.new(:rspec)
|
|
8
|
+
|
|
9
|
+
# Documentation
|
|
10
|
+
require 'yard'
|
|
11
|
+
YARD::Rake::YardocTask.new do |t|
|
|
12
|
+
t.files = ['lib/**/*.rb']
|
|
13
|
+
t.options = ['-m', 'markdown']
|
|
14
|
+
t.stats_options = ['--list-undoc']
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Combined test task
|
|
18
|
+
desc "Test all the things!"
|
|
19
|
+
task :test do
|
|
20
|
+
Rake::Task[:rubocop].invoke
|
|
21
|
+
Rake::Task[:rspec].invoke
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Default is the test task
|
|
25
|
+
task default: :test
|
data/collapsium.gemspec
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# collapsium
|
|
4
|
+
# https://github.com/jfinkhaeuser/collapsium
|
|
5
|
+
#
|
|
6
|
+
# Copyright (c) 2016 Jens Finkhaeuser and other collapsium contributors.
|
|
7
|
+
# All rights reserved.
|
|
8
|
+
#
|
|
9
|
+
|
|
10
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
11
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
12
|
+
require 'collapsium/version'
|
|
13
|
+
|
|
14
|
+
# rubocop:disable Style/UnneededPercentQ
|
|
15
|
+
# rubocop:disable Style/SpaceAroundOperators
|
|
16
|
+
Gem::Specification.new do |spec|
|
|
17
|
+
spec.name = "collapsium"
|
|
18
|
+
spec.version = Collapsium::VERSION
|
|
19
|
+
spec.authors = ["Jens Finkhaeuser"]
|
|
20
|
+
spec.email = ["jens@finkhaeuser.de"]
|
|
21
|
+
spec.description = %q(
|
|
22
|
+
Provides IndifferentAccess, RecursiveMerge, PathedAccess, etc.
|
|
23
|
+
)
|
|
24
|
+
spec.summary = %q(
|
|
25
|
+
Provides various Hash extensions, and an UberHash class that uses them all.
|
|
26
|
+
)
|
|
27
|
+
spec.homepage = "https://github.com/jfinkhaeuser/collapsium"
|
|
28
|
+
spec.license = "MITNFA"
|
|
29
|
+
|
|
30
|
+
spec.files = `git ls-files -z`.split("\x0")
|
|
31
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
32
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
33
|
+
spec.require_paths = ["lib"]
|
|
34
|
+
|
|
35
|
+
spec.required_ruby_version = '>= 2.0'
|
|
36
|
+
|
|
37
|
+
spec.add_development_dependency "bundler", "~> 1.12"
|
|
38
|
+
spec.add_development_dependency "rubocop", "~> 0.40"
|
|
39
|
+
spec.add_development_dependency "rake", "~> 11.1"
|
|
40
|
+
spec.add_development_dependency "rspec", "~> 3.4"
|
|
41
|
+
spec.add_development_dependency "simplecov", "~> 0.11"
|
|
42
|
+
spec.add_development_dependency "yard", "~> 0.8"
|
|
43
|
+
end
|
|
44
|
+
# rubocop:enable Style/SpaceAroundOperators
|
|
45
|
+
# rubocop:enable Style/UnneededPercentQ
|
data/lib/collapsium.rb
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# collapsium
|
|
4
|
+
# https://github.com/jfinkhaeuser/collapsium
|
|
5
|
+
#
|
|
6
|
+
# Copyright (c) 2016 Jens Finkhaeuser and other collapsium contributors.
|
|
7
|
+
# All rights reserved.
|
|
8
|
+
#
|
|
9
|
+
|
|
10
|
+
require 'collapsium/version'
|
|
11
|
+
|
|
12
|
+
require 'collapsium/recursive_merge'
|
|
13
|
+
require 'collapsium/indifferent_access'
|
|
14
|
+
require 'collapsium/pathed_access'
|
|
15
|
+
|
|
16
|
+
require 'collapsium/uber_hash'
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# collapsium
|
|
4
|
+
# https://github.com/jfinkhaeuser/collapsium
|
|
5
|
+
#
|
|
6
|
+
# Copyright (c) 2016 Jens Finkhaeuser and other collapsium contributors.
|
|
7
|
+
# All rights reserved.
|
|
8
|
+
#
|
|
9
|
+
|
|
10
|
+
module Collapsium
|
|
11
|
+
|
|
12
|
+
##
|
|
13
|
+
# Provides indifferent access to string/symbol keys in a Hash. That is,
|
|
14
|
+
# if your hash contains a string key, you can also access it via a symbol
|
|
15
|
+
# and vice versa.
|
|
16
|
+
module IndifferentAccess
|
|
17
|
+
|
|
18
|
+
##
|
|
19
|
+
# Set your Hash's #default_proc to DEFAULT_PROC, and you've got indifferent
|
|
20
|
+
# access.
|
|
21
|
+
DEFAULT_PROC = proc do |hash, key|
|
|
22
|
+
case key
|
|
23
|
+
when String
|
|
24
|
+
sym = key.to_sym
|
|
25
|
+
hash[sym] if hash.key?(sym)
|
|
26
|
+
when Symbol
|
|
27
|
+
str = key.to_s
|
|
28
|
+
hash[str] if hash.key?(str)
|
|
29
|
+
end
|
|
30
|
+
end.freeze
|
|
31
|
+
|
|
32
|
+
end # module IndifferentAccess
|
|
33
|
+
|
|
34
|
+
end # module Collapsium
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# collapsium
|
|
4
|
+
# https://github.com/jfinkhaeuser/collapsium
|
|
5
|
+
#
|
|
6
|
+
# Copyright (c) 2016 Jens Finkhaeuser and other collapsium contributors.
|
|
7
|
+
# All rights reserved.
|
|
8
|
+
#
|
|
9
|
+
|
|
10
|
+
module Collapsium
|
|
11
|
+
|
|
12
|
+
##
|
|
13
|
+
# The PathedAccess module can be used to extend Hash with pathed access
|
|
14
|
+
# on top of regular access, i.e. instead of `h["first"]["second"]` you can
|
|
15
|
+
# write `h["first.second"]`.
|
|
16
|
+
#
|
|
17
|
+
# The main benefit is much simpler code for accessing nested structured.
|
|
18
|
+
# For any given path, PathedAccess will return nil from `[]` if *any* of
|
|
19
|
+
# the path components do not exist.
|
|
20
|
+
#
|
|
21
|
+
# Similarly, intermediate nodes will be created when you write a value
|
|
22
|
+
# for a path.
|
|
23
|
+
module PathedAccess
|
|
24
|
+
|
|
25
|
+
# @return [String] the separator is the character or pattern splitting paths.
|
|
26
|
+
def separator
|
|
27
|
+
@separator ||= DEFAULT_SEPARATOR
|
|
28
|
+
return @separator
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @api private
|
|
32
|
+
# Methods redefined to support pathed read access.
|
|
33
|
+
READ_METHODS = [
|
|
34
|
+
:[], :default, :delete, :fetch, :has_key?, :include?, :key?, :member?,
|
|
35
|
+
].freeze
|
|
36
|
+
|
|
37
|
+
# @api private
|
|
38
|
+
# Methods redefined to support pathed write access.
|
|
39
|
+
WRITE_METHODS = [
|
|
40
|
+
:[]=, :store,
|
|
41
|
+
].freeze
|
|
42
|
+
|
|
43
|
+
# @api private
|
|
44
|
+
# Default path separator
|
|
45
|
+
DEFAULT_SEPARATOR = '.'.freeze
|
|
46
|
+
|
|
47
|
+
##
|
|
48
|
+
# @return [RegExp] the pattern to split paths at; based on `separator`
|
|
49
|
+
def split_pattern
|
|
50
|
+
/(?<!\\)#{Regexp.escape(separator)}/
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
(READ_METHODS + WRITE_METHODS).each do |method|
|
|
54
|
+
# Wrap all accessor functions to deal with paths
|
|
55
|
+
define_method(method) do |*args, &block|
|
|
56
|
+
# If there are no arguments, there's nothing to do with paths. Just
|
|
57
|
+
# delegate to the hash.
|
|
58
|
+
if args.empty?
|
|
59
|
+
return super(*args, &block)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# With any of the dispatch methods, we know that the first argument has
|
|
63
|
+
# to be a key. We'll try to split it by the path separator.
|
|
64
|
+
components = args[0].to_s.split(split_pattern)
|
|
65
|
+
loop do
|
|
66
|
+
if components.empty? or not components[0].empty?
|
|
67
|
+
break
|
|
68
|
+
end
|
|
69
|
+
components.shift
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# If there are no components, return self/the root
|
|
73
|
+
if components.empty?
|
|
74
|
+
return self
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# This is already the leaf-most Hash
|
|
78
|
+
if components.length == 1
|
|
79
|
+
# Weird edge case: if we didn't have to shift anything, then it's
|
|
80
|
+
# possible we inadvertently changed a symbol key into a string key,
|
|
81
|
+
# which could mean looking fails.
|
|
82
|
+
# We can detect that by comparing copy[0] to a symbolized version of
|
|
83
|
+
# components[0].
|
|
84
|
+
copy = args.dup
|
|
85
|
+
if copy[0] != components[0].to_sym
|
|
86
|
+
copy[0] = components[0]
|
|
87
|
+
end
|
|
88
|
+
return super(*copy, &block)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Deal with other paths. The frustrating part here is that for nested
|
|
92
|
+
# hashes, only this outermost one is guaranteed to know anything about
|
|
93
|
+
# path splitting, so we'll have to recurse down to the leaf here.
|
|
94
|
+
#
|
|
95
|
+
# For write methods, we need to create intermediary hashes.
|
|
96
|
+
leaf = recursive_fetch(components, self,
|
|
97
|
+
create: WRITE_METHODS.include?(method))
|
|
98
|
+
if leaf.is_a? Hash
|
|
99
|
+
leaf.default_proc = default_proc
|
|
100
|
+
end
|
|
101
|
+
if leaf.nil?
|
|
102
|
+
leaf = self
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# If we have a leaf, we want to send the requested method to that
|
|
106
|
+
# leaf.
|
|
107
|
+
copy = args.dup
|
|
108
|
+
copy[0] = components.last
|
|
109
|
+
return leaf.send(method, *copy, &block)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
private
|
|
114
|
+
|
|
115
|
+
##
|
|
116
|
+
# Given the path components, recursively fetch any but the last key.
|
|
117
|
+
def recursive_fetch(path, data, options = {})
|
|
118
|
+
# For the leaf element, we do nothing because that's where we want to
|
|
119
|
+
# dispatch to.
|
|
120
|
+
if path.length == 1
|
|
121
|
+
return data
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Split path into head and tail; for the next iteration, we'll look use only
|
|
125
|
+
# head, and pass tail on recursively.
|
|
126
|
+
head = path[0]
|
|
127
|
+
tail = path.slice(1, path.length)
|
|
128
|
+
|
|
129
|
+
# If we're a write function, then we need to create intermediary objects,
|
|
130
|
+
# i.e. what's at head if nothing is there.
|
|
131
|
+
if options[:create] and data[head].nil?
|
|
132
|
+
data[head] = {}
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Ok, recurse.
|
|
136
|
+
return recursive_fetch(tail, data[head], options)
|
|
137
|
+
end
|
|
138
|
+
end # module PathedAccess
|
|
139
|
+
end # module Collapsium
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# collapsium
|
|
4
|
+
# https://github.com/jfinkhaeuser/collapsium
|
|
5
|
+
#
|
|
6
|
+
# Copyright (c) 2016 Jens Finkhaeuser and other collapsium contributors.
|
|
7
|
+
# All rights reserved.
|
|
8
|
+
#
|
|
9
|
+
|
|
10
|
+
module Collapsium
|
|
11
|
+
##
|
|
12
|
+
# Provides recursive merge functions for hashes. Used in PathedHash.
|
|
13
|
+
module RecursiveMerge
|
|
14
|
+
##
|
|
15
|
+
# Recursively merge `:other` into this Hash.
|
|
16
|
+
#
|
|
17
|
+
# This starts by merging the leaf-most Hash entries. Arrays are merged
|
|
18
|
+
# by addition.
|
|
19
|
+
#
|
|
20
|
+
# For everything that's neither Hash or Array, if the `:overwrite`
|
|
21
|
+
# parameter is true, the entry from `:other` is used. Otherwise the entry
|
|
22
|
+
# from `:self` is used.
|
|
23
|
+
#
|
|
24
|
+
# @param other [Hash] the hash to merge into `:self`
|
|
25
|
+
# @param overwrite [Boolean] see method description.
|
|
26
|
+
def recursive_merge!(other, overwrite = true)
|
|
27
|
+
if other.nil?
|
|
28
|
+
return self
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
merger = proc do |_, v1, v2|
|
|
32
|
+
# rubocop:disable Style/GuardClause
|
|
33
|
+
if v1.is_a? Hash and v2.is_a? Hash
|
|
34
|
+
next v1.merge(v2, &merger)
|
|
35
|
+
elsif v1.is_a? Array and v2.is_a? Array
|
|
36
|
+
next v1 + v2
|
|
37
|
+
end
|
|
38
|
+
if overwrite
|
|
39
|
+
next v2
|
|
40
|
+
else
|
|
41
|
+
next v1
|
|
42
|
+
end
|
|
43
|
+
# rubocop:enable Style/GuardClause
|
|
44
|
+
end
|
|
45
|
+
merge!(other, &merger)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
##
|
|
49
|
+
# Same as `dup.recursive_merge!`
|
|
50
|
+
# @param (see #recursive_merge!)
|
|
51
|
+
def recursive_merge(other, overwrite = true)
|
|
52
|
+
copy = dup
|
|
53
|
+
copy.extend(RecursiveMerge)
|
|
54
|
+
return copy.recursive_merge!(other, overwrite)
|
|
55
|
+
end
|
|
56
|
+
end # module RecursiveMerge
|
|
57
|
+
end # module Collapsium
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# collapsium
|
|
4
|
+
# https://github.com/jfinkhaeuser/collapsium
|
|
5
|
+
#
|
|
6
|
+
# Copyright (c) 2016 Jens Finkhaeuser and other collapsium contributors.
|
|
7
|
+
# All rights reserved.
|
|
8
|
+
#
|
|
9
|
+
|
|
10
|
+
require 'collapsium/recursive_merge'
|
|
11
|
+
require 'collapsium/indifferent_access'
|
|
12
|
+
require 'collapsium/pathed_access'
|
|
13
|
+
|
|
14
|
+
module Collapsium
|
|
15
|
+
|
|
16
|
+
# A Hash that includes all the different Hash extensions in collapsium
|
|
17
|
+
class UberHash < Hash
|
|
18
|
+
include RecursiveMerge
|
|
19
|
+
include PathedAccess
|
|
20
|
+
|
|
21
|
+
def initialize(*args)
|
|
22
|
+
super
|
|
23
|
+
|
|
24
|
+
# Activate IndifferentAccess
|
|
25
|
+
self.default_proc = IndifferentAccess::DEFAULT_PROC
|
|
26
|
+
|
|
27
|
+
# Extra functionality: allow being initialized by a Hash
|
|
28
|
+
if args.empty? or not args[0].is_a?(Hash)
|
|
29
|
+
return
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
merge!(args[0])
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
end # module Collapsium
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# collapsium
|
|
4
|
+
# https://github.com/jfinkhaeuser/collapsium
|
|
5
|
+
#
|
|
6
|
+
# Copyright (c) 2016 Jens Finkhaeuser and other collapsium contributors.
|
|
7
|
+
# All rights reserved.
|
|
8
|
+
#
|
|
9
|
+
module Collapsium
|
|
10
|
+
# The current release version
|
|
11
|
+
VERSION = "0.1.0".freeze
|
|
12
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require_relative '../lib/collapsium/indifferent_access'
|
|
3
|
+
|
|
4
|
+
describe ::Collapsium::IndifferentAccess do
|
|
5
|
+
before :each do
|
|
6
|
+
@tester = {}
|
|
7
|
+
@tester.default_proc = ::Collapsium::IndifferentAccess::DEFAULT_PROC
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "allows accessing string keys via symbol" do
|
|
11
|
+
@tester["foo"] = 42
|
|
12
|
+
expect(@tester["foo"]).to eql 42
|
|
13
|
+
expect(@tester[:foo]).to eql 42
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "allows accessing symbol keys via strings" do
|
|
17
|
+
@tester[:foo] = 42
|
|
18
|
+
expect(@tester[:foo]).to eql 42
|
|
19
|
+
expect(@tester["foo"]).to eql 42
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "still works with other keys" do
|
|
23
|
+
@tester[42] = "foo"
|
|
24
|
+
expect(@tester[42]).to eql "foo"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require_relative '../lib/collapsium/pathed_access'
|
|
3
|
+
|
|
4
|
+
describe ::Collapsium::PathedAccess do
|
|
5
|
+
before :each do
|
|
6
|
+
@tester = {}
|
|
7
|
+
@tester.extend(::Collapsium::PathedAccess)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
describe "Hash-like" do
|
|
11
|
+
it "responds to Hash functions" do
|
|
12
|
+
[:invert, :delete, :fetch].each do |meth|
|
|
13
|
+
expect(@tester.respond_to?(meth)).to eql true
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "can be used like a Hash" do
|
|
18
|
+
@tester[:foo] = 42
|
|
19
|
+
inverted = @tester.invert
|
|
20
|
+
expect(inverted.empty?).to eql false
|
|
21
|
+
expect(inverted[42]).to eql :foo
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "delegates to Hash if it's nothing to do with paths" do
|
|
25
|
+
expect(@tester.default).to be_nil
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
describe "pathed access" do
|
|
30
|
+
it "can recursively read entries via a path" do
|
|
31
|
+
@tester["foo"] = 42
|
|
32
|
+
@tester["bar"] = {
|
|
33
|
+
"baz" => "quux",
|
|
34
|
+
"blah" => [1, 2],
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
expect(@tester["foo"]).to eql 42
|
|
38
|
+
expect(@tester["bar.baz"]).to eql "quux"
|
|
39
|
+
expect(@tester["bar.blah"]).to eql [1, 2]
|
|
40
|
+
|
|
41
|
+
expect(@tester["nope"]).to eql nil
|
|
42
|
+
expect(@tester["bar.nope"]).to eql nil
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "behaves consistently if in a path the first node cannot be found" do
|
|
46
|
+
@tester["foo"] = 42
|
|
47
|
+
|
|
48
|
+
expect(@tester["nope.bar"]).to eql nil
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "treats a single separator as the root" do
|
|
52
|
+
@tester["foo"] = 42
|
|
53
|
+
|
|
54
|
+
expect(@tester[@tester.separator]["foo"]).to eql 42
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "treats an empty path as the root" do
|
|
58
|
+
@tester["foo"] = 42
|
|
59
|
+
|
|
60
|
+
expect(@tester[""]["foo"]).to eql 42
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "can recursively write entries via a path" do
|
|
64
|
+
@tester["foo.bar"] = 42
|
|
65
|
+
expect(@tester["foo.bar"]).to eql 42
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "understands absolute paths (starting with separator)" do
|
|
69
|
+
@tester["foo"] = 42
|
|
70
|
+
@tester["bar"] = {
|
|
71
|
+
"baz" => "quux",
|
|
72
|
+
"blah" => [1, 2],
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
expect(@tester["bar.baz"]).to eql "quux"
|
|
76
|
+
expect(@tester[".bar.baz"]).to eql "quux"
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
describe "with indifferent access" do
|
|
81
|
+
before do
|
|
82
|
+
require_relative '../lib/collapsium/indifferent_access'
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "can write with indifferent access without overwriting" do
|
|
86
|
+
@tester[:foo] = {
|
|
87
|
+
bar: 42,
|
|
88
|
+
baz: 'quux',
|
|
89
|
+
}
|
|
90
|
+
@tester.default_proc = ::Collapsium::IndifferentAccess::DEFAULT_PROC
|
|
91
|
+
|
|
92
|
+
expect(@tester['foo.bar']).to eql 42
|
|
93
|
+
expect(@tester['foo.baz']).to eql 'quux'
|
|
94
|
+
|
|
95
|
+
@tester['foo.bar'] = 123
|
|
96
|
+
expect(@tester['foo.bar']).to eql 123
|
|
97
|
+
expect(@tester['foo.baz']).to eql 'quux'
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require_relative '../lib/collapsium/recursive_merge'
|
|
3
|
+
|
|
4
|
+
describe ::Collapsium::RecursiveMerge do
|
|
5
|
+
before :each do
|
|
6
|
+
@tester = {}
|
|
7
|
+
@tester.extend(::Collapsium::RecursiveMerge)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "handles a nil parameter well" do
|
|
11
|
+
x = @tester.recursive_merge(nil)
|
|
12
|
+
|
|
13
|
+
expect(x.is_a?(Hash)).to be_truthy
|
|
14
|
+
expect(x).to be_empty
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "merges simple values by overwriting by default" do
|
|
18
|
+
@tester[:foo] = 'old'
|
|
19
|
+
x = @tester.recursive_merge(foo: 'new')
|
|
20
|
+
|
|
21
|
+
expect(x[:foo]).to eql 'new'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "merges simple values by using the old value if requested" do
|
|
25
|
+
@tester[:foo] = 'old'
|
|
26
|
+
x = @tester.recursive_merge({ foo: 'new' }, false)
|
|
27
|
+
|
|
28
|
+
expect(x[:foo]).to eql 'old'
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "merges arrays by concatenation" do
|
|
32
|
+
@tester[:foo] = ['old']
|
|
33
|
+
x = @tester.recursive_merge(foo: ['new'])
|
|
34
|
+
|
|
35
|
+
expect(x[:foo].length).to eql 2
|
|
36
|
+
expect(x[:foo][0]).to eql 'old'
|
|
37
|
+
expect(x[:foo][1]).to eql 'new'
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "merges objects by recursing" do
|
|
41
|
+
@tester[:foo] = {
|
|
42
|
+
bar: 42,
|
|
43
|
+
baz: ['old'],
|
|
44
|
+
quux: {
|
|
45
|
+
something: 42,
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
@tester[:bar] = [1]
|
|
49
|
+
|
|
50
|
+
to_merge = {
|
|
51
|
+
foo: {
|
|
52
|
+
bar: 123, # should overwrite
|
|
53
|
+
baz: ['new'], # should concatenate
|
|
54
|
+
quux: { # should merge
|
|
55
|
+
another: 123,
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
bar: [2],
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
x = @tester.recursive_merge(to_merge)
|
|
62
|
+
|
|
63
|
+
expect(x[:foo][:bar]).to eql 123
|
|
64
|
+
expect(x[:foo][:baz].length).to eql 2
|
|
65
|
+
expect(x[:foo][:quux][:something]).to eql 42
|
|
66
|
+
expect(x[:foo][:quux][:another]).to eql 123
|
|
67
|
+
|
|
68
|
+
expect(x[:bar].length).to eql 2
|
|
69
|
+
end
|
|
70
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require_relative '../lib/collapsium/uber_hash'
|
|
3
|
+
|
|
4
|
+
describe Collapsium::UberHash do
|
|
5
|
+
it "has recursive_merge support" do
|
|
6
|
+
x = ::Collapsium::UberHash.new(foo: [1])
|
|
7
|
+
|
|
8
|
+
# Interface expecations
|
|
9
|
+
expect(x.respond_to?(:recursive_merge)).to be_truthy
|
|
10
|
+
expect(x.respond_to?(:recursive_merge!)).to be_truthy
|
|
11
|
+
|
|
12
|
+
# Behaviour expectations
|
|
13
|
+
x.recursive_merge!(foo: [2])
|
|
14
|
+
expect(x[:foo].length).to eql 2
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "has pathed access" do
|
|
18
|
+
x = ::Collapsium::UberHash.new(
|
|
19
|
+
"foo" => {
|
|
20
|
+
"bar" => 42,
|
|
21
|
+
}
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
# Interface expecations
|
|
25
|
+
expect(x.respond_to?(:separator)).to be_truthy
|
|
26
|
+
expect(x.respond_to?(:split_pattern)).to be_truthy
|
|
27
|
+
|
|
28
|
+
# Behaviour expectations
|
|
29
|
+
expect(x["foo.bar"]).to eql 42
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "has indifferent access" do
|
|
33
|
+
x = ::Collapsium::UberHash.new(foo: 42)
|
|
34
|
+
expect(x['foo']).to eql 42
|
|
35
|
+
|
|
36
|
+
x = ::Collapsium::UberHash.new('foo' => 42)
|
|
37
|
+
expect(x[:foo]).to eql 42
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "can be initialized without arguments" do
|
|
41
|
+
x = ::Collapsium::UberHash.new
|
|
42
|
+
expect(x.empty?).to be_truthy
|
|
43
|
+
end
|
|
44
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: collapsium
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Jens Finkhaeuser
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2016-05-11 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.12'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.12'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rubocop
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0.40'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0.40'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rake
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '11.1'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '11.1'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rspec
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '3.4'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '3.4'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: simplecov
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0.11'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0.11'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: yard
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - "~>"
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '0.8'
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - "~>"
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '0.8'
|
|
97
|
+
description: "\n Provides IndifferentAccess, RecursiveMerge, PathedAccess, etc.\n
|
|
98
|
+
\ "
|
|
99
|
+
email:
|
|
100
|
+
- jens@finkhaeuser.de
|
|
101
|
+
executables: []
|
|
102
|
+
extensions: []
|
|
103
|
+
extra_rdoc_files: []
|
|
104
|
+
files:
|
|
105
|
+
- ".codeclimate.yml"
|
|
106
|
+
- ".gitignore"
|
|
107
|
+
- ".rspec"
|
|
108
|
+
- ".rubocop.yml"
|
|
109
|
+
- ".travis.yml"
|
|
110
|
+
- Gemfile
|
|
111
|
+
- Gemfile.lock
|
|
112
|
+
- LICENSE
|
|
113
|
+
- README.md
|
|
114
|
+
- Rakefile
|
|
115
|
+
- collapsium.gemspec
|
|
116
|
+
- lib/collapsium.rb
|
|
117
|
+
- lib/collapsium/indifferent_access.rb
|
|
118
|
+
- lib/collapsium/pathed_access.rb
|
|
119
|
+
- lib/collapsium/recursive_merge.rb
|
|
120
|
+
- lib/collapsium/uber_hash.rb
|
|
121
|
+
- lib/collapsium/version.rb
|
|
122
|
+
- spec/indifferent_access_spec.rb
|
|
123
|
+
- spec/pathed_access_spec.rb
|
|
124
|
+
- spec/recursive_merge_spec.rb
|
|
125
|
+
- spec/spec_helper.rb
|
|
126
|
+
- spec/uber_hash_spec.rb
|
|
127
|
+
homepage: https://github.com/jfinkhaeuser/collapsium
|
|
128
|
+
licenses:
|
|
129
|
+
- MITNFA
|
|
130
|
+
metadata: {}
|
|
131
|
+
post_install_message:
|
|
132
|
+
rdoc_options: []
|
|
133
|
+
require_paths:
|
|
134
|
+
- lib
|
|
135
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
136
|
+
requirements:
|
|
137
|
+
- - ">="
|
|
138
|
+
- !ruby/object:Gem::Version
|
|
139
|
+
version: '2.0'
|
|
140
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
141
|
+
requirements:
|
|
142
|
+
- - ">="
|
|
143
|
+
- !ruby/object:Gem::Version
|
|
144
|
+
version: '0'
|
|
145
|
+
requirements: []
|
|
146
|
+
rubyforge_project:
|
|
147
|
+
rubygems_version: 2.4.5.1
|
|
148
|
+
signing_key:
|
|
149
|
+
specification_version: 4
|
|
150
|
+
summary: Provides various Hash extensions, and an UberHash class that uses them all.
|
|
151
|
+
test_files:
|
|
152
|
+
- spec/indifferent_access_spec.rb
|
|
153
|
+
- spec/pathed_access_spec.rb
|
|
154
|
+
- spec/recursive_merge_spec.rb
|
|
155
|
+
- spec/spec_helper.rb
|
|
156
|
+
- spec/uber_hash_spec.rb
|
|
157
|
+
has_rdoc:
|