hashie 2.0.5 → 2.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/.rubocop.yml +36 -0
- data/.travis.yml +13 -6
- data/CHANGELOG.md +40 -21
- data/CONTRIBUTING.md +110 -19
- data/Gemfile +9 -0
- data/LICENSE +1 -1
- data/README.md +347 -0
- data/Rakefile +4 -2
- data/hashie.gemspec +4 -7
- data/lib/hashie.rb +3 -0
- data/lib/hashie/clash.rb +19 -19
- data/lib/hashie/dash.rb +47 -39
- data/lib/hashie/extensions/coercion.rb +10 -6
- data/lib/hashie/extensions/deep_fetch.rb +29 -0
- data/lib/hashie/extensions/deep_merge.rb +15 -6
- data/lib/hashie/extensions/ignore_undeclared.rb +41 -0
- data/lib/hashie/extensions/indifferent_access.rb +37 -10
- data/lib/hashie/extensions/key_conversion.rb +3 -3
- data/lib/hashie/extensions/method_access.rb +9 -9
- data/lib/hashie/hash.rb +7 -7
- data/lib/hashie/hash_extensions.rb +5 -7
- data/lib/hashie/mash.rb +38 -31
- data/lib/hashie/rash.rb +119 -0
- data/lib/hashie/trash.rb +31 -22
- data/lib/hashie/version.rb +1 -1
- data/spec/hashie/clash_spec.rb +43 -45
- data/spec/hashie/dash_spec.rb +115 -53
- data/spec/hashie/extensions/coercion_spec.rb +42 -37
- data/spec/hashie/extensions/deep_fetch_spec.rb +70 -0
- data/spec/hashie/extensions/deep_merge_spec.rb +11 -9
- data/spec/hashie/extensions/ignore_undeclared_spec.rb +23 -0
- data/spec/hashie/extensions/indifferent_access_spec.rb +117 -64
- data/spec/hashie/extensions/key_conversion_spec.rb +28 -27
- data/spec/hashie/extensions/merge_initializer_spec.rb +13 -10
- data/spec/hashie/extensions/method_access_spec.rb +49 -40
- data/spec/hashie/hash_spec.rb +25 -13
- data/spec/hashie/mash_spec.rb +243 -187
- data/spec/hashie/rash_spec.rb +44 -0
- data/spec/hashie/trash_spec.rb +81 -43
- data/spec/hashie/version_spec.rb +7 -0
- data/spec/spec_helper.rb +0 -4
- metadata +27 -78
- data/.document +0 -5
- data/README.markdown +0 -236
- data/lib/hashie/extensions/structure.rb +0 -47
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1fd1f73bdb3a592938fb9e274e7306c16c2410b8
|
4
|
+
data.tar.gz: 545f19b3a9989433f31c047af0fdf477789f8d10
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4a96ffb374b4560d0276412d43ceaa5717aa963e5c8e596343c6cf484081cc2f1b49b7725b97eb9c64baf33631e96f8ccecc1ee95dc470c2fe677334f3c38a45
|
7
|
+
data.tar.gz: e67465dc21d6a9eef56e3eb7b603d41471a926c42e2a4f687d4e2c4ead92522e04dc03408b6854f7d594b7a9510d517d432208e94287a1f77c13008d4a5a40f8
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
AllCops:
|
2
|
+
Exclude:
|
3
|
+
- vendor/**
|
4
|
+
- bin/**
|
5
|
+
- .bundle/**
|
6
|
+
|
7
|
+
LineLength:
|
8
|
+
Enabled: false
|
9
|
+
|
10
|
+
MethodLength:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
ClassLength:
|
14
|
+
Enabled: false
|
15
|
+
|
16
|
+
Documentation:
|
17
|
+
# don't require classes to be documented
|
18
|
+
Enabled: false
|
19
|
+
|
20
|
+
Encoding:
|
21
|
+
# no need to always specify encoding
|
22
|
+
Enabled: false
|
23
|
+
|
24
|
+
Lambda:
|
25
|
+
# TODO: replace all lambda with -> or Proc
|
26
|
+
Enabled: false
|
27
|
+
|
28
|
+
CyclomaticComplexity:
|
29
|
+
Enabled: false
|
30
|
+
|
31
|
+
DoubleNegation:
|
32
|
+
Enabled: false
|
33
|
+
|
34
|
+
CaseEquality:
|
35
|
+
Enabled: false
|
36
|
+
|
data/.travis.yml
CHANGED
@@ -1,8 +1,15 @@
|
|
1
|
+
language: ruby
|
1
2
|
rvm:
|
2
|
-
- 2.0.0
|
3
|
-
- 1.8.7
|
4
|
-
- 1.9.2
|
5
|
-
- rbx
|
6
|
-
- ree
|
7
3
|
- ruby-head
|
8
|
-
-
|
4
|
+
- 2.1.1
|
5
|
+
- 2.1.0
|
6
|
+
- 2.0.0
|
7
|
+
- 1.9.3
|
8
|
+
- jruby-19mode
|
9
|
+
- jruby-head
|
10
|
+
- rbx-2.1
|
11
|
+
- rbx-2.2
|
12
|
+
matrix:
|
13
|
+
allow_failures:
|
14
|
+
- rvm: ruby-head
|
15
|
+
- rvm: jruby-head
|
data/CHANGELOG.md
CHANGED
@@ -1,39 +1,58 @@
|
|
1
|
-
|
1
|
+
## Next Release
|
2
|
+
|
3
|
+
* [#134](https://github.com/intridea/hashie/pull/134): Add deep_fetch extension for nested access - [@tylerdooling](https://github.com/tylerdooling).
|
4
|
+
* Removed support for Ruby 1.8.7 - [@dblock](https://github.com/dblock).
|
5
|
+
* Ruby style now enforced with Rubocop - [@dblock](https://github.com/dblock).
|
6
|
+
* [#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).
|
7
|
+
* [#131](https://github.com/intridea/hashie/pull/131): Added IgnoreUndeclared, an extension to silently ignore undeclared properties at intialization - [@righi](https://github.com/righi).
|
8
|
+
* [#136](https://github.com/intridea/hashie/issues/136): Removed Hashie::Extensions::Structure - [@markiz](https://github.com/markiz).
|
9
|
+
* [#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).
|
10
|
+
* [#69](https://github.com/intridea/hashie/issues/69): Fixed assigning multiple properties in Hashie::Trash - [@einzige](https://github.com/einzige).
|
11
|
+
* [#100](https://github.com/intridea/hashie/pull/100): IndifferentAccess#store will respect indifference - [@jrochkind](https://github.com/jrochkind).
|
12
|
+
* [#103](https://github.com/intridea/hashie/pull/103): Fixed support for Hashie::Dash properties that end in bang - [@thedavemarshall](https://github.com/thedavemarshall).
|
13
|
+
* [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).
|
14
|
+
* [#110](https://github.com/intridea/hashie/pull/110): Correctly use Hash#default from Mash#method_missing - [@ryansouza](https://github.com/ryansouza).
|
15
|
+
* [#120](https://github.com/intridea/hashie/pull/120): Pass options to recursive to_hash calls - [@pwillett](https://github.com/pwillett).
|
16
|
+
* [#113](https://github.com/intridea/hashie/issues/113): Fixed Hash#merge with Hashie::Dash - [@spencer1248](https://github.com/spencer1248).
|
17
|
+
* [#99](https://github.com/intridea/hashie/issues/99): Hash#deep_merge raises errors when it encounters integers - [@defsprite](https://github.com/defsprite).
|
18
|
+
* [#133](https://github.com/intridea/hashie/pull/133): Fixed Hash##to_hash with symbolize_keys - [@mhuggins](https://github.com/mhuggins).
|
19
|
+
* [#130](https://github.com/intridea/hashie/pull/130): IndifferentAccess now works without MergeInitializer - [@npj](https://github.com/npj).
|
20
|
+
* [#111](https://github.com/intridea/hashie/issues/111): Trash#translations correctly maps original to translated names - [@artm](https://github.com/artm).
|
21
|
+
* [#129](https://github.com/intridea/hashie/pull/129): Added Trash#permitted_input_keys and inverse_translations - [@artm](https://github.com/artm).
|
2
22
|
|
3
23
|
## 2.0.5
|
4
24
|
|
5
|
-
*
|
25
|
+
* [#96](https://github.com/intridea/hashie/pull/96): Make coercion work better with non-symbol keys in Hashie::Mash - [@wapcaplet](https://github.com/wapcaplet).
|
6
26
|
|
7
27
|
## 2.0.4
|
8
28
|
|
9
|
-
*
|
10
|
-
*
|
29
|
+
* [#04](https://github.com/intridea/hashie/pull/94): Make #fetch method consistent with normal Hash - [@markiz](https://github.com/markiz).
|
30
|
+
* [#90](https://github.com/intridea/hashie/pull/90): Various doc tweaks - [@craiglittle](https://github.com/craiglittle).
|
11
31
|
|
12
32
|
## 2.0.3
|
13
33
|
|
14
|
-
* Hashie::Mash.new(abc: true).respond_to?(:abc?) works 7even
|
15
|
-
* Fix #replace jimeh
|
34
|
+
* [#88](https://github.com/intridea/hashie/pull/88): Hashie::Mash.new(abc: true).respond_to?(:abc?) works - [@7even](https://github.com/7even).
|
35
|
+
* [#68](https://github.com/intridea/hashie/pull/68): Fix #replace - [@jimeh](https://github.com/jimeh).
|
16
36
|
|
17
37
|
## 2.0.2
|
18
38
|
|
19
|
-
* adding symbolize_keys back to to_hash cromulus
|
39
|
+
* [#85](https://github.com/intridea/hashie/pull/85): adding symbolize_keys back to to_hash - [@cromulus](https://github.com/cromulus).
|
20
40
|
|
21
41
|
## 2.0.1
|
22
42
|
|
23
|
-
* remove Mash#object_id override matschaffer
|
24
|
-
*
|
43
|
+
* [#81](https://github.com/intridea/hashie/pull/81): remove Mash#object_id override - [@matschaffer](https://github.com/matschaffer).
|
44
|
+
* Gem cleanup: removed VERSION, Gemfile.lock [@jch](https://github.com/jch), [@mbleigh](https://github.com/mbleigh).
|
25
45
|
|
26
46
|
## 2.0.0
|
27
47
|
|
28
|
-
*
|
29
|
-
*
|
30
|
-
*
|
31
|
-
*
|
32
|
-
*
|
33
|
-
*
|
34
|
-
*
|
35
|
-
*
|
36
|
-
*
|
37
|
-
*
|
38
|
-
*
|
39
|
-
* merge and update accepts a block jch #78
|
48
|
+
* [#72](https://github.com/intridea/hashie/pull/72): Updated gemspec with license info - [@jordimassaguerpla](https://github.com/jordimassaguerpla).
|
49
|
+
* [#27](https://github.com/intridea/hashie/pull/27): Initialized with merge coerces values - [@mattfawcett](https://github.com/mattfawcett).
|
50
|
+
* [#28](https://github.com/intridea/hashie/pull/28): Hashie::Extensions::Coercion coerce_keys takes arguments - [@mattfawcett](https://github.com/mattfawcett).
|
51
|
+
* [#39](https://github.com/intridea/hashie/pull/39): Trash removes translated values on initialization - [@sleverbor](https://github.com/sleverbor).
|
52
|
+
* [#66](https://github.com/intridea/hashie/pull/66): Mash#fetch works with symbol or string keys - [@arthwood](https://github.com/arthwood).
|
53
|
+
* [#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).
|
54
|
+
* [#62](https://github.com/intridea/hashie/pull/62): update respond_to? method signature to match ruby core definition - [@dlupu](https://github.com/dlupu).
|
55
|
+
* [#41](https://github.com/intridea/hashie/pull/41): DeepMerge extension - [@nashby](https://github.com/nashby).
|
56
|
+
* [#63](https://github.com/intridea/hashie/pull/63): Dash defaults are dup'ed before assigned - [@ohrite](https://github.com/ohrite).
|
57
|
+
* [#77](https://github.com/intridea/hashie/pull/77): Remove id, type, and object_id as special allowable keys [@jch](https://github.com/jch).
|
58
|
+
* [#78](https://github.com/intridea/hashie/pull/78): Merge and update accepts a block - [@jch](https://github.com/jch).
|
data/CONTRIBUTING.md
CHANGED
@@ -1,27 +1,118 @@
|
|
1
|
-
|
1
|
+
Contributing to Hashie
|
2
|
+
======================
|
2
3
|
|
3
|
-
|
4
|
-
review your changes, try to follow these guidelines:
|
4
|
+
Hashie is work of [many contributors](https://github.com/intridea/hashie/graphs/contributors). You're encouraged to submit [pull requests](https://github.com/intridea/hashie/pulls), [propose features and discuss issues](https://github.com/intridea/hashie/issues).
|
5
5
|
|
6
|
-
|
7
|
-
up? Do it in a separate branch.
|
8
|
-
* Stay consistent with existing code conventions.
|
9
|
-
* Break changes into smaller logical commits.
|
6
|
+
#### Fork the Project
|
10
7
|
|
11
|
-
|
8
|
+
Fork the [project on Github](https://github.com/intridea/hashie) and check out your copy.
|
12
9
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
* [Check that your pull request passes the build](https://travis-ci.org/intridea/hashie/pull_requests).
|
10
|
+
```
|
11
|
+
git clone https://github.com/contributor/hashie.git
|
12
|
+
cd hashie
|
13
|
+
git remote add upstream https://github.com/intridea/hashie.git
|
14
|
+
```
|
19
15
|
|
20
|
-
|
16
|
+
#### Create a Topic Branch
|
21
17
|
|
22
|
-
|
18
|
+
Make sure your fork is up-to-date and create a topic branch for your feature or bug fix.
|
23
19
|
|
24
|
-
|
20
|
+
```
|
21
|
+
git checkout master
|
22
|
+
git pull upstream master
|
23
|
+
git checkout -b my-feature-branch
|
24
|
+
```
|
25
25
|
|
26
|
-
|
27
|
-
|
26
|
+
#### Bundle Install and Test
|
27
|
+
|
28
|
+
Ensure that you can build the project and run tests.
|
29
|
+
|
30
|
+
```
|
31
|
+
bundle install
|
32
|
+
bundle exec rake
|
33
|
+
```
|
34
|
+
|
35
|
+
#### Write Tests
|
36
|
+
|
37
|
+
Try to write a test that reproduces the problem you're trying to fix or describes a feature that you want to build. Add to [spec/hashie](spec/hashie).
|
38
|
+
|
39
|
+
We definitely appreciate pull requests that highlight or reproduce a problem, even without a fix.
|
40
|
+
|
41
|
+
#### Write Code
|
42
|
+
|
43
|
+
Implement your feature or bug fix.
|
44
|
+
|
45
|
+
Ruby style is enforced with [Rubocop](https://github.com/bbatsov/rubocop), run `bundle exec rubocop` and fix any style issues highlighted.
|
46
|
+
|
47
|
+
Make sure that `bundle exec rake` completes without errors.
|
48
|
+
|
49
|
+
#### Write Documentation
|
50
|
+
|
51
|
+
Document any external behavior in the [README](README.md).
|
52
|
+
|
53
|
+
#### Update Changelog
|
54
|
+
|
55
|
+
Add a line to [CHANGELOG](CHANGELOG.md) under *Next Release*. Make it look like every other line, including your name and link to your Github account.
|
56
|
+
|
57
|
+
#### Commit Changes
|
58
|
+
|
59
|
+
Make sure git knows your name and email address:
|
60
|
+
|
61
|
+
```
|
62
|
+
git config --global user.name "Your Name"
|
63
|
+
git config --global user.email "contributor@example.com"
|
64
|
+
```
|
65
|
+
|
66
|
+
Writing good commit logs is important. A commit log should describe what changed and why.
|
67
|
+
|
68
|
+
```
|
69
|
+
git add ...
|
70
|
+
git commit
|
71
|
+
```
|
72
|
+
|
73
|
+
#### Push
|
74
|
+
|
75
|
+
```
|
76
|
+
git push origin my-feature-branch
|
77
|
+
```
|
78
|
+
|
79
|
+
#### Make a Pull Request
|
80
|
+
|
81
|
+
Go to https://github.com/contributor/hashie and select your feature branch. Click the 'Pull Request' button and fill out the form. Pull requests are usually reviewed within a few days.
|
82
|
+
|
83
|
+
#### Rebase
|
84
|
+
|
85
|
+
If you've been working on a change for a while, rebase with upstream/master.
|
86
|
+
|
87
|
+
```
|
88
|
+
git fetch upstream
|
89
|
+
git rebase upstream/master
|
90
|
+
git push origin my-feature-branch -f
|
91
|
+
```
|
92
|
+
|
93
|
+
#### Update CHANGELOG Again
|
94
|
+
|
95
|
+
Update the [CHANGELOG](CHANGELOG.md) with the pull request number. A typical entry looks as follows.
|
96
|
+
|
97
|
+
```
|
98
|
+
* [#123](https://github.com/intridea/hashie/pull/123): Reticulated splines - [@contributor](https://github.com/contributor).
|
99
|
+
```
|
100
|
+
|
101
|
+
Amend your previous commit and force push the changes.
|
102
|
+
|
103
|
+
```
|
104
|
+
git commit --amend
|
105
|
+
git push origin my-feature-branch -f
|
106
|
+
```
|
107
|
+
|
108
|
+
#### Check on Your Pull Request
|
109
|
+
|
110
|
+
Go back to your pull request after a few minutes and see whether it passed muster with Travis-CI. Everything should look green, otherwise fix issues and amend your commit as described above.
|
111
|
+
|
112
|
+
#### Be Patient
|
113
|
+
|
114
|
+
It's likely that your change will not be merged and that the nitpicky maintainers will ask you to do more, or fix seemingly benign problems. Hang on there!
|
115
|
+
|
116
|
+
#### Thank You
|
117
|
+
|
118
|
+
Please do know that we really appreciate and value your time and work. We love you, really.
|
data/Gemfile
CHANGED
data/LICENSE
CHANGED
data/README.md
ADDED
@@ -0,0 +1,347 @@
|
|
1
|
+
# Hashie [](http://travis-ci.org/intridea/hashie) [](https://gemnasium.com/intridea/hashie)
|
2
|
+
|
3
|
+
Hashie is a growing collection of tools that extend Hashes and make
|
4
|
+
them more useful.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Hashie is available as a RubyGem:
|
9
|
+
|
10
|
+
```bash
|
11
|
+
$ gem install hashie
|
12
|
+
```
|
13
|
+
|
14
|
+
## Hash Extensions
|
15
|
+
|
16
|
+
The library is broken up into a number of atomically includeable Hash
|
17
|
+
extension modules as described below. This provides maximum flexibility
|
18
|
+
for users to mix and match functionality while maintaining feature parity
|
19
|
+
with earlier versions of Hashie.
|
20
|
+
|
21
|
+
Any of the extensions listed below can be mixed into a class by
|
22
|
+
`include`-ing `Hashie::Extensions::ExtensionName`.
|
23
|
+
|
24
|
+
### Coercion
|
25
|
+
|
26
|
+
Coercions allow you to set up "coercion rules" based either on the key
|
27
|
+
or the value type to massage data as it's being inserted into the Hash.
|
28
|
+
Key coercions might be used, for example, in lightweight data modeling
|
29
|
+
applications such as an API client:
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
class Tweet < Hash
|
33
|
+
include Hashie::Extensions::Coercion
|
34
|
+
coerce_key :user, User
|
35
|
+
end
|
36
|
+
|
37
|
+
user_hash = { name: "Bob" }
|
38
|
+
Tweet.new(user: user_hash)
|
39
|
+
# => automatically calls User.coerce(user_hash) or
|
40
|
+
# User.new(user_hash) if that isn't present.
|
41
|
+
```
|
42
|
+
|
43
|
+
Value coercions, on the other hand, will coerce values based on the type
|
44
|
+
of the value being inserted. This is useful if you are trying to build a
|
45
|
+
Hash-like class that is self-propagating.
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
class SpecialHash < Hash
|
49
|
+
include Hashie::Extensions::Coercion
|
50
|
+
coerce_value Hash, SpecialHash
|
51
|
+
|
52
|
+
def initialize(hash = {})
|
53
|
+
super
|
54
|
+
hash.each_pair do |k,v|
|
55
|
+
self[k] = v
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
61
|
+
### KeyConversion
|
62
|
+
|
63
|
+
The KeyConversion extension gives you the convenience methods of
|
64
|
+
`symbolize_keys` and `stringify_keys` along with their bang
|
65
|
+
counterparts. You can also include just stringify or just symbolize with
|
66
|
+
`Hashie::Extensions::StringifyKeys` or `Hashie::Extensions::SymbolizeKeys`.
|
67
|
+
|
68
|
+
### MergeInitializer
|
69
|
+
|
70
|
+
The MergeInitializer extension simply makes it possible to initialize a
|
71
|
+
Hash subclass with another Hash, giving you a quick short-hand.
|
72
|
+
|
73
|
+
### MethodAccess
|
74
|
+
|
75
|
+
The MethodAccess extension allows you to quickly build method-based
|
76
|
+
reading, writing, and querying into your Hash descendant. It can also be
|
77
|
+
included as individual modules, i.e. `Hashie::Extensions::MethodReader`,
|
78
|
+
`Hashie::Extensions::MethodWriter` and `Hashie::Extensions::MethodQuery`
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
class MyHash < Hash
|
82
|
+
include Hashie::Extensions::MethodAccess
|
83
|
+
end
|
84
|
+
|
85
|
+
h = MyHash.new
|
86
|
+
h.abc = 'def'
|
87
|
+
h.abc # => 'def'
|
88
|
+
h.abc? # => true
|
89
|
+
```
|
90
|
+
|
91
|
+
### IndifferentAccess
|
92
|
+
|
93
|
+
This extension can be mixed in to instantly give you indifferent access
|
94
|
+
to your Hash subclass. This works just like the params hash in Rails and
|
95
|
+
other frameworks where whether you provide symbols or strings to access
|
96
|
+
keys, you will get the same results.
|
97
|
+
|
98
|
+
A unique feature of Hashie's IndifferentAccess mixin is that it will
|
99
|
+
inject itself recursively into subhashes *without* reinitializing the
|
100
|
+
hash in question. This means you can safely merge together indifferent
|
101
|
+
and non-indifferent hashes arbitrarily deeply without worrying about
|
102
|
+
whether you'll be able to `hash[:other][:another]` properly.
|
103
|
+
|
104
|
+
### IgnoreUndeclared
|
105
|
+
|
106
|
+
This extension can be mixed in to silently ignore undeclared properties on
|
107
|
+
initialization instead of raising an error. This is useful when using a
|
108
|
+
Trash to capture a subset of a larger hash.
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
class Person < Trash
|
112
|
+
include Hashie::Extensions::IgnoreUndeclared
|
113
|
+
property :first_name
|
114
|
+
property :last_name
|
115
|
+
end
|
116
|
+
|
117
|
+
user_data = {
|
118
|
+
first_name: 'Freddy',
|
119
|
+
last_name: 'Nostrils',
|
120
|
+
email: 'freddy@example.com'
|
121
|
+
}
|
122
|
+
|
123
|
+
p = Person.new(user_data) # 'email' is silently ignored
|
124
|
+
|
125
|
+
p.first_name # => 'Freddy'
|
126
|
+
p.last_name # => 'Nostrils'
|
127
|
+
p.email # => NoMethodError
|
128
|
+
```
|
129
|
+
|
130
|
+
### DeepMerge
|
131
|
+
|
132
|
+
This extension allow you to easily include a recursive merging
|
133
|
+
system to any Hash descendant:
|
134
|
+
|
135
|
+
```ruby
|
136
|
+
class MyHash < Hash
|
137
|
+
include Hashie::Extensions::DeepMerge
|
138
|
+
end
|
139
|
+
|
140
|
+
h1 = MyHash.new
|
141
|
+
h2 = MyHash.new
|
142
|
+
|
143
|
+
h1 = { x: { y: [4,5,6] }, z: [7,8,9] }
|
144
|
+
h2 = { x: { y: [7,8,9] }, z: "xyz" }
|
145
|
+
|
146
|
+
h1.deep_merge(h2) #=> { x: { y: [7, 8, 9] }, z: "xyz" }
|
147
|
+
h2.deep_merge(h1) #=> { x: { y: [4, 5, 6] }, z: [7, 8, 9] }
|
148
|
+
```
|
149
|
+
|
150
|
+
### DeepFetch
|
151
|
+
|
152
|
+
This extension can be mixed in to provide for safe and concise retrieval of
|
153
|
+
deeply nested hash values. In the event that the requested key does not exist
|
154
|
+
a block can be provided and its value will be returned.
|
155
|
+
|
156
|
+
Though this is a hash extension, it conveniently allows for arrays to be
|
157
|
+
present in the nested structure. This feature makes the extension particularly
|
158
|
+
useful for working with JSON API responses.
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
user = {
|
162
|
+
name: { first: 'Bob', last: 'Boberts' },
|
163
|
+
groups: [
|
164
|
+
{ name: 'Rubyists' },
|
165
|
+
{ name: 'Open source enthusiasts' }
|
166
|
+
]
|
167
|
+
}
|
168
|
+
user.extend Hashie::Extensions::DeepFetch
|
169
|
+
|
170
|
+
user.deep_fetch :name, :first #=> 'Bob'
|
171
|
+
user.deep_fetch :name, :middle #=> 'KeyError: Could not fetch middle'
|
172
|
+
|
173
|
+
# using a default block
|
174
|
+
user.deep_fetch :name, :middle { |key| 'default' } #=> 'default'
|
175
|
+
|
176
|
+
# a nested array
|
177
|
+
user.deep_fetch :groups, 1, :name #=> 'Open source enthusiasts'
|
178
|
+
```
|
179
|
+
|
180
|
+
## Mash
|
181
|
+
|
182
|
+
Mash is an extended Hash that gives simple pseudo-object functionality
|
183
|
+
that can be built from hashes and easily extended. It is designed to
|
184
|
+
be used in RESTful API libraries to provide easy object-like access
|
185
|
+
to JSON and XML parsed hashes.
|
186
|
+
|
187
|
+
### Example:
|
188
|
+
|
189
|
+
```ruby
|
190
|
+
mash = Hashie::Mash.new
|
191
|
+
mash.name? # => false
|
192
|
+
mash.name # => nil
|
193
|
+
mash.name = "My Mash"
|
194
|
+
mash.name # => "My Mash"
|
195
|
+
mash.name? # => true
|
196
|
+
mash.inspect # => <Hashie::Mash name="My Mash">
|
197
|
+
|
198
|
+
mash = Mash.new
|
199
|
+
# use bang methods for multi-level assignment
|
200
|
+
mash.author!.name = "Michael Bleigh"
|
201
|
+
mash.author # => <Hashie::Mash name="Michael Bleigh">
|
202
|
+
|
203
|
+
mash = Mash.new
|
204
|
+
# use under-bang methods for multi-level testing
|
205
|
+
mash.author_.name? # => false
|
206
|
+
mash.inspect # => <Hashie::Mash>
|
207
|
+
```
|
208
|
+
|
209
|
+
**Note:** The `?` method will return false if a key has been set
|
210
|
+
to false or nil. In order to check if a key has been set at all, use the
|
211
|
+
`mash.key?('some_key')` method instead.
|
212
|
+
|
213
|
+
## Dash
|
214
|
+
|
215
|
+
Dash is an extended Hash that has a discrete set of defined properties
|
216
|
+
and only those properties may be set on the hash. Additionally, you
|
217
|
+
can set defaults for each property. You can also flag a property as
|
218
|
+
required. Required properties will raise an exception if unset.
|
219
|
+
|
220
|
+
### Example:
|
221
|
+
|
222
|
+
```ruby
|
223
|
+
class Person < Hashie::Dash
|
224
|
+
property :name, required: true
|
225
|
+
property :email
|
226
|
+
property :occupation, default: 'Rubyist'
|
227
|
+
end
|
228
|
+
|
229
|
+
p = Person.new # => ArgumentError: The property 'name' is required for this Dash.
|
230
|
+
|
231
|
+
p = Person.new(name: "Bob")
|
232
|
+
p.name # => 'Bob'
|
233
|
+
p.name = nil # => ArgumentError: The property 'name' is required for this Dash.
|
234
|
+
p.email = 'abc@def.com'
|
235
|
+
p.occupation # => 'Rubyist'
|
236
|
+
p.email # => 'abc@def.com'
|
237
|
+
p[:awesome] # => NoMethodError
|
238
|
+
p[:occupation] # => 'Rubyist'
|
239
|
+
```
|
240
|
+
|
241
|
+
## Trash
|
242
|
+
|
243
|
+
A Trash is a Dash that allows you to translate keys on initialization.
|
244
|
+
It is used like so:
|
245
|
+
|
246
|
+
```ruby
|
247
|
+
class Person < Hashie::Trash
|
248
|
+
property :first_name, from: :firstName
|
249
|
+
end
|
250
|
+
```
|
251
|
+
|
252
|
+
This will automatically translate the <tt>firstName</tt> key to <tt>first_name</tt>
|
253
|
+
when it is initialized using a hash such as through:
|
254
|
+
|
255
|
+
```ruby
|
256
|
+
Person.new(firstName: 'Bob')
|
257
|
+
```
|
258
|
+
|
259
|
+
Trash also supports translations using lambda, this could be useful when dealing with
|
260
|
+
external API's. You can use it in this way:
|
261
|
+
|
262
|
+
```ruby
|
263
|
+
class Result < Hashie::Trash
|
264
|
+
property :id, transform_with: lambda { |v| v.to_i }
|
265
|
+
property :created_at, from: :creation_date, with: lambda { |v| Time.parse(v) }
|
266
|
+
end
|
267
|
+
```
|
268
|
+
|
269
|
+
this will produce the following
|
270
|
+
|
271
|
+
```ruby
|
272
|
+
result = Result.new(id: '123', creation_date: '2012-03-30 17:23:28')
|
273
|
+
result.id.class # => Fixnum
|
274
|
+
result.created_at.class # => Time
|
275
|
+
```
|
276
|
+
|
277
|
+
## Clash
|
278
|
+
|
279
|
+
Clash is a Chainable Lazy Hash that allows you to easily construct
|
280
|
+
complex hashes using method notation chaining. This will allow you
|
281
|
+
to use a more action-oriented approach to building options hashes.
|
282
|
+
|
283
|
+
Essentially, a Clash is a generalized way to provide much of the same
|
284
|
+
kind of "chainability" that libraries like Arel or Rails 2.x's named_scopes
|
285
|
+
provide.
|
286
|
+
|
287
|
+
### Example:
|
288
|
+
|
289
|
+
```ruby
|
290
|
+
c = Hashie::Clash.new
|
291
|
+
c.where(abc: 'def').order(:created_at)
|
292
|
+
c # => { where: { abc: 'def' }, order: :created_at }
|
293
|
+
|
294
|
+
# You can also use bang notation to chain into sub-hashes,
|
295
|
+
# jumping back up the chain with _end!
|
296
|
+
c = Hashie::Clash.new
|
297
|
+
c.where!.abc('def').ghi(123)._end!.order(:created_at)
|
298
|
+
c # => { where: { abc: 'def', ghi: 123 }, order: :created_at }
|
299
|
+
|
300
|
+
# Multiple hashes are merged automatically
|
301
|
+
c = Hashie::Clash.new
|
302
|
+
c.where(abc: 'def').where(hgi: 123)
|
303
|
+
c # => { where: { abc: 'def', hgi: 123 } }
|
304
|
+
```
|
305
|
+
|
306
|
+
## Rash
|
307
|
+
|
308
|
+
Rash is a Hash whose keys can be Regexps or Ranges, which will map many input keys to a value.
|
309
|
+
|
310
|
+
A good use case for the Rash is an URL router for a web framework, where URLs need to be mapped to actions; the Rash's keys match URL patterns, while the values call the action which handles the URL.
|
311
|
+
|
312
|
+
If the Rash's value is a `proc`, the `proc` will be automatically called with the regexp's MatchData (matched groups) as a block argument.
|
313
|
+
|
314
|
+
### Example:
|
315
|
+
|
316
|
+
```ruby
|
317
|
+
|
318
|
+
# Mapping names to appropriate greetings
|
319
|
+
greeting = Hashie::Rash.new( /^Mr./ => "Hello sir!", /^Mrs./ => "Evening, madame." )
|
320
|
+
greeting["Mr. Steve Austin"] #=> "Hello sir!"
|
321
|
+
greeting["Mrs. Steve Austin"] #=> "Evening, madame."
|
322
|
+
|
323
|
+
# Mapping statements to saucy retorts
|
324
|
+
mapper = Hashie::Rash.new(
|
325
|
+
/I like (.+)/ => proc { |m| "Who DOESN'T like #{m[1]}?!" },
|
326
|
+
/Get off my (.+)!/ => proc { |m| "Forget your #{m[1]}, old man!" }
|
327
|
+
)
|
328
|
+
mapper["I like traffic lights"] #=> "Who DOESN'T like traffic lights?!"
|
329
|
+
mapper["Get off my lawn!"] #=> "Forget your lawn, old man!"
|
330
|
+
```
|
331
|
+
|
332
|
+
### Auto-optimized
|
333
|
+
|
334
|
+
**Note:** The Rash is automatically optimized every 500 accesses
|
335
|
+
(which means that it sorts the list of Regexps, putting the most frequently matched ones at the beginning).
|
336
|
+
|
337
|
+
If this value is too low or too high for your needs, you can tune it by setting: `rash.optimize_every = n`.
|
338
|
+
|
339
|
+
## Contributing
|
340
|
+
|
341
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md)
|
342
|
+
|
343
|
+
## Copyright
|
344
|
+
|
345
|
+
Copyright (c) 2009-2014 Intridea, Inc. (http://intridea.com/) and [contributors](https://github.com/intridea/hashie/graphs/contributors).
|
346
|
+
|
347
|
+
MIT License. See [LICENSE](LICENSE) for details.
|