hashie 3.4.3 → 3.4.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +226 -60
- data/CONTRIBUTING.md +11 -1
- data/README.md +29 -8
- data/UPGRADING.md +11 -0
- data/hashie.gemspec +3 -3
- data/lib/hashie/clash.rb +12 -11
- data/lib/hashie/extensions/coercion.rb +4 -2
- data/lib/hashie/extensions/deep_locate.rb +21 -15
- data/lib/hashie/extensions/ignore_undeclared.rb +5 -2
- data/lib/hashie/extensions/indifferent_access.rb +8 -0
- data/lib/hashie/extensions/method_access.rb +30 -5
- data/lib/hashie/mash.rb +7 -1
- data/lib/hashie/version.rb +1 -1
- data/spec/hashie/clash_spec.rb +24 -2
- data/spec/hashie/dash_spec.rb +23 -0
- data/spec/hashie/extensions/coercion_spec.rb +7 -7
- data/spec/hashie/extensions/deep_find_spec.rb +68 -0
- data/spec/hashie/extensions/deep_locate_spec.rb +13 -0
- data/spec/hashie/extensions/ignore_undeclared_spec.rb +2 -1
- data/spec/hashie/extensions/indifferent_access_spec.rb +31 -5
- data/spec/hashie/extensions/indifferent_access_with_rails_hwia_spec.rb +1 -1
- data/spec/hashie/extensions/method_access_spec.rb +7 -3
- data/spec/hashie/hash_spec.rb +6 -6
- data/spec/hashie/mash_spec.rb +20 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 08dd1e6f13c8a218c2d8417c194f598e7b063e34
|
4
|
+
data.tar.gz: 2a3431f1435c2cc7fae475303d8eaa3e0c68f709
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f802e665c81b36ff942f27f500ab7928db9cfa1812a74ecccdf68bcbb2ef3c4df7c16c6c8ff9e44b9bc62246474a8a0027092f07ed1f92c92ef4793fb0e8bc53
|
7
|
+
data.tar.gz: d1fb7562ac07a170355729e8dbbaa0ceee73c6307a7175109363d8b95e823db45461693d7469b28c86616090dfd2bfc1ce984296db00c7b4511d54feca6f31b5
|
data/CHANGELOG.md
CHANGED
@@ -1,154 +1,320 @@
|
|
1
|
-
|
1
|
+
# Change Log
|
2
2
|
|
3
|
+
All notable changes to this project will be documented in this file. This
|
4
|
+
project adheres to [Semantic Versioning 2.0.0][semver]. Any violations of this
|
5
|
+
scheme are considered to be bugs.
|
6
|
+
|
7
|
+
[semver]: http://semver.org/spec/v2.0.0.html
|
8
|
+
|
9
|
+
## [3.4.4] - 2016-04-29
|
10
|
+
|
11
|
+
[3.4.4]: https://github.com/intridea/hashie/compare/v3.4.3...v3.4.4
|
12
|
+
|
13
|
+
### Added
|
14
|
+
|
15
|
+
* [#349](https://github.com/intridea/hashie/pull/349): Convert `Hashie::Mash#dig` arguments for Ruby 2.3.0 - [@k0kubun](https://github.com/k0kubun).
|
16
|
+
|
17
|
+
### Fixed
|
18
|
+
|
19
|
+
* [#240](https://github.com/intridea/hashie/pull/240): Fixed nesting twice with Clash keys - [@bartoszkopinski](https://github.com/bartoszkopinski).
|
20
|
+
* [#317](https://github.com/intridea/hashie/pull/317): Ensure `Hashie::Extensions::MethodQuery` methods return boolean values - [@michaelherold](https://github.com/michaelherold).
|
21
|
+
* [#319](https://github.com/intridea/hashie/pull/319): Fix a regression from 3.4.1 where `Hashie::Extensions::DeepFind` is no longer indifference-aware - [@michaelherold](https://github.com/michaelherold).
|
22
|
+
* [#322](https://github.com/intridea/hashie/pull/322): Fixed `reverse_merge` issue with `Mash` subclasses - [@marshall-lee](https://github.com/marshall-lee).
|
23
|
+
* [#346](https://github.com/intridea/hashie/pull/346): Fixed `merge` breaking indifferent access - [@docwhat](https://github.com/docwhat), [@michaelherold](https://github.com/michaelherold).
|
24
|
+
* [#350](https://github.com/intridea/hashie/pull/350): Fixed from string translations used with `IgnoreUndeclared` - [@marshall-lee](https://github.com/marshall-lee).
|
25
|
+
|
26
|
+
## [3.4.3] - 2015-10-25
|
27
|
+
|
28
|
+
[3.4.3]: https://github.com/intridea/hashie/compare/v3.4.2...v3.4.3
|
29
|
+
|
30
|
+
### Added
|
31
|
+
|
32
|
+
* [#306](https://github.com/intridea/hashie/pull/306): Added `Hashie::Extensions::Dash::Coercion` - [@marshall-lee](https://github.com/marshall-lee).
|
3
33
|
* [#314](https://github.com/intridea/hashie/pull/314): Added a `StrictKeyAccess` extension that will raise an error whenever a key is accessed that does not exist in the hash - [@pboling](https://github.com/pboling).
|
34
|
+
|
35
|
+
### Fixed
|
36
|
+
|
4
37
|
* [#304](https://github.com/intridea/hashie/pull/304): Ensured compatibility of `Hash` extensions with singleton objects - [@regexident](https://github.com/regexident).
|
5
|
-
* [#306](https://github.com/intridea/hashie/pull/306): Added `Hashie::Extensions::Dash::Coercion` - [@marshall-lee](https://github.com/marshall-lee).
|
6
38
|
* [#310](https://github.com/intridea/hashie/pull/310): Fixed `Hashie::Extensions::SafeAssignment` bug with private methods - [@marshall-lee](https://github.com/marshall-lee).
|
39
|
+
|
40
|
+
### Miscellaneous
|
41
|
+
|
7
42
|
* [#313](https://github.com/intridea/hashie/pull/313): Restrict pending spec to only Ruby versions 2.2.0-2.2.2 - [@pboling](https://github.com/pboling).
|
8
43
|
* [#315](https://github.com/intridea/hashie/pull/315): Default `bin/` scripts: `console` and `setup` - [@pboling](https://github.com/pboling).
|
9
44
|
|
10
|
-
## 3.4.2
|
45
|
+
## [3.4.2] - 2015-06-02
|
46
|
+
|
47
|
+
[3.4.2]: https://github.com/intridea/hashie/compare/v3.4.1...v3.4.2
|
48
|
+
|
49
|
+
### Added
|
11
50
|
|
12
|
-
* [#292](https://github.com/intridea/hashie/pull/292): Removed `Mash#id` and `Mash#type` - [@jrochkind](https://github.com/jrochkind).
|
13
51
|
* [#297](https://github.com/intridea/hashie/pull/297): Extracted `Trash`'s behavior into a new `Dash::PropertyTranslation` extension - [@michaelherold](https://github.com/michaelherold).
|
14
52
|
|
15
|
-
|
53
|
+
### Removed
|
54
|
+
|
55
|
+
* [#292](https://github.com/intridea/hashie/pull/292): Removed `Mash#id` and `Mash#type` - [@jrochkind](https://github.com/jrochkind).
|
56
|
+
|
57
|
+
## [3.4.1] - 2015-03-31
|
58
|
+
|
59
|
+
[3.4.1]: https://github.com/intridea/hashie/compare/v3.4.0...v3.4.1
|
60
|
+
|
61
|
+
### Added
|
16
62
|
|
17
63
|
* [#269](https://github.com/intridea/hashie/pull/272): Added Hashie::Extensions::DeepLocate - [@msievers](https://github.com/msievers).
|
18
|
-
* [#270](https://github.com/intridea/hashie/pull/277): Fixed ArgumentError raised when using IndifferentAccess and HashWithIndifferentAccess - [@gardenofwine](https://github.com/gardenofwine).
|
19
64
|
* [#281](https://github.com/intridea/hashie/pull/281): Added #reverse_merge to Mash to override ActiveSupport's version - [@mgold](https://github.com/mgold).
|
65
|
+
|
66
|
+
### Fixed
|
67
|
+
|
68
|
+
* [#270](https://github.com/intridea/hashie/pull/277): Fixed ArgumentError raised when using IndifferentAccess and HashWithIndifferentAccess - [@gardenofwine](https://github.com/gardenofwine).
|
20
69
|
* [#282](https://github.com/intridea/hashie/pull/282): Fixed coercions in a subclass accumulating in the superclass - [@maxlinc](https://github.com/maxlinc), [@martinstreicher](https://github.com/martinstreicher).
|
21
70
|
|
22
|
-
## 3.4.0
|
71
|
+
## [3.4.0] - 2015-02-02
|
72
|
+
|
73
|
+
[3.4.0]: https://github.com/intridea/hashie/compare/v3.3.2...v3.4.0
|
74
|
+
|
75
|
+
### Added
|
23
76
|
|
24
|
-
* [#271](https://github.com/intridea/hashie/pull/271): Added ability to define defaults based on current hash - [@gregory](https://github.com/gregory).
|
25
|
-
* [#247](https://github.com/intridea/hashie/pull/247): Fixed #stringify_keys and #symbolize_keys collision with ActiveSupport - [@bartoszkopinski](https://github.com/bartoszkopinski).
|
26
|
-
* [#249](https://github.com/intridea/hashie/pull/249): SafeAssignment will now also protect hash-style assignments - [@jrochkind](https://github.com/jrochkind).
|
27
77
|
* [#251](https://github.com/intridea/hashie/pull/251): Added block support to indifferent access #fetch - [@jgraichen](https://github.com/jgraichen).
|
28
78
|
* [#252](https://github.com/intridea/hashie/pull/252): Added support for conditionally required Hashie::Dash attributes - [@ccashwell](https://github.com/ccashwell).
|
79
|
+
* [#254](https://github.com/intridea/hashie/pull/254): Added public utility methods for stringify and symbolize keys - [@maxlinc](https://github.com/maxlinc).
|
80
|
+
* [#260](https://github.com/intridea/hashie/pull/260): Added block support to Extensions::DeepMerge - [@galathius](https://github.com/galathius).
|
81
|
+
* [#271](https://github.com/intridea/hashie/pull/271): Added ability to define defaults based on current hash - [@gregory](https://github.com/gregory).
|
82
|
+
|
83
|
+
### Changed
|
84
|
+
|
85
|
+
* [#249](https://github.com/intridea/hashie/pull/249): SafeAssignment will now also protect hash-style assignments - [@jrochkind](https://github.com/jrochkind).
|
86
|
+
* [#264](https://github.com/intridea/hashie/pull/264): Methods such as abc? return true/false with Hashie::Extensions::MethodReader - [@Zloy](https://github.com/Zloy).
|
87
|
+
|
88
|
+
### Fixed
|
89
|
+
|
90
|
+
* [#247](https://github.com/intridea/hashie/pull/247): Fixed #stringify_keys and #symbolize_keys collision with ActiveSupport - [@bartoszkopinski](https://github.com/bartoszkopinski).
|
29
91
|
* [#256](https://github.com/intridea/hashie/pull/256): Inherit key coercions - [@Erol](https://github.com/Erol).
|
30
92
|
* [#259](https://github.com/intridea/hashie/pull/259): Fixed handling of default proc values in Mash - [@Erol](https://github.com/Erol).
|
31
|
-
* [#260](https://github.com/intridea/hashie/pull/260): Added block support to Extensions::DeepMerge - [@galathius](https://github.com/galathius).
|
32
|
-
* [#254](https://github.com/intridea/hashie/pull/254): Added public utility methods for stringify and symbolize keys - [@maxlinc](https://github.com/maxlinc).
|
33
93
|
* [#261](https://github.com/intridea/hashie/pull/261): Fixed bug where Dash.property modifies argument object - [@d-tw](https://github.com/d-tw).
|
34
|
-
* [#264](https://github.com/intridea/hashie/pull/264): Methods such as abc? return true/false with Hashie::Extensions::MethodReader - [@Zloy](https://github.com/Zloy).
|
35
94
|
* [#269](https://github.com/intridea/hashie/pull/269): Add #extractable_options? so ActiveSupport Array#extract_options! can extract it - [@ridiculous](https://github.com/ridiculous).
|
36
95
|
|
37
|
-
## 3.3.2
|
96
|
+
## [3.3.2] - 2014-11-26
|
97
|
+
|
98
|
+
[3.3.2]: https://github.com/intridea/hashie/compare/v3.3.1...v3.3.2
|
99
|
+
|
100
|
+
### Added
|
38
101
|
|
39
|
-
* [#233](https://github.com/intridea/hashie/pull/233): Custom error messages for required properties in Hashie::Dash subclasses - [@joss](https://github.com/joss).
|
40
102
|
* [#231](https://github.com/intridea/hashie/pull/231): Added support for coercion on class type that inherit from Hash - [@gregory](https://github.com/gregory).
|
41
|
-
* [#
|
42
|
-
* [#224](https://github.com/intridea/hashie/pull/224): Merging Hashie::Mash now correctly only calls the block on duplicate values - [@amysutedja](https://github.com/amysutedja).
|
43
|
-
* [#221](https://github.com/intridea/hashie/pull/221): Reduce amount of allocated objects on calls with suffixes in Hashie::Mash - [@kubum](https://github.com/kubum).
|
103
|
+
* [#233](https://github.com/intridea/hashie/pull/233): Custom error messages for required properties in Hashie::Dash subclasses - [@joss](https://github.com/joss).
|
44
104
|
* [#245](https://github.com/intridea/hashie/pull/245): Added Hashie::Extensions::MethodAccessWithOverride to autoloads - [@Fritzinger](https://github.com/Fritzinger).
|
45
105
|
|
46
|
-
|
106
|
+
### Fixed
|
107
|
+
|
108
|
+
* [#221](https://github.com/intridea/hashie/pull/221): Reduce amount of allocated objects on calls with suffixes in Hashie::Mash - [@kubum](https://github.com/kubum).
|
109
|
+
* [#224](https://github.com/intridea/hashie/pull/224): Merging Hashie::Mash now correctly only calls the block on duplicate values - [@amysutedja](https://github.com/amysutedja).
|
110
|
+
* [#228](https://github.com/intridea/hashie/pull/228): Made Hashie::Extensions::Parsers::YamlErbParser pass template filename to ERB - [@jperville](https://github.com/jperville).
|
111
|
+
|
112
|
+
## [3.3.1] - 2014-08-26
|
113
|
+
|
114
|
+
[3.3.1]: https://github.com/intridea/hashie/compare/v3.3.0...v3.3.1
|
115
|
+
|
116
|
+
### Added
|
47
117
|
|
48
118
|
* [#183](https://github.com/intridea/hashie/pull/183): Added Mash#load with YAML file support - [@gregory](https://github.com/gregory).
|
49
|
-
* [#195](https://github.com/intridea/hashie/pull/195): Ensure that the same object is returned after injecting IndifferentAccess - [@michaelherold](https://github.com/michaelherold).
|
50
|
-
* [#201](https://github.com/intridea/hashie/pull/201): Hashie::Trash transforms can be inherited - [@fobocaster](https://github.com/fobocaster).
|
51
119
|
* [#189](https://github.com/intridea/hashie/pull/189): Added Rash#fetch - [@medcat](https://github.com/medcat).
|
52
|
-
* [#200](https://github.com/intridea/hashie/pull/200): Improved coercion: primitives and error handling - [@maxlinc](https://github.com/maxlinc).
|
53
120
|
* [#204](https://github.com/intridea/hashie/pull/204): Added Hashie::Extensions::MethodOverridingWriter and MethodAccessWithOverride - [@michaelherold](https://github.com/michaelherold).
|
54
121
|
* [#205](http://github.com/intridea/hashie/pull/205): Added Hashie::Extensions::Mash::SafeAssignment - [@michaelherold](https://github.com/michaelherold).
|
55
|
-
* [#206](http://github.com/intridea/hashie/pull/206): Fixed stack overflow from repetitively including coercion in subclasses - [@michaelherold](https://github.com/michaelherold).
|
56
|
-
* [#207](http://github.com/intridea/hashie/pull/207): Fixed inheritance of transformations in Trash - [@fobocaster](https://github.com/fobocaster).
|
57
122
|
* [#209](http://github.com/intridea/hashie/pull/209): Added Hashie::Extensions::DeepFind - [@michaelherold](https://github.com/michaelherold).
|
123
|
+
|
124
|
+
### Fixed
|
125
|
+
|
58
126
|
* [#69](https://github.com/intridea/hashie/pull/69): Fixed regression in assigning multiple properties in Hashie::Trash - [@michaelherold](https://github.com/michaelherold), [@einzige](https://github.com/einzige), [@dblock](https://github.com/dblock).
|
127
|
+
* [#195](https://github.com/intridea/hashie/pull/195): Ensure that the same object is returned after injecting IndifferentAccess - [@michaelherold](https://github.com/michaelherold).
|
128
|
+
* [#201](https://github.com/intridea/hashie/pull/201): Hashie::Trash transforms can be inherited - [@fobocaster](https://github.com/fobocaster).
|
129
|
+
* [#200](https://github.com/intridea/hashie/pull/200): Improved coercion: primitives and error handling - [@maxlinc](https://github.com/maxlinc).
|
130
|
+
* [#206](http://github.com/intridea/hashie/pull/206): Fixed stack overflow from repetitively including coercion in subclasses - [@michaelherold](https://github.com/michaelherold).
|
131
|
+
* [#207](http://github.com/intridea/hashie/pull/207): Fixed inheritance of transformations in Trash - [@fobocaster](https://github.com/fobocaster).
|
59
132
|
|
60
|
-
## 3.2.0
|
133
|
+
## [3.2.0] - 2014-07-10
|
134
|
+
|
135
|
+
[3.2.0]: https://github.com/intridea/hashie/compare/v3.1.0...v3.2.0
|
136
|
+
|
137
|
+
### Added
|
61
138
|
|
62
|
-
* [#164](https://github.com/intridea/hashie/pull/164), [#165](https://github.com/intridea/hashie/pull/165), [#166](https://github.com/intridea/hashie/pull/166): Fixed stack overflow when coercing mashes that contain ActiveSupport::HashWithIndifferentAccess values - [@numinit](https://github.com/numinit), [@kgrz](https://github.com/kgrz).
|
63
139
|
* [#177](https://github.com/intridea/hashie/pull/177): Added support for coercing enumerables and collections - [@gregory](https://github.com/gregory).
|
140
|
+
|
141
|
+
### Changed
|
142
|
+
|
64
143
|
* [#179](https://github.com/intridea/hashie/pull/179): Mash#values_at will convert each key before doing the lookup - [@nahiluhmot](https://github.com/nahiluhmot).
|
65
144
|
* [#184](https://github.com/intridea/hashie/pull/184): Allow ranges on Rash to match all Numeric types - [@medcat](https://github.com/medcat).
|
145
|
+
|
146
|
+
### Fixed
|
147
|
+
|
148
|
+
* [#164](https://github.com/intridea/hashie/pull/164), [#165](https://github.com/intridea/hashie/pull/165), [#166](https://github.com/intridea/hashie/pull/166): Fixed stack overflow when coercing mashes that contain ActiveSupport::HashWithIndifferentAccess values - [@numinit](https://github.com/numinit), [@kgrz](https://github.com/kgrz).
|
66
149
|
* [#187](https://github.com/intridea/hashie/pull/187): Automatically require version - [@medcat](https://github.com/medcat).
|
67
150
|
* [#190](https://github.com/intridea/hashie/issues/190): Fixed `coerce_key` with `from` Trash feature and Coercion extension - [@gregory](https://github.com/gregory).
|
68
151
|
* [#192](https://github.com/intridea/hashie/pull/192): Fixed StringifyKeys#stringify_keys! to recursively stringify keys of embedded ::Hash types - [@dblock](https://github.com/dblock).
|
69
152
|
|
70
|
-
## 3.1.0
|
153
|
+
## [3.1.0] - 2014-06-25
|
154
|
+
|
155
|
+
[3.1.0]: https://github.com/intridea/hashie/compare/v3.0.0...v3.1.0
|
156
|
+
|
157
|
+
### Added
|
158
|
+
|
159
|
+
* [#172](https://github.com/intridea/hashie/pull/172): Added Dash and Trash#update_attributes! - [@gregory](https://github.com/gregory).
|
160
|
+
|
161
|
+
### Changed
|
71
162
|
|
72
163
|
* [#169](https://github.com/intridea/hashie/pull/169): Hash#to_hash will also convert nested objects that implement to_hash - [@gregory](https://github.com/gregory).
|
164
|
+
* [#173](https://github.com/intridea/hashie/pull/173): Auto include Dash::IndifferentAccess when IndifferentAccess is included in Dash - [@gregory](https://github.com/gregory).
|
165
|
+
|
166
|
+
### Fixed
|
167
|
+
|
73
168
|
* [#171](https://github.com/intridea/hashie/pull/171): Include Trash and Dash class name when raising `NoMethodError` - [@gregory](https://github.com/gregory).
|
74
|
-
* [#172](https://github.com/intridea/hashie/pull/172): Added Dash and Trash#update_attributes! - [@gregory](https://github.com/gregory).
|
75
|
-
* [#173](https://github.com/intridea/hashie/pull/173): Auto include Dash::IndifferentAccess when IndiferentAccess is included in Dash - [@gregory](https://github.com/gregory).
|
76
169
|
* [#174](https://github.com/intridea/hashie/pull/174): Fixed `from` and `transform_with` Trash features when IndifferentAccess is included - [@gregory](https://github.com/gregory).
|
77
170
|
|
78
|
-
## 3.0.0
|
171
|
+
## [3.0.0] - 2014-06-03
|
172
|
+
|
173
|
+
[3.0.0]: https://github.com/intridea/hashie/compare/v2.1.2...v3.0.0
|
79
174
|
|
80
175
|
**Note:** This version introduces several backward incompatible API changes. See [UPGRADING](UPGRADING.md) for details.
|
81
176
|
|
82
|
-
|
83
|
-
|
177
|
+
### Added
|
178
|
+
|
179
|
+
* [#149](https://github.com/intridea/hashie/issues/149): Allow IgnoreUndeclared and DeepMerge to be used with undeclared properties - [@jhaesus](https://github.com/jhaesus).
|
180
|
+
|
181
|
+
### Changed
|
182
|
+
|
84
183
|
* [#152](https://github.com/intridea/hashie/pull/152): Do not convert keys to String in Hashie::Dash and Hashie::Trash, use Hashie::Extensions::Dash::IndifferentAccess to achieve backward compatible behavior - [@dblock](https://github.com/dblock).
|
85
184
|
* [#152](https://github.com/intridea/hashie/pull/152): Do not automatically stringify keys in Hashie::Hash#to_hash, pass `:stringify_keys` to achieve backward compatible behavior - [@dblock](https://github.com/dblock).
|
185
|
+
|
186
|
+
### Fixed
|
187
|
+
|
188
|
+
* [#146](https://github.com/intridea/hashie/issues/146): Mash#respond_to? inconsistent with #method_missing and does not respond to #permitted? - [@dblock](https://github.com/dblock).
|
86
189
|
* [#148](https://github.com/intridea/hashie/pull/148): Consolidated Hashie::Hash#stringify_keys implementation - [@dblock](https://github.com/dblock).
|
87
|
-
* [#
|
190
|
+
* [#159](https://github.com/intridea/hashie/pull/159): Handle nil intermediate object on deep fetch - [@stephenaument](https://github.com/stephenaument).
|
191
|
+
|
192
|
+
## [2.1.2] - 2014-05-12
|
88
193
|
|
89
|
-
|
194
|
+
[2.1.2]: https://github.com/intridea/hashie/compare/v2.1.1...v2.1.2
|
195
|
+
|
196
|
+
### Changed
|
90
197
|
|
91
198
|
* [#169](https://github.com/intridea/hashie/pull/169): Hash#to_hash will also convert nested objects that implement `to_hash` - [@gregory](https://github.com/gregory).
|
92
199
|
|
93
|
-
## 2.1.1
|
200
|
+
## [2.1.1] - 2014-04-12
|
201
|
+
|
202
|
+
[2.1.1]: https://github.com/intridea/hashie/compare/v2.1.0...v2.1.1
|
203
|
+
|
204
|
+
### Fixed
|
94
205
|
|
206
|
+
* [#131](https://github.com/intridea/hashie/pull/131): Added IgnoreUndeclared, an extension to silently ignore undeclared properties at intialization - [@righi](https://github.com/righi).
|
207
|
+
* [#138](https://github.com/intridea/hashie/pull/138): Added Hashie::Rash, a hash whose keys can be regular expressions or ranges - [@epitron](https://github.com/epitron).
|
95
208
|
* [#144](https://github.com/intridea/hashie/issues/144): Fixed regression invoking `to_hash` with no parameters - [@mbleigh](https://github.com/mbleigh).
|
96
209
|
|
97
|
-
## 2.1.0
|
210
|
+
## [2.1.0] - 2014-04-06
|
211
|
+
|
212
|
+
[2.1.0]: https://github.com/intridea/hashie/compare/v2.0.5...v2.1.0
|
213
|
+
|
214
|
+
### Added
|
98
215
|
|
99
216
|
* [#134](https://github.com/intridea/hashie/pull/134): Add deep_fetch extension for nested access - [@tylerdooling](https://github.com/tylerdooling).
|
217
|
+
|
218
|
+
### Changed
|
219
|
+
|
220
|
+
* [#89](https://github.com/intridea/hashie/issues/89): Do not respond to every method with suffix in Hashie::Mash, fixes Rails strong_parameters - [@Maxim-Filimonov](https://github.com/Maxim-Filimonov).
|
221
|
+
|
222
|
+
### Removed
|
223
|
+
|
100
224
|
* Removed support for Ruby 1.8.7 - [@dblock](https://github.com/dblock).
|
101
|
-
* Ruby style now enforced with Rubocop - [@dblock](https://github.com/dblock).
|
102
|
-
* [#138](https://github.com/intridea/hashie/pull/138): Added Hashie::Rash, a hash whose keys can be regular expressions or ranges - [@epitron](https://github.com/epitron).
|
103
|
-
* [#131](https://github.com/intridea/hashie/pull/131): Added IgnoreUndeclared, an extension to silently ignore undeclared properties at intialization - [@righi](https://github.com/righi).
|
104
225
|
* [#136](https://github.com/intridea/hashie/issues/136): Removed Hashie::Extensions::Structure - [@markiz](https://github.com/markiz).
|
105
|
-
|
226
|
+
|
227
|
+
### Fixed
|
228
|
+
|
106
229
|
* [#69](https://github.com/intridea/hashie/issues/69): Fixed assigning multiple properties in Hashie::Trash - [@einzige](https://github.com/einzige).
|
230
|
+
* [#99](https://github.com/intridea/hashie/issues/99): Hash#deep_merge raises errors when it encounters integers - [@defsprite](https://github.com/defsprite).
|
107
231
|
* [#100](https://github.com/intridea/hashie/pull/100): IndifferentAccess#store will respect indifference - [@jrochkind](https://github.com/jrochkind).
|
108
232
|
* [#103](https://github.com/intridea/hashie/pull/103): Fixed support for Hashie::Dash properties that end in bang - [@thedavemarshall](https://github.com/thedavemarshall).
|
109
|
-
* [
|
233
|
+
* [#107](https://github.com/intridea/hashie/pull/107): Fixed excessive value conversions, poor performance of deep merge in Hashie::Mash - [@davemitchell](https://github.com/dblock), [@dblock](https://github.com/dblock).
|
110
234
|
* [#110](https://github.com/intridea/hashie/pull/110): Correctly use Hash#default from Mash#method_missing - [@ryansouza](https://github.com/ryansouza).
|
111
|
-
* [#120](https://github.com/intridea/hashie/pull/120): Pass options to recursive to_hash calls - [@pwillett](https://github.com/pwillett).
|
112
|
-
* [#113](https://github.com/intridea/hashie/issues/113): Fixed Hash#merge with Hashie::Dash - [@spencer1248](https://github.com/spencer1248).
|
113
|
-
* [#99](https://github.com/intridea/hashie/issues/99): Hash#deep_merge raises errors when it encounters integers - [@defsprite](https://github.com/defsprite).
|
114
|
-
* [#133](https://github.com/intridea/hashie/pull/133): Fixed Hash##to_hash with symbolize_keys - [@mhuggins](https://github.com/mhuggins).
|
115
|
-
* [#130](https://github.com/intridea/hashie/pull/130): IndifferentAccess now works without MergeInitializer - [@npj](https://github.com/npj).
|
116
235
|
* [#111](https://github.com/intridea/hashie/issues/111): Trash#translations correctly maps original to translated names - [@artm](https://github.com/artm).
|
236
|
+
* [#113](https://github.com/intridea/hashie/issues/113): Fixed Hash#merge with Hashie::Dash - [@spencer1248](https://github.com/spencer1248).
|
237
|
+
* [#120](https://github.com/intridea/hashie/pull/120): Pass options to recursive to_hash calls - [@pwillett](https://github.com/pwillett).
|
117
238
|
* [#129](https://github.com/intridea/hashie/pull/129): Added Trash#permitted_input_keys and inverse_translations - [@artm](https://github.com/artm).
|
239
|
+
* [#130](https://github.com/intridea/hashie/pull/130): IndifferentAccess now works without MergeInitializer - [@npj](https://github.com/npj).
|
240
|
+
* [#133](https://github.com/intridea/hashie/pull/133): Fixed Hash##to_hash with symbolize_keys - [@mhuggins](https://github.com/mhuggins).
|
241
|
+
|
242
|
+
### Miscellaneous
|
243
|
+
|
244
|
+
* Ruby style now enforced with Rubocop - [@dblock](https://github.com/dblock).
|
245
|
+
|
246
|
+
## [2.0.5] - 2013-05-10
|
118
247
|
|
119
|
-
|
248
|
+
[2.0.5]: https://github.com/intridea/hashie/compare/v2.0.4...v2.0.5
|
249
|
+
|
250
|
+
### Fixed
|
120
251
|
|
121
252
|
* [#96](https://github.com/intridea/hashie/pull/96): Make coercion work better with non-symbol keys in Hashie::Mash - [@wapcaplet](https://github.com/wapcaplet).
|
122
253
|
|
123
|
-
## 2.0.4
|
254
|
+
## [2.0.4] - 2013-04-24
|
255
|
+
|
256
|
+
[2.0.4]: https://github.com/intridea/hashie/compare/v2.0.3...v2.0.4
|
257
|
+
|
258
|
+
### Fixed
|
259
|
+
|
260
|
+
* [#94](https://github.com/intridea/hashie/pull/94): Make #fetch method consistent with normal Hash - [@markiz](https://github.com/markiz).
|
261
|
+
|
262
|
+
### Miscellaneous
|
124
263
|
|
125
|
-
* [#04](https://github.com/intridea/hashie/pull/94): Make #fetch method consistent with normal Hash - [@markiz](https://github.com/markiz).
|
126
264
|
* [#90](https://github.com/intridea/hashie/pull/90): Various doc tweaks - [@craiglittle](https://github.com/craiglittle).
|
127
265
|
|
128
|
-
## 2.0.3
|
266
|
+
## [2.0.3] - 2013-03-18
|
267
|
+
|
268
|
+
[2.0.3]: https://github.com/intridea/hashie/compare/v2.0.2...v2.0.3
|
269
|
+
|
270
|
+
### Fixed
|
129
271
|
|
130
|
-
* [#88](https://github.com/intridea/hashie/pull/88): Hashie::Mash.new(abc: true).respond_to?(:abc?) works - [@7even](https://github.com/7even).
|
131
272
|
* [#68](https://github.com/intridea/hashie/pull/68): Fix #replace - [@jimeh](https://github.com/jimeh).
|
273
|
+
* [#88](https://github.com/intridea/hashie/pull/88): Hashie::Mash.new(abc: true).respond_to?(:abc?) works - [@7even](https://github.com/7even).
|
274
|
+
|
275
|
+
## [2.0.2] - 2013-02-26
|
132
276
|
|
133
|
-
|
277
|
+
[2.0.2]: https://github.com/intridea/hashie/compare/v2.0.1...v2.0.2
|
278
|
+
|
279
|
+
### Fixed
|
134
280
|
|
135
281
|
* [#85](https://github.com/intridea/hashie/pull/85): adding symbolize_keys back to to_hash - [@cromulus](https://github.com/cromulus).
|
136
282
|
|
137
|
-
## 2.0.1
|
283
|
+
## [2.0.1] - 2013-02-26
|
284
|
+
|
285
|
+
[2.0.1]: https://github.com/intridea/hashie/compare/v2.0.0...v2.0.1
|
286
|
+
|
287
|
+
### Removed
|
138
288
|
|
139
289
|
* [#81](https://github.com/intridea/hashie/pull/81): remove Mash#object_id override - [@matschaffer](https://github.com/matschaffer).
|
290
|
+
|
291
|
+
### Miscellaneous
|
292
|
+
|
140
293
|
* Gem cleanup: removed VERSION, Gemfile.lock [@jch](https://github.com/jch), [@mbleigh](https://github.com/mbleigh).
|
141
294
|
|
142
|
-
## 2.0.0
|
295
|
+
## [2.0.0] - 2013-02-16
|
296
|
+
|
297
|
+
[2.0.0]: https://github.com/intridea/hashie/compare/v1.2.0...v2.0.0
|
298
|
+
|
299
|
+
### Added
|
300
|
+
|
301
|
+
* [#41](https://github.com/intridea/hashie/pull/41): DeepMerge extension - [@nashby](https://github.com/nashby).
|
302
|
+
* [#78](https://github.com/intridea/hashie/pull/78): Merge and update accepts a block - [@jch](https://github.com/jch).
|
303
|
+
|
304
|
+
### Changed
|
143
305
|
|
144
|
-
* [#72](https://github.com/intridea/hashie/pull/72): Updated gemspec with license info - [@jordimassaguerpla](https://github.com/jordimassaguerpla).
|
145
|
-
* [#27](https://github.com/intridea/hashie/pull/27): Initialized with merge coerces values - [@mattfawcett](https://github.com/mattfawcett).
|
146
306
|
* [#28](https://github.com/intridea/hashie/pull/28): Hashie::Extensions::Coercion coerce_keys takes arguments - [@mattfawcett](https://github.com/mattfawcett).
|
307
|
+
* [#77](https://github.com/intridea/hashie/pull/77): Remove id, type, and object_id as special allowable keys [@jch](https://github.com/jch).
|
308
|
+
|
309
|
+
### Fixed
|
310
|
+
|
311
|
+
* [#27](https://github.com/intridea/hashie/pull/27): Initialized with merge coerces values - [@mattfawcett](https://github.com/mattfawcett).
|
147
312
|
* [#39](https://github.com/intridea/hashie/pull/39): Trash removes translated values on initialization - [@sleverbor](https://github.com/sleverbor).
|
148
|
-
* [#66](https://github.com/intridea/hashie/pull/66): Mash#fetch works with symbol or string keys - [@arthwood](https://github.com/arthwood).
|
149
313
|
* [#49](https://github.com/intridea/hashie/pull/49): Hashie::Hash inherits from ::Hash to avoid ambiguity - [@meh](https://github.com/meh), [@orend](https://github.com/orend).
|
150
314
|
* [#62](https://github.com/intridea/hashie/pull/62): update respond_to? method signature to match ruby core definition - [@dlupu](https://github.com/dlupu).
|
151
|
-
* [#41](https://github.com/intridea/hashie/pull/41): DeepMerge extension - [@nashby](https://github.com/nashby).
|
152
315
|
* [#63](https://github.com/intridea/hashie/pull/63): Dash defaults are dup'ed before assigned - [@ohrite](https://github.com/ohrite).
|
153
|
-
* [#
|
154
|
-
|
316
|
+
* [#66](https://github.com/intridea/hashie/pull/66): Mash#fetch works with symbol or string keys - [@arthwood](https://github.com/arthwood).
|
317
|
+
|
318
|
+
### Miscellaneous
|
319
|
+
|
320
|
+
* [#72](https://github.com/intridea/hashie/pull/72): Updated gemspec with license info - [@jordimassaguerpla](https://github.com/jordimassaguerpla).
|
data/CONTRIBUTING.md
CHANGED
@@ -52,7 +52,17 @@ Document any external behavior in the [README](README.md).
|
|
52
52
|
|
53
53
|
#### Update Changelog
|
54
54
|
|
55
|
-
Add a line to [CHANGELOG](CHANGELOG.md) under *
|
55
|
+
Add a line to [CHANGELOG](CHANGELOG.md) under *Unreleased*. Make it look like every other line, including your name and link to your Github account.
|
56
|
+
|
57
|
+
There are several categorizations of changes that you can choose from. Add your line to the appropriate section, following these conventions:
|
58
|
+
|
59
|
+
* **Added** - When you add a new behavior to any class or module (or add a new extension) that does not break backwards compatibility, you should mark it as "added". This is generally a fully new behavior that does not touch any pre-existing public API. Changes here require a MINOR version bump, following the Semantic Versioning specification.
|
60
|
+
* **Changed** - You should mark any change to the behavior of a public API on any class or module as "changed". Changes here require a MAJOR version bump, following the Semantic Versioning specification.
|
61
|
+
* **Deprecated** - Any time you deprecate part of the public API on any class or module you should mark the change as "deprecated". Deprecated behavior will be removed in the next MAJOR version bump, but should be left in until then. Changes here require a MINOR version bump, following the Semantic Versioning specification.
|
62
|
+
* **Removed** - You should mark any behavior that you removed from a public API on any class or module as "removed". Changes here require a MAJOR version bump, following the Semantic Versioning specification.
|
63
|
+
* **Fixed** - Any time you fix a bug you should mark as "fixed". Changes here require a PATCH version bump.
|
64
|
+
* **Security** - You should mark any security issue that you fix as "security". Changes here require a PATCH version bump.
|
65
|
+
* **Miscellaneous** - Mark any other changes you make (i.e. documentation updates, test harness changes, etc.) as "miscellaneous". Changes here require a PATCH version bump.
|
56
66
|
|
57
67
|
#### Commit Changes
|
58
68
|
|
data/README.md
CHANGED
@@ -18,13 +18,13 @@ Hashie is available as a RubyGem:
|
|
18
18
|
$ gem install hashie
|
19
19
|
```
|
20
20
|
|
21
|
-
##
|
21
|
+
## Upgrading
|
22
22
|
|
23
|
-
You're reading the documentation for the stable release
|
23
|
+
You're reading the documentation for the stable release of Hashie, 3.4.4. Please read [UPGRADING](UPGRADING.md) when upgrading from a previous version.
|
24
24
|
|
25
25
|
## Hash Extensions
|
26
26
|
|
27
|
-
The library is broken up into a number of atomically
|
27
|
+
The library is broken up into a number of atomically includable Hash extension modules as described below. This provides maximum flexibility for users to mix and match functionality while maintaining feature parity with earlier versions of Hashie.
|
28
28
|
|
29
29
|
Any of the extensions listed below can be mixed into a class by `include`-ing `Hashie::Extensions::ExtensionName`.
|
30
30
|
|
@@ -135,11 +135,11 @@ class Tweet < Hash
|
|
135
135
|
coerce_key :retweeted, ->(v) do
|
136
136
|
case v
|
137
137
|
when String
|
138
|
-
|
138
|
+
!!(v =~ /\A(true|t|yes|y|1)\z/i)
|
139
139
|
when Numeric
|
140
|
-
|
140
|
+
!v.to_i.zero?
|
141
141
|
else
|
142
|
-
|
142
|
+
v == true
|
143
143
|
end
|
144
144
|
end
|
145
145
|
end
|
@@ -237,9 +237,30 @@ overriding.__zip #=> [[['zip', 'a-dee-doo-dah']]]
|
|
237
237
|
|
238
238
|
### IndifferentAccess
|
239
239
|
|
240
|
-
This extension can be mixed in to
|
240
|
+
This extension can be mixed in to your Hash subclass to allow you to use Strings or Symbols interchangeably as keys; similar to the `params` hash in Rails.
|
241
241
|
|
242
|
-
|
242
|
+
In addition, IndifferentAccess will also inject itself into sub-hashes so they behave the same.
|
243
|
+
|
244
|
+
Example:
|
245
|
+
|
246
|
+
```ruby
|
247
|
+
class MyHash < Hash
|
248
|
+
include Hashie::Extensions::MergeInitializer
|
249
|
+
include Hashie::Extensions::IndifferentAccess
|
250
|
+
end
|
251
|
+
|
252
|
+
myhash = MyHash.new(:cat => 'meow', 'dog' => 'woof')
|
253
|
+
myhash['cat'] # => "meow"
|
254
|
+
myhash[:cat] # => "meow"
|
255
|
+
myhash[:dog] # => "woof"
|
256
|
+
myhash['dog'] # => "woof"
|
257
|
+
|
258
|
+
# Auto-Injecting into sub-hashes.
|
259
|
+
myhash['fishes'] = {}
|
260
|
+
myhash['fishes'].class # => Hash
|
261
|
+
myhash['fishes'][:food] = 'flakes'
|
262
|
+
myhash['fishes']['food'] # => "flakes"
|
263
|
+
```
|
243
264
|
|
244
265
|
### IgnoreUndeclared
|
245
266
|
|
data/UPGRADING.md
CHANGED
@@ -1,6 +1,17 @@
|
|
1
1
|
Upgrading Hashie
|
2
2
|
================
|
3
3
|
|
4
|
+
### Upgrading to 3.4.4
|
5
|
+
|
6
|
+
#### Mash subclasses and reverse_merge
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
class MyMash < Hashie::Mash
|
10
|
+
end
|
11
|
+
```
|
12
|
+
|
13
|
+
In versions >= 3.4.4 `MyMash#reverse_merge` returns an instance of `MyMash` but in previous versions it was a `Hashie::Mash` instance.
|
14
|
+
|
4
15
|
### Upgrading to 3.2.2
|
5
16
|
|
6
17
|
#### Testing if key defined
|
data/hashie.gemspec
CHANGED
@@ -12,9 +12,9 @@ Gem::Specification.new do |gem|
|
|
12
12
|
|
13
13
|
gem.require_paths = ['lib']
|
14
14
|
gem.files = %w(.yardopts CHANGELOG.md CONTRIBUTING.md LICENSE README.md UPGRADING.md Rakefile hashie.gemspec)
|
15
|
-
gem.files
|
16
|
-
gem.files
|
17
|
-
gem.test_files
|
15
|
+
gem.files += Dir['lib/**/*.rb']
|
16
|
+
gem.files += Dir['spec/**/*.rb']
|
17
|
+
gem.test_files = Dir['spec/**/*.rb']
|
18
18
|
|
19
19
|
gem.add_development_dependency 'rake'
|
20
20
|
gem.add_development_dependency 'rspec', '~> 3.0'
|
data/lib/hashie/clash.rb
CHANGED
@@ -54,7 +54,7 @@ module Hashie
|
|
54
54
|
case args.length
|
55
55
|
when 1
|
56
56
|
val = args.first
|
57
|
-
val = self[key].merge(val) if self[key].is_a?(::Hash) && val.is_a?(::Hash)
|
57
|
+
val = self.class.new(self[key]).merge(val) if self[key].is_a?(::Hash) && val.is_a?(::Hash)
|
58
58
|
else
|
59
59
|
val = args
|
60
60
|
end
|
@@ -64,22 +64,23 @@ module Hashie
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def method_missing(name, *args) #:nodoc:
|
67
|
-
|
68
|
-
if name.match(/!$/) && args.empty?
|
67
|
+
if args.empty? && name.to_s.end_with?('!')
|
69
68
|
key = name[0...-1].to_sym
|
70
69
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
70
|
+
case self[key]
|
71
|
+
when NilClass
|
72
|
+
self[key] = self.class.new({}, self)
|
73
|
+
when Clash
|
74
|
+
self[key]
|
75
|
+
when Hash
|
76
|
+
self[key] = self.class.new(self[key], self)
|
75
77
|
else
|
76
78
|
fail ChainError, 'Tried to chain into a non-hash key.'
|
77
79
|
end
|
78
|
-
|
79
|
-
self[key]
|
80
80
|
elsif args.any?
|
81
|
-
|
82
|
-
|
81
|
+
merge_store(name, *args)
|
82
|
+
else
|
83
|
+
super
|
83
84
|
end
|
84
85
|
end
|
85
86
|
end
|
@@ -111,7 +111,7 @@ module Hashie
|
|
111
111
|
options = { strict: true }.merge(options)
|
112
112
|
|
113
113
|
if ABSTRACT_CORE_TYPES.key? from
|
114
|
-
ABSTRACT_CORE_TYPES[from].each do |
|
114
|
+
ABSTRACT_CORE_TYPES[from].each do |type|
|
115
115
|
coerce_value type, into, options
|
116
116
|
end
|
117
117
|
end
|
@@ -130,6 +130,7 @@ module Hashie
|
|
130
130
|
def strict_value_coercions
|
131
131
|
@strict_value_coercions ||= {}
|
132
132
|
end
|
133
|
+
|
133
134
|
# Return all value coercions that have the :strict rule as false.
|
134
135
|
def lenient_value_coercions
|
135
136
|
@lenient_value_coercions ||= {}
|
@@ -158,7 +159,8 @@ module Hashie
|
|
158
159
|
type, key_type, value_type = type.class, *type.first
|
159
160
|
build_hash_coercion(type, key_type, value_type)
|
160
161
|
else # Enumerable but not Hash: Array, Set
|
161
|
-
|
162
|
+
value_type = type.first
|
163
|
+
type = type.class
|
162
164
|
build_container_coercion(type, value_type)
|
163
165
|
end
|
164
166
|
elsif CORE_TYPES.key? type
|
@@ -17,12 +17,7 @@ module Hashie
|
|
17
17
|
# Hashie::Extensions::DeepLocate.deep_locate -> (key, value, object) { key == :title }, books
|
18
18
|
# # => [{:title=>"Ruby for beginners", :pages=>120}, ...]
|
19
19
|
def self.deep_locate(comparator, object)
|
20
|
-
|
21
|
-
unless comparator.respond_to?(:call)
|
22
|
-
comparator = lambda do |non_callable_object|
|
23
|
-
->(key, _, _) { key == non_callable_object }
|
24
|
-
end.call(comparator)
|
25
|
-
end
|
20
|
+
comparator = _construct_key_comparator(comparator, object) unless comparator.respond_to?(:call)
|
26
21
|
|
27
22
|
_deep_locate(comparator, object)
|
28
23
|
end
|
@@ -68,17 +63,18 @@ module Hashie
|
|
68
63
|
|
69
64
|
private
|
70
65
|
|
66
|
+
def self._construct_key_comparator(search_key, object)
|
67
|
+
search_key = search_key.to_s if defined?(::ActiveSupport) && object.is_a?(::ActiveSupport::HashWithIndifferentAccess)
|
68
|
+
search_key = search_key.to_s if object.respond_to?(:indifferent_access?) && object.indifferent_access?
|
69
|
+
|
70
|
+
lambda do |non_callable_object|
|
71
|
+
->(key, _, _) { key == non_callable_object }
|
72
|
+
end.call(search_key)
|
73
|
+
end
|
74
|
+
|
71
75
|
def self._deep_locate(comparator, object, result = [])
|
72
76
|
if object.is_a?(::Enumerable)
|
73
|
-
if object.any?
|
74
|
-
if object.is_a?(::Hash)
|
75
|
-
key, value = value
|
76
|
-
else
|
77
|
-
key = nil
|
78
|
-
end
|
79
|
-
|
80
|
-
comparator.call(key, value, object)
|
81
|
-
end
|
77
|
+
if object.any? { |value| _match_comparator?(value, comparator, object) }
|
82
78
|
result.push object
|
83
79
|
else
|
84
80
|
(object.respond_to?(:values) ? object.values : object.entries).each do |value|
|
@@ -89,6 +85,16 @@ module Hashie
|
|
89
85
|
|
90
86
|
result
|
91
87
|
end
|
88
|
+
|
89
|
+
def self._match_comparator?(value, comparator, object)
|
90
|
+
if object.is_a?(::Hash)
|
91
|
+
key, value = value
|
92
|
+
else
|
93
|
+
key = nil
|
94
|
+
end
|
95
|
+
|
96
|
+
comparator.call(key, value, object)
|
97
|
+
end
|
92
98
|
end
|
93
99
|
end
|
94
100
|
end
|
@@ -30,10 +30,13 @@ module Hashie
|
|
30
30
|
# p.email # => NoMethodError
|
31
31
|
module IgnoreUndeclared
|
32
32
|
def initialize_attributes(attributes)
|
33
|
+
return unless attributes
|
34
|
+
klass = self.class
|
35
|
+
translations = klass.respond_to?(:translations) && klass.translations
|
33
36
|
attributes.each_pair do |att, value|
|
34
|
-
next unless
|
37
|
+
next unless klass.property?(att) || (translations && translations.include?(att))
|
35
38
|
self[att] = value
|
36
|
-
end
|
39
|
+
end
|
37
40
|
end
|
38
41
|
|
39
42
|
def property_exists?(property)
|
@@ -107,16 +107,41 @@ module Hashie
|
|
107
107
|
# h.hji? # => NoMethodError
|
108
108
|
module MethodQuery
|
109
109
|
def respond_to?(name, include_private = false)
|
110
|
-
|
111
|
-
|
110
|
+
if query_method?(name) && indifferent_key?(key_from_query_method(name))
|
111
|
+
true
|
112
|
+
else
|
113
|
+
super
|
114
|
+
end
|
112
115
|
end
|
113
116
|
|
114
117
|
def method_missing(name, *args)
|
115
|
-
|
116
|
-
|
118
|
+
return super unless args.empty?
|
119
|
+
|
120
|
+
if query_method?(name)
|
121
|
+
key = key_from_query_method(name)
|
122
|
+
if indifferent_key?(key)
|
123
|
+
!!(self[key] || self[key.to_sym])
|
124
|
+
else
|
125
|
+
super
|
126
|
+
end
|
127
|
+
else
|
128
|
+
super
|
117
129
|
end
|
130
|
+
end
|
118
131
|
|
119
|
-
|
132
|
+
private
|
133
|
+
|
134
|
+
def indifferent_key?(name)
|
135
|
+
name = name.to_s
|
136
|
+
key?(name) || key?(name.to_sym)
|
137
|
+
end
|
138
|
+
|
139
|
+
def key_from_query_method(query_method)
|
140
|
+
query_method.to_s[0..-2]
|
141
|
+
end
|
142
|
+
|
143
|
+
def query_method?(name)
|
144
|
+
name.to_s.end_with?('?')
|
120
145
|
end
|
121
146
|
end
|
122
147
|
|
data/lib/hashie/mash.rb
CHANGED
@@ -247,7 +247,13 @@ module Hashie
|
|
247
247
|
|
248
248
|
# another ActiveSupport method, see issue #270
|
249
249
|
def reverse_merge(other_hash)
|
250
|
-
|
250
|
+
self.class.new(other_hash).merge(self)
|
251
|
+
end
|
252
|
+
|
253
|
+
if RUBY_VERSION >= '2.3.0'
|
254
|
+
def dig(*keys)
|
255
|
+
super(*keys.map { |key| convert_key(key) })
|
256
|
+
end
|
251
257
|
end
|
252
258
|
|
253
259
|
protected
|
data/lib/hashie/version.rb
CHANGED
data/spec/hashie/clash_spec.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Hashie::Clash do
|
4
|
-
subject { Hashie::Clash.new }
|
5
|
-
|
6
4
|
it 'is able to set an attribute via method_missing' do
|
7
5
|
subject.foo('bar')
|
8
6
|
expect(subject[:foo]).to eq 'bar'
|
@@ -45,4 +43,28 @@ describe Hashie::Clash do
|
|
45
43
|
expect(subject[:foo]).to be_nil
|
46
44
|
expect(subject[:hello]).to be_nil
|
47
45
|
end
|
46
|
+
|
47
|
+
it 'merges multiple bang notation calls' do
|
48
|
+
subject.where!.foo(123)
|
49
|
+
subject.where!.bar(321)
|
50
|
+
expect(subject).to eq(where: { foo: 123, bar: 321 })
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'raises an exception when method is missing' do
|
54
|
+
expect { subject.boo }.to raise_error(NoMethodError)
|
55
|
+
end
|
56
|
+
|
57
|
+
describe 'when inherited' do
|
58
|
+
subject { Class.new(described_class).new }
|
59
|
+
|
60
|
+
it 'bang nodes are instances of a subclass' do
|
61
|
+
subject.where!.foo(123)
|
62
|
+
expect(subject[:where]).to be_instance_of(subject.class)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'merged nodes are instances of a subclass' do
|
66
|
+
subject.where(abc: 'def').where(hgi: 123)
|
67
|
+
expect(subject[:where]).to be_instance_of(subject.class)
|
68
|
+
end
|
69
|
+
end
|
48
70
|
end
|
data/spec/hashie/dash_spec.rb
CHANGED
@@ -511,3 +511,26 @@ context 'Dynamic Dash Class' do
|
|
511
511
|
expect(my_property).to eq(my_orig)
|
512
512
|
end
|
513
513
|
end
|
514
|
+
|
515
|
+
context 'with method access' do
|
516
|
+
class DashWithMethodAccess < Hashie::Dash
|
517
|
+
include Hashie::Extensions::IndifferentAccess
|
518
|
+
include Hashie::Extensions::MethodQuery
|
519
|
+
|
520
|
+
property :test
|
521
|
+
end
|
522
|
+
|
523
|
+
subject(:dash) { DashWithMethodAccess.new(test: 'value') }
|
524
|
+
|
525
|
+
describe '#test' do
|
526
|
+
subject { dash.test }
|
527
|
+
|
528
|
+
it { is_expected.to eq('value') }
|
529
|
+
end
|
530
|
+
|
531
|
+
describe '#test?' do
|
532
|
+
subject { dash.test? }
|
533
|
+
|
534
|
+
it { is_expected.to eq true }
|
535
|
+
end
|
536
|
+
end
|
@@ -87,7 +87,7 @@ describe Hashie::Extensions::Coercion do
|
|
87
87
|
]
|
88
88
|
expect(instance[:nested_list]).to be_a Array
|
89
89
|
expect(instance[:nested_list].size).to eq(3)
|
90
|
-
instance[:nested_list].each do |
|
90
|
+
instance[:nested_list].each do |nested|
|
91
91
|
test_nested_object nested
|
92
92
|
end
|
93
93
|
end
|
@@ -100,7 +100,7 @@ describe Hashie::Extensions::Coercion do
|
|
100
100
|
}
|
101
101
|
expect(instance[:nested_hash]).to be_a Hash
|
102
102
|
expect(instance[:nested_hash].size).to eq(3)
|
103
|
-
instance[:nested_hash].each do |
|
103
|
+
instance[:nested_hash].each do |key, nested|
|
104
104
|
expect(key).to be_a(String)
|
105
105
|
test_nested_object nested
|
106
106
|
end
|
@@ -251,9 +251,9 @@ describe Hashie::Extensions::Coercion do
|
|
251
251
|
xyz: 987
|
252
252
|
}
|
253
253
|
expect(instance[:foo]).to eq(
|
254
|
-
|
255
|
-
|
256
|
-
|
254
|
+
'abc' => '123',
|
255
|
+
'xyz' => '987'
|
256
|
+
)
|
257
257
|
end
|
258
258
|
|
259
259
|
it 'can coerce via a proc' do
|
@@ -571,7 +571,7 @@ describe Hashie::Extensions::Coercion do
|
|
571
571
|
float: 2.7,
|
572
572
|
rational: Rational(2, 3),
|
573
573
|
complex: Complex(1)
|
574
|
-
}.each do |
|
574
|
+
}.each do |k, v|
|
575
575
|
instance[k] = v
|
576
576
|
if v.is_a? Integer
|
577
577
|
expect(instance[k]).to be_a(String)
|
@@ -592,7 +592,7 @@ describe Hashie::Extensions::Coercion do
|
|
592
592
|
float: 2.7,
|
593
593
|
rational: Rational(2, 3),
|
594
594
|
complex: Complex(1)
|
595
|
-
}.each do |
|
595
|
+
}.each do |k, v|
|
596
596
|
instance[k] = v
|
597
597
|
expect(instance[k]).to be_a(String)
|
598
598
|
expect(instance[k]).to eq(v.to_s)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
2
3
|
|
3
4
|
describe Hashie::Extensions::DeepFind do
|
4
5
|
subject { Class.new(Hash) { include Hashie::Extensions::DeepFind } }
|
@@ -42,4 +43,71 @@ describe Hashie::Extensions::DeepFind do
|
|
42
43
|
expect(instance.deep_find_all(:wahoo)).to be_nil
|
43
44
|
end
|
44
45
|
end
|
46
|
+
|
47
|
+
context 'on an ActiveSupport::HashWithIndifferentAccess' do
|
48
|
+
subject(:instance) { hash.with_indifferent_access.extend(Hashie::Extensions::DeepFind) }
|
49
|
+
|
50
|
+
describe '#deep_find' do
|
51
|
+
it 'indifferently detects a value from a nested hash' do
|
52
|
+
expect(instance.deep_find(:address)).to eq('123 Library St.')
|
53
|
+
expect(instance.deep_find('address')).to eq('123 Library St.')
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'indifferently detects a value from a nested array' do
|
57
|
+
expect(instance.deep_find(:title)).to eq('Call of the Wild')
|
58
|
+
expect(instance.deep_find('title')).to eq('Call of the Wild')
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'indifferently returns nil if it does not find a match' do
|
62
|
+
expect(instance.deep_find(:wahoo)).to be_nil
|
63
|
+
expect(instance.deep_find('wahoo')).to be_nil
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe '#deep_find_all' do
|
68
|
+
it 'indifferently detects all values from a nested hash' do
|
69
|
+
expect(instance.deep_find_all(:title)).to eq(['Call of the Wild', 'Moby Dick', 'Main Library'])
|
70
|
+
expect(instance.deep_find_all('title')).to eq(['Call of the Wild', 'Moby Dick', 'Main Library'])
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'indifferently returns nil if it does not find any matches' do
|
74
|
+
expect(instance.deep_find_all(:wahoo)).to be_nil
|
75
|
+
expect(instance.deep_find_all('wahoo')).to be_nil
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'on a Hash including Hashie::Extensions::IndifferentAccess' do
|
81
|
+
let(:klass) { Class.new(Hash) { include Hashie::Extensions::IndifferentAccess } }
|
82
|
+
subject(:instance) { klass[hash.dup].extend(Hashie::Extensions::DeepFind) }
|
83
|
+
|
84
|
+
describe '#deep_find' do
|
85
|
+
it 'indifferently detects a value from a nested hash' do
|
86
|
+
expect(instance.deep_find(:address)).to eq('123 Library St.')
|
87
|
+
expect(instance.deep_find('address')).to eq('123 Library St.')
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'indifferently detects a value from a nested array' do
|
91
|
+
expect(instance.deep_find(:title)).to eq('Call of the Wild')
|
92
|
+
expect(instance.deep_find('title')).to eq('Call of the Wild')
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'indifferently returns nil if it does not find a match' do
|
96
|
+
expect(instance.deep_find(:wahoo)).to be_nil
|
97
|
+
expect(instance.deep_find('wahoo')).to be_nil
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe '#deep_find_all' do
|
102
|
+
it 'indifferently detects all values from a nested hash' do
|
103
|
+
expect(instance.deep_find_all(:title)).to eq(['Call of the Wild', 'Moby Dick', 'Main Library'])
|
104
|
+
expect(instance.deep_find_all('title')).to eq(['Call of the Wild', 'Moby Dick', 'Main Library'])
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'indifferently returns nil if it does not find any matches' do
|
108
|
+
expect(instance.deep_find_all(:wahoo)).to be_nil
|
109
|
+
expect(instance.deep_find_all('wahoo')).to be_nil
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
45
113
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
2
3
|
|
3
4
|
describe Hashie::Extensions::DeepLocate do
|
4
5
|
let(:hash) do
|
@@ -121,4 +122,16 @@ describe Hashie::Extensions::DeepLocate do
|
|
121
122
|
expect(instance.deep_locate(:bool)).to eq([hash[:query]])
|
122
123
|
end
|
123
124
|
end
|
125
|
+
|
126
|
+
context 'on an ActiveSupport::HashWithIndifferentAccess' do
|
127
|
+
let(:instance) { hash.dup.with_indifferent_access }
|
128
|
+
|
129
|
+
it 'can locate symbolic keys' do
|
130
|
+
expect(described_class.deep_locate(:lsr10, instance)).to eq ['lsr10' => { 'gte' => 2014 }]
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'can locate string keys' do
|
134
|
+
expect(described_class.deep_locate('lsr10', instance)).to eq ['lsr10' => { 'gte' => 2014 }]
|
135
|
+
end
|
136
|
+
end
|
124
137
|
end
|
@@ -6,6 +6,7 @@ describe Hashie::Extensions::IgnoreUndeclared do
|
|
6
6
|
include Hashie::Extensions::IgnoreUndeclared
|
7
7
|
property :city
|
8
8
|
property :state, from: :provence
|
9
|
+
property :str_state, from: 'str_provence'
|
9
10
|
end
|
10
11
|
|
11
12
|
subject { ForgivingTrash }
|
@@ -19,7 +20,7 @@ describe Hashie::Extensions::IgnoreUndeclared do
|
|
19
20
|
end
|
20
21
|
|
21
22
|
it 'works with translated properties (with string keys)' do
|
22
|
-
expect(subject.new(
|
23
|
+
expect(subject.new('str_provence' => 'Ontario').str_state).to eq('Ontario')
|
23
24
|
end
|
24
25
|
|
25
26
|
it 'requires properties to be declared on assignment' do
|
@@ -31,6 +31,32 @@ describe Hashie::Extensions::IndifferentAccess do
|
|
31
31
|
property :foo
|
32
32
|
end
|
33
33
|
|
34
|
+
describe '#merge' do
|
35
|
+
it 'indifferently merges in a hash' do
|
36
|
+
indifferent_hash = Class.new(::Hash) do
|
37
|
+
include Hashie::Extensions::IndifferentAccess
|
38
|
+
end.new
|
39
|
+
|
40
|
+
merged_hash = indifferent_hash.merge(:cat => 'meow')
|
41
|
+
|
42
|
+
expect(merged_hash[:cat]).to eq('meow')
|
43
|
+
expect(merged_hash['cat']).to eq('meow')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#merge!' do
|
48
|
+
it 'indifferently merges in a hash' do
|
49
|
+
indifferent_hash = Class.new(::Hash) do
|
50
|
+
include Hashie::Extensions::IndifferentAccess
|
51
|
+
end.new
|
52
|
+
|
53
|
+
indifferent_hash.merge!(:cat => 'meow')
|
54
|
+
|
55
|
+
expect(indifferent_hash[:cat]).to eq('meow')
|
56
|
+
expect(indifferent_hash['cat']).to eq('meow')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
34
60
|
describe 'when included in dash' do
|
35
61
|
let(:params) { { foo: 'bar' } }
|
36
62
|
subject { IndifferentHashWithDash.new(params) }
|
@@ -54,13 +80,13 @@ describe Hashie::Extensions::IndifferentAccess do
|
|
54
80
|
end
|
55
81
|
|
56
82
|
it 'returns the same instance of the hash that was set' do
|
57
|
-
hash =
|
83
|
+
hash = {}
|
58
84
|
h = subject.build(foo: hash)
|
59
85
|
expect(h.values_at(:foo)[0]).to be(hash)
|
60
86
|
end
|
61
87
|
|
62
88
|
it 'returns the same instance of the array that was set' do
|
63
|
-
array =
|
89
|
+
array = []
|
64
90
|
h = subject.build(foo: array)
|
65
91
|
expect(h.values_at(:foo)[0]).to be(array)
|
66
92
|
end
|
@@ -86,13 +112,13 @@ describe Hashie::Extensions::IndifferentAccess do
|
|
86
112
|
end
|
87
113
|
|
88
114
|
it 'returns the same instance of the hash that was set' do
|
89
|
-
hash =
|
115
|
+
hash = {}
|
90
116
|
h = subject.build(foo: hash)
|
91
117
|
expect(h.fetch(:foo)).to be(hash)
|
92
118
|
end
|
93
119
|
|
94
120
|
it 'returns the same instance of the array that was set' do
|
95
|
-
array =
|
121
|
+
array = []
|
96
122
|
h = subject.build(foo: array)
|
97
123
|
expect(h.fetch(:foo)).to be(array)
|
98
124
|
end
|
@@ -156,7 +182,7 @@ describe Hashie::Extensions::IndifferentAccess do
|
|
156
182
|
|
157
183
|
it 'does not change the ancestors of the injected object class' do
|
158
184
|
h.update(baz: { qux: 'abc' })
|
159
|
-
expect(
|
185
|
+
expect({}).not_to be_respond_to(:indifferent_access?)
|
160
186
|
end
|
161
187
|
end
|
162
188
|
|
@@ -118,7 +118,7 @@ describe Hashie::Extensions::IndifferentAccess do
|
|
118
118
|
|
119
119
|
it 'does not change the ancestors of the injected object class' do
|
120
120
|
h.update(baz: { qux: 'abc' })
|
121
|
-
expect(
|
121
|
+
expect({}).not_to be_respond_to(:indifferent_access?)
|
122
122
|
end
|
123
123
|
end
|
124
124
|
|
@@ -92,15 +92,19 @@ describe Hashie::Extensions::MethodQuery do
|
|
92
92
|
subject { QueryHash }
|
93
93
|
|
94
94
|
it 'is true for non-nil string key values' do
|
95
|
-
expect(subject.new('abc' => 123)).to
|
95
|
+
expect(subject.new('abc' => 123).abc?).to eq true
|
96
96
|
end
|
97
97
|
|
98
98
|
it 'is true for non-nil symbol key values' do
|
99
|
-
expect(subject.new(abc: 123)).to
|
99
|
+
expect(subject.new(abc: 123).abc?).to eq true
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'is false for false key values' do
|
103
|
+
expect(subject.new(abc: false).abc?).to eq false
|
100
104
|
end
|
101
105
|
|
102
106
|
it 'is false for nil key values' do
|
103
|
-
expect(subject.new(abc:
|
107
|
+
expect(subject.new(abc: nil).abc?).to eq false
|
104
108
|
end
|
105
109
|
|
106
110
|
it 'raises a NoMethodError for non-set keys' do
|
data/spec/hashie/hash_spec.rb
CHANGED
@@ -8,21 +8,21 @@ describe Hash do
|
|
8
8
|
end
|
9
9
|
|
10
10
|
it '#stringify_keys! turns all keys into strings' do
|
11
|
-
hash = Hashie::Hash[:
|
11
|
+
hash = Hashie::Hash[a: 'hey', 123 => 'bob']
|
12
12
|
hash.stringify_keys!
|
13
13
|
expect(hash).to eq Hashie::Hash['a' => 'hey', '123' => 'bob']
|
14
14
|
end
|
15
15
|
|
16
16
|
it '#stringify_keys! turns all keys into strings recursively' do
|
17
|
-
hash = Hashie::Hash[:
|
17
|
+
hash = Hashie::Hash[a: 'hey', 123 => { 345 => 'hey' }]
|
18
18
|
hash.stringify_keys!
|
19
19
|
expect(hash).to eq Hashie::Hash['a' => 'hey', '123' => { '345' => 'hey' }]
|
20
20
|
end
|
21
21
|
|
22
22
|
it '#stringify_keys returns a hash with stringified keys' do
|
23
|
-
hash = Hashie::Hash[:
|
23
|
+
hash = Hashie::Hash[a: 'hey', 123 => 'bob']
|
24
24
|
stringified_hash = hash.stringify_keys
|
25
|
-
expect(hash).to eq Hashie::Hash[:
|
25
|
+
expect(hash).to eq Hashie::Hash[a: 'hey', 123 => 'bob']
|
26
26
|
expect(stringified_hash).to eq Hashie::Hash['a' => 'hey', '123' => 'bob']
|
27
27
|
end
|
28
28
|
|
@@ -41,7 +41,7 @@ describe Hash do
|
|
41
41
|
it '#to_hash with symbolize_keys set to true returns a hash with symbolized keys' do
|
42
42
|
hash = Hashie::Hash['a' => 'hey', 123 => 'bob', 'array' => [1, 2, 3]]
|
43
43
|
symbolized_hash = hash.to_hash(symbolize_keys: true)
|
44
|
-
expect(symbolized_hash).to eq(:
|
44
|
+
expect(symbolized_hash).to eq(a: 'hey', :"123" => 'bob', array: [1, 2, 3])
|
45
45
|
end
|
46
46
|
|
47
47
|
it "#to_hash should not blow up when #to_hash doesn't accept arguments" do
|
@@ -78,7 +78,7 @@ describe Hash do
|
|
78
78
|
it '#to_hash with symbolize_keys set to true returns a hash with symbolized keys' do
|
79
79
|
hash = Hashie::Hash['a' => 'hey', 123 => 'bob', 'array' => [1, 2, 3], subhash: ClassRespondsToHash.new]
|
80
80
|
symbolized_hash = hash.to_hash(symbolize_keys: true)
|
81
|
-
expect(symbolized_hash).to eq(:
|
81
|
+
expect(symbolized_hash).to eq(a: 'hey', :"123" => 'bob', array: [1, 2, 3], subhash: { a: 'hey', b: 'bar', :'123' => 'bob', array: [1, 2, 3] })
|
82
82
|
end
|
83
83
|
end
|
84
84
|
end
|
data/spec/hashie/mash_spec.rb
CHANGED
@@ -676,5 +676,25 @@ describe Hashie::Mash do
|
|
676
676
|
it 'does not overwrite values' do
|
677
677
|
expect(subject.reverse_merge(a: 5).a).to eq subject.a
|
678
678
|
end
|
679
|
+
|
680
|
+
context 'when using with subclass' do
|
681
|
+
let(:subclass) { Class.new(Hashie::Mash) }
|
682
|
+
subject { subclass.new(a: 1) }
|
683
|
+
|
684
|
+
it 'creates an instance of subclass' do
|
685
|
+
expect(subject.reverse_merge(a: 5)).to be_kind_of(subclass)
|
686
|
+
end
|
687
|
+
end
|
688
|
+
end
|
689
|
+
|
690
|
+
if RUBY_VERSION >= '2.3.0'
|
691
|
+
describe '#dig' do
|
692
|
+
subject { described_class.new(a: { b: 1 }) }
|
693
|
+
|
694
|
+
it 'accepts both string and symbol as key' do
|
695
|
+
expect(subject.dig(:a, :b)).to eq(1)
|
696
|
+
expect(subject.dig('a', 'b')).to eq(1)
|
697
|
+
end
|
698
|
+
end
|
679
699
|
end
|
680
700
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hashie
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.4.
|
4
|
+
version: 3.4.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Bleigh
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2016-04-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -144,7 +144,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
144
144
|
version: '0'
|
145
145
|
requirements: []
|
146
146
|
rubyforge_project:
|
147
|
-
rubygems_version: 2.4.
|
147
|
+
rubygems_version: 2.4.6
|
148
148
|
signing_key:
|
149
149
|
specification_version: 4
|
150
150
|
summary: Your friendly neighborhood hash library.
|