hashie 2.0.5 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +36 -0
  3. data/.travis.yml +13 -6
  4. data/CHANGELOG.md +40 -21
  5. data/CONTRIBUTING.md +110 -19
  6. data/Gemfile +9 -0
  7. data/LICENSE +1 -1
  8. data/README.md +347 -0
  9. data/Rakefile +4 -2
  10. data/hashie.gemspec +4 -7
  11. data/lib/hashie.rb +3 -0
  12. data/lib/hashie/clash.rb +19 -19
  13. data/lib/hashie/dash.rb +47 -39
  14. data/lib/hashie/extensions/coercion.rb +10 -6
  15. data/lib/hashie/extensions/deep_fetch.rb +29 -0
  16. data/lib/hashie/extensions/deep_merge.rb +15 -6
  17. data/lib/hashie/extensions/ignore_undeclared.rb +41 -0
  18. data/lib/hashie/extensions/indifferent_access.rb +37 -10
  19. data/lib/hashie/extensions/key_conversion.rb +3 -3
  20. data/lib/hashie/extensions/method_access.rb +9 -9
  21. data/lib/hashie/hash.rb +7 -7
  22. data/lib/hashie/hash_extensions.rb +5 -7
  23. data/lib/hashie/mash.rb +38 -31
  24. data/lib/hashie/rash.rb +119 -0
  25. data/lib/hashie/trash.rb +31 -22
  26. data/lib/hashie/version.rb +1 -1
  27. data/spec/hashie/clash_spec.rb +43 -45
  28. data/spec/hashie/dash_spec.rb +115 -53
  29. data/spec/hashie/extensions/coercion_spec.rb +42 -37
  30. data/spec/hashie/extensions/deep_fetch_spec.rb +70 -0
  31. data/spec/hashie/extensions/deep_merge_spec.rb +11 -9
  32. data/spec/hashie/extensions/ignore_undeclared_spec.rb +23 -0
  33. data/spec/hashie/extensions/indifferent_access_spec.rb +117 -64
  34. data/spec/hashie/extensions/key_conversion_spec.rb +28 -27
  35. data/spec/hashie/extensions/merge_initializer_spec.rb +13 -10
  36. data/spec/hashie/extensions/method_access_spec.rb +49 -40
  37. data/spec/hashie/hash_spec.rb +25 -13
  38. data/spec/hashie/mash_spec.rb +243 -187
  39. data/spec/hashie/rash_spec.rb +44 -0
  40. data/spec/hashie/trash_spec.rb +81 -43
  41. data/spec/hashie/version_spec.rb +7 -0
  42. data/spec/spec_helper.rb +0 -4
  43. metadata +27 -78
  44. data/.document +0 -5
  45. data/README.markdown +0 -236
  46. data/lib/hashie/extensions/structure.rb +0 -47
data/.document DELETED
@@ -1,5 +0,0 @@
1
- README.rdoc
2
- lib/**/*.rb
3
- bin/*
4
- features/**/*.feature
5
- LICENSE
@@ -1,236 +0,0 @@
1
- # Hashie [![Build Status](https://secure.travis-ci.org/intridea/hashie.png)](http://travis-ci.org/intridea/hashie) [![Dependency Status](https://gemnasium.com/intridea/hashie.png)](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
- gem install hashie
11
-
12
- ## Hash Extensions
13
-
14
- The library is broken up into a number of atomically includeable Hash
15
- extension modules as described below. This provides maximum flexibility
16
- for users to mix and match functionality while maintaining feature parity
17
- with earlier versions of Hashie.
18
-
19
- Any of the extensions listed below can be mixed into a class by
20
- `include`-ing `Hashie::Extensions::ExtensionName`.
21
-
22
- ### Coercion
23
-
24
- Coercions allow you to set up "coercion rules" based either on the key
25
- or the value type to massage data as it's being inserted into the Hash.
26
- Key coercions might be used, for example, in lightweight data modeling
27
- applications such as an API client:
28
-
29
- class Tweet < Hash
30
- include Hashie::Extensions::Coercion
31
- coerce_key :user, User
32
- end
33
-
34
- user_hash = {:name => "Bob"}
35
- Tweet.new(:user => user_hash)
36
- # => automatically calls User.coerce(user_hash) or
37
- # User.new(user_hash) if that isn't present.
38
-
39
- Value coercions, on the other hand, will coerce values based on the type
40
- of the value being inserted. This is useful if you are trying to build a
41
- Hash-like class that is self-propagating.
42
-
43
- class SpecialHash < Hash
44
- include Hashie::Extensions::Coercion
45
- coerce_value Hash, SpecialHash
46
-
47
- def initialize(hash = {})
48
- super
49
- hash.each_pair do |k,v|
50
- self[k] = v
51
- end
52
- end
53
- end
54
-
55
- ### KeyConversion
56
-
57
- The KeyConversion extension gives you the convenience methods of
58
- `symbolize_keys` and `stringify_keys` along with their bang
59
- counterparts. You can also include just stringify or just symbolize with
60
- `Hashie::Extensions::StringifyKeys` or `Hashie::Extensions::SymbolizeKeys`.
61
-
62
- ### MergeInitializer
63
-
64
- The MergeInitializer extension simply makes it possible to initialize a
65
- Hash subclass with another Hash, giving you a quick short-hand.
66
-
67
- ### MethodAccess
68
-
69
- The MethodAccess extension allows you to quickly build method-based
70
- reading, writing, and querying into your Hash descendant. It can also be
71
- included as individual modules, i.e. `Hashie::Extensions::MethodReader`,
72
- `Hashie::Extensions::MethodWriter` and `Hashie::Extensions::MethodQuery`
73
-
74
- class MyHash < Hash
75
- include Hashie::Extensions::MethodAccess
76
- end
77
-
78
- h = MyHash.new
79
- h.abc = 'def'
80
- h.abc # => 'def'
81
- h.abc? # => true
82
-
83
- ### IndifferentAccess
84
-
85
- This extension can be mixed in to instantly give you indifferent access
86
- to your Hash subclass. This works just like the params hash in Rails and
87
- other frameworks where whether you provide symbols or strings to access
88
- keys, you will get the same results.
89
-
90
- A unique feature of Hashie's IndifferentAccess mixin is that it will
91
- inject itself recursively into subhashes *without* reinitializing the
92
- hash in question. This means you can safely merge together indifferent
93
- and non-indifferent hashes arbitrarily deeply without worrying about
94
- whether you'll be able to `hash[:other][:another]` properly.
95
-
96
- ### DeepMerge
97
-
98
- This extension allow you to easily include a recursive merging
99
- system to any Hash descendant:
100
-
101
- class MyHash < Hash
102
- include Hashie::Extensions::DeepMerge
103
- end
104
-
105
- h1 = MyHash.new
106
- h2 = MyHash.new
107
-
108
- h1 = {:x => {:y => [4,5,6]}, :z => [7,8,9]}
109
- h2 = {:x => {:y => [7,8,9]}, :z => "xyz"}
110
-
111
- h1.deep_merge(h2) #=> { :x => {:y => [7, 8, 9]}, :z => "xyz" }
112
- h2.deep_merge(h1) #=> { :x => {:y => [4, 5, 6]}, :z => [7, 8, 9] }
113
-
114
- ## Mash
115
-
116
- Mash is an extended Hash that gives simple pseudo-object functionality
117
- that can be built from hashes and easily extended. It is designed to
118
- be used in RESTful API libraries to provide easy object-like access
119
- to JSON and XML parsed hashes.
120
-
121
- ### Example:
122
-
123
- mash = Hashie::Mash.new
124
- mash.name? # => false
125
- mash.name # => nil
126
- mash.name = "My Mash"
127
- mash.name # => "My Mash"
128
- mash.name? # => true
129
- mash.inspect # => <Hashie::Mash name="My Mash">
130
-
131
- mash = Mash.new
132
- # use bang methods for multi-level assignment
133
- mash.author!.name = "Michael Bleigh"
134
- mash.author # => <Hashie::Mash name="Michael Bleigh">
135
-
136
- mash = Mash.new
137
- # use under-bang methods for multi-level testing
138
- mash.author_.name? # => false
139
- mash.inspect # => <Hashie::Mash>
140
-
141
- **Note:** The `?` method will return false if a key has been set
142
- to false or nil. In order to check if a key has been set at all, use the
143
- `mash.key?('some_key')` method instead.
144
-
145
- ## Dash
146
-
147
- Dash is an extended Hash that has a discrete set of defined properties
148
- and only those properties may be set on the hash. Additionally, you
149
- can set defaults for each property. You can also flag a property as
150
- required. Required properties will raise an exception if unset.
151
-
152
- ### Example:
153
-
154
- class Person < Hashie::Dash
155
- property :name, :required => true
156
- property :email
157
- property :occupation, :default => 'Rubyist'
158
- end
159
-
160
- p = Person.new # => ArgumentError: The property 'name' is required for this Dash.
161
-
162
- p = Person.new(:name => "Bob")
163
- p.name # => 'Bob'
164
- p.name = nil # => ArgumentError: The property 'name' is required for this Dash.
165
- p.email = 'abc@def.com'
166
- p.occupation # => 'Rubyist'
167
- p.email # => 'abc@def.com'
168
- p[:awesome] # => NoMethodError
169
- p[:occupation] # => 'Rubyist'
170
-
171
- ## Trash
172
-
173
- A Trash is a Dash that allows you to translate keys on initialization.
174
- It is used like so:
175
-
176
- class Person < Hashie::Trash
177
- property :first_name, :from => :firstName
178
- end
179
-
180
- This will automatically translate the <tt>firstName</tt> key to <tt>first_name</tt>
181
- when it is initialized using a hash such as through:
182
-
183
- Person.new(:firstName => 'Bob')
184
-
185
- Trash also supports translations using lambda, this could be useful when dealing with
186
- external API's. You can use it in this way:
187
-
188
- class Result < Hashie::Trash
189
- property :id, :transform_with => lambda { |v| v.to_i }
190
- property :created_at, :from => :creation_date, :with => lambda { |v| Time.parse(v) }
191
- end
192
-
193
- this will produce the following
194
-
195
- result = Result.new(:id => '123', :creation_date => '2012-03-30 17:23:28')
196
- result.id.class # => Fixnum
197
- result.created_at.class # => Time
198
-
199
- ## Clash
200
-
201
- Clash is a Chainable Lazy Hash that allows you to easily construct
202
- complex hashes using method notation chaining. This will allow you
203
- to use a more action-oriented approach to building options hashes.
204
-
205
- Essentially, a Clash is a generalized way to provide much of the same
206
- kind of "chainability" that libraries like Arel or Rails 2.x's named_scopes
207
- provide.
208
-
209
- ### Example
210
-
211
- c = Hashie::Clash.new
212
- c.where(:abc => 'def').order(:created_at)
213
- c # => {:where => {:abc => 'def'}, :order => :created_at}
214
-
215
- # You can also use bang notation to chain into sub-hashes,
216
- # jumping back up the chain with _end!
217
- c = Hashie::Clash.new
218
- c.where!.abc('def').ghi(123)._end!.order(:created_at)
219
- c # => {:where => {:abc => 'def', :ghi => 123}, :order => :created_at}
220
-
221
- # Multiple hashes are merged automatically
222
- c = Hashie::Clash.new
223
- c.where(:abc => 'def').where(:hgi => 123)
224
- c # => {:where => {:abc => 'def', :hgi => 123}}
225
-
226
- ## Contributing
227
-
228
- See [CONTRIBUTING.md](CONTRIBUTING.md)
229
-
230
- ## Authors
231
-
232
- * Michael Bleigh
233
-
234
- ## Copyright
235
-
236
- Copyright (c) 2009-2013 Intridea, Inc. (http://intridea.com/). See LICENSE for details.
@@ -1,47 +0,0 @@
1
- module Hashie
2
- module Extensions
3
- # The Structure extension provides facilities for declaring
4
- # properties that a Hash can have. This provides for the
5
- # creation of structures that still behave like hashes but
6
- # do not allow setting non-allowed keys.
7
- #
8
- # @example
9
- # class RestrictedHash < Hash
10
- # include Hashie::Extensions::MergeInitializer
11
- # include Hashie::Extensions::Structure
12
- #
13
- # key :first
14
- # key :second, :default => 'foo'
15
- # end
16
- #
17
- # h = RestrictedHash.new(:first => 1)
18
- # h[:first] # => 1
19
- # h[:second] # => 'foo'
20
- # h[:third] # => ArgumentError
21
- #
22
- module Structure
23
- def self.included(base)
24
- base.extend ClassMethods
25
- base.class_eval do
26
- @permitted_keys = superclass.permitted_keys if superclass.respond_to?(:permitted_keys)
27
- end
28
- end
29
-
30
- module ClassMethods
31
- def key(key, options = {})
32
- (@permitted_keys ||= []) << key
33
-
34
- if options[:default]
35
- (@default_values ||= {})[key] = options.delete(:default)
36
- end
37
-
38
- permitted_keys
39
- end
40
-
41
- def permitted_keys
42
- @permitted_keys
43
- end
44
- end
45
- end
46
- end
47
- end