hashie 3.1.0 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f8151e8630508db39e56ae5ac2b5333913573f3f
4
- data.tar.gz: de13b700b22ff856acabc7be36581e32f50ea43e
3
+ metadata.gz: 9392e6b092e218e8f232ce4232ffc42e593321d8
4
+ data.tar.gz: 96d123ecbe640bf034bd43108e27da8d437d9720
5
5
  SHA512:
6
- metadata.gz: 4a2ea8a3fd07a80a75bbb4a687258c0ae92f3a85fdef18178bc9319fc0bc122a1c2b7d7f47fdfd6ba378d3459165642cdf8610e491d7e6438254a289434ed75f
7
- data.tar.gz: cf309ea2aec15071033875bcdeb4885f2a4755a0611856acdb44c4d92c07b2b8a739d5e81c42ba163014a0485788f7597ca055ae86f913105e6efea3f90b8519
6
+ metadata.gz: 13c30a48d328a2427cfe2325f0690e2621fcf601bc0354b5d0831f005e4c23ea4fc83b40aef250ce85b9c4434fe6733cff2b5be2822f313b9535485e7003eef6
7
+ data.tar.gz: e03895318b6f26ac05e394069c30eb9eb8a98f86b206996f04a19402dd2c283ad2cd52f203e739b7a2b30f7ae4282840a6be783ea8f21cf550e047d2ed732129
@@ -2,7 +2,7 @@ language: ruby
2
2
 
3
3
  rvm:
4
4
  - ruby-head
5
- - 2.1.1
5
+ - 2.1.2
6
6
  - 2.1.0
7
7
  - 2.0.0
8
8
  - 1.9.3
@@ -1,4 +1,14 @@
1
- ## 3.1 (7/25/2014)
1
+ ## 3.2.0 (7/10/2014)
2
+
3
+ * [#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).
4
+ * [#177](https://github.com/intridea/hashie/pull/177): Added support for coercing enumerables and collections - [@gregory](https://github.com/gregory).
5
+ * [#179](https://github.com/intridea/hashie/pull/179): Mash#values_at will convert each key before doing the lookup - [@nahiluhmot](https://github.com/nahiluhmot).
6
+ * [#184](https://github.com/intridea/hashie/pull/184): Allow ranges on Rash to match all Numeric types - [@medcat](https://github.com/medcat).
7
+ * [#187](https://github.com/intridea/hashie/pull/187): Automatically require version - [@medcat](https://github.com/medcat).
8
+ * [#190](https://github.com/intridea/hashie/issues/190): Fixed `coerce_key` with `from` Trash feature and Coercion extension - [@gregory](https://github.com/gregory).
9
+ * [#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).
10
+
11
+ ## 3.1.0 (6/25/2014)
2
12
 
3
13
  * [#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).
4
14
  * [#171](https://github.com/intridea/hashie/pull/171): Include Trash and Dash class name when raising `NoMethodError` - [@gregory](https://github.com/gregory).
@@ -6,7 +16,7 @@
6
16
  * [#173](https://github.com/intridea/hashie/pull/173): Auto include Dash::IndifferentAccess when IndiferentAccess is included in Dash - [@gregory](https://github.com/gregory).
7
17
  * [#174](https://github.com/intridea/hashie/pull/174): Fixed `from` and `transform_with` Trash features when IndifferentAccess is included - [@gregory](https://github.com/gregory).
8
18
 
9
- ## 3.0 (6/3/2014)
19
+ ## 3.0.0 (6/3/2014)
10
20
 
11
21
  **Note:** This version introduces several backward incompatible API changes. See [UPGRADING](UPGRADING.md) for details.
12
22
 
@@ -18,6 +28,7 @@
18
28
  * [#149](https://github.com/intridea/hashie/issues/149): Allow IgnoreUndeclared and DeepMerge to be used with undeclared properties - [@jhaesus](https://github.com/jhaesus).
19
29
 
20
30
  ## 2.1.1 (4/12/2014)
31
+
21
32
  * [#144](https://github.com/intridea/hashie/issues/144): Fixed regression invoking `to_hash` with no parameters - [@mbleigh](https://github.com/mbleigh).
22
33
 
23
34
  ## 2.1.0 (4/6/2014)
data/Gemfile CHANGED
@@ -8,4 +8,7 @@ end
8
8
 
9
9
  gemspec
10
10
 
11
- gem 'rubocop', '0.21.0'
11
+ gem 'rubocop', '0.24.1'
12
+
13
+ # ActiveSupport required to test compatibility with ActiveSupport Core Extensions.
14
+ gem 'activesupport', require: false
data/README.md CHANGED
@@ -12,7 +12,7 @@ $ gem install hashie
12
12
 
13
13
  ## Upgrading
14
14
 
15
- You're reading the documentation for the stable release of Hashie, 3.1. Please read [UPGRADING](UPGRADING.md) when upgrading from a previous version.
15
+ You're reading the documentation for the stable release of Hashie, 3.2.0. Please read [UPGRADING](UPGRADING.md) when upgrading from a previous version.
16
16
 
17
17
  ## Hash Extensions
18
18
 
@@ -52,6 +52,50 @@ class SpecialHash < Hash
52
52
  end
53
53
  ```
54
54
 
55
+ ### Coercing Collections
56
+
57
+ ```ruby
58
+ class Tweet < Hash
59
+ include Hashie::Extensions::Coercion
60
+ coerce_key :mentions, Array[User]
61
+ coerce_key :friends, Set[User]
62
+ end
63
+
64
+ user_hash = { name: "Bob" }
65
+ mentions_hash= [user_hash, user_hash]
66
+ friends_hash = [user_hash]
67
+ tweet = Tweet.new(mentions: mentions_hash, friends: friends_hash)
68
+ # => automatically calls User.coerce(user_hash) or
69
+ # User.new(user_hash) if that isn't present on each element of the array
70
+
71
+ tweet.mentions.map(&:class) # => [User, User]
72
+ tweet.friends.class # => Set
73
+ ```
74
+
75
+ ### Coercing Hashes
76
+
77
+ ```ruby
78
+ class Relation
79
+ def initialize(string)
80
+ @relation = string
81
+ end
82
+ end
83
+
84
+ class Tweet < Hash
85
+ include Hashie::Extensions::Coercion
86
+ coerce_key :relations, Hash[User => Relation]
87
+ end
88
+
89
+ user_hash = { name: "Bob" }
90
+ relations_hash= { user_hash => "father", user_hash => "friend" }
91
+ tweet = Tweet.new(relations: relations_hash)
92
+ tweet.relations.map { |k,v| [k.class, v.class] } # => [[User, Relation], [User, Relation]]
93
+ tweet.relations.class # => Hash
94
+
95
+ # => automatically calls User.coerce(user_hash) on each key
96
+ # and Relation.new on each value since Relation doesn't define the `coerce` class method
97
+ ```
98
+
55
99
  ### KeyConversion
56
100
 
57
101
  The KeyConversion extension gives you the convenience methods of `symbolize_keys` and `stringify_keys` along with their bang counterparts. You can also include just stringify or just symbolize with `Hashie::Extensions::StringifyKeys` or `Hashie::Extensions::SymbolizeKeys`.
data/Rakefile CHANGED
@@ -10,6 +10,6 @@ RSpec::Core::RakeTask.new do |spec|
10
10
  end
11
11
 
12
12
  require 'rubocop/rake_task'
13
- Rubocop::RakeTask.new(:rubocop)
13
+ RuboCop::RakeTask.new(:rubocop)
14
14
 
15
15
  task default: [:rubocop, :spec]
@@ -1,3 +1,5 @@
1
+ require 'hashie/version'
2
+
1
3
  module Hashie
2
4
  autoload :Clash, 'hashie/clash'
3
5
  autoload :Dash, 'hashie/dash'
@@ -2,25 +2,38 @@ module Hashie
2
2
  module Extensions
3
3
  module Coercion
4
4
  def self.included(base)
5
- base.extend ClassMethods
6
5
  base.send :include, InstanceMethods
6
+ base.extend ClassMethods # NOTE: we wanna make sure we first define set_value_with_coercion before extending
7
+
8
+ base.send :alias_method, :'set_value_without_coercion', :[]=
9
+ base.send :alias_method, :[]=, :'set_value_with_coercion'
7
10
  end
8
11
 
9
12
  module InstanceMethods
10
- def []=(key, value)
13
+ def set_value_with_coercion(key, value)
11
14
  into = self.class.key_coercion(key) || self.class.value_coercion(value)
12
15
 
13
- if value && into
14
- if into.respond_to?(:coerce)
15
- value = into.coerce(value)
16
- else
17
- value = into.new(value)
18
- end
16
+ return set_value_without_coercion(key, value) unless value && into
17
+ return set_value_without_coercion(key, coerce_or_init(into).call(value)) unless into.is_a?(Enumerable)
18
+
19
+ if into.class >= Hash
20
+ key_coerce = coerce_or_init(into.flatten[0])
21
+ value_coerce = coerce_or_init(into.flatten[-1])
22
+ value = Hash[value.map { |k, v| [key_coerce.call(k), value_coerce.call(v)] }]
23
+ else # Enumerable but not Hash: Array, Set
24
+ value_coerce = coerce_or_init(into.first)
25
+ value = into.class.new(value.map { |v| value_coerce.call(v) })
19
26
  end
20
27
 
21
- super(key, value)
28
+ set_value_without_coercion(key, value)
22
29
  end
23
30
 
31
+ def coerce_or_init(type)
32
+ type.respond_to?(:coerce) ? ->(v) { type.coerce(v) } : ->(v) { type.new(v) }
33
+ end
34
+
35
+ private :coerce_or_init
36
+
24
37
  def custom_writer(key, value, _convert = true)
25
38
  self[key] = value
26
39
  end
@@ -16,7 +16,7 @@ module Hashie
16
16
  def deep_fetch(*args, &block)
17
17
  args.reduce(self) do |obj, arg|
18
18
  begin
19
- arg = Integer(arg) if obj.kind_of? Array
19
+ arg = Integer(arg) if obj.is_a? Array
20
20
  obj.fetch(arg)
21
21
  rescue ArgumentError, IndexError, NoMethodError => e
22
22
  break block.call(arg) if block
@@ -31,9 +31,8 @@ module Hashie
31
31
  module IgnoreUndeclared
32
32
  def initialize_attributes(attributes)
33
33
  attributes.each_pair do |att, value|
34
- if self.class.property?(att) || (self.class.respond_to?(:translations) && self.class.translations.include?(att.to_sym))
35
- self[att] = value
36
- end
34
+ next unless self.class.property?(att) || (self.class.respond_to?(:translations) && self.class.translations.include?(att.to_sym))
35
+ self[att] = value
37
36
  end if attributes
38
37
  end
39
38
 
@@ -29,11 +29,11 @@ module Hashie
29
29
  end
30
30
 
31
31
  base.class_eval do
32
- alias_method :regular_writer, :[]=
32
+ alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
33
33
  alias_method :[]=, :indifferent_writer
34
34
  alias_method :store, :indifferent_writer
35
35
  %w(default update replace fetch delete key? values_at).each do |m|
36
- alias_method "regular_#{m}", m
36
+ alias_method "regular_#{m}", m unless method_defined?("regular_#{m}")
37
37
  alias_method m, "indifferent_#{m}"
38
38
  end
39
39
 
@@ -35,6 +35,12 @@ module Hashie
35
35
  object
36
36
  elsif object.respond_to?(:stringify_keys!)
37
37
  object.stringify_keys!
38
+ elsif ::Hash === object
39
+ object.keys.each do |k|
40
+ stringify_keys_recursively!(object[k])
41
+ object[k.to_s] = object.delete(k)
42
+ end
43
+ object
38
44
  else
39
45
  object
40
46
  end
@@ -128,6 +128,10 @@ module Hashie
128
128
  super(convert_key(key))
129
129
  end
130
130
 
131
+ def values_at(*keys)
132
+ super(*keys.map { |key| convert_key(key) })
133
+ end
134
+
131
135
  alias_method :regular_dup, :dup
132
136
  # Duplicates the current mash as a new mash.
133
137
  def dup
@@ -78,21 +78,20 @@ module Hashie
78
78
  # see if any of the regexps match the string
79
79
  @regexes.each do |regex|
80
80
  match = regex.match(query)
81
- if match
82
- @regex_counts[regex] += 1
83
- value = @hash[regex]
84
- if value.respond_to? :call
85
- yield value.call(match)
86
- else
87
- yield value
88
- end
81
+ next unless match
82
+ @regex_counts[regex] += 1
83
+ value = @hash[regex]
84
+ if value.respond_to? :call
85
+ yield value.call(match)
86
+ else
87
+ yield value
89
88
  end
90
89
  end
91
90
 
92
- when Integer
91
+ when Numeric
93
92
  # see if any of the ranges match the integer
94
93
  @ranges.each do |range|
95
- yield @hash[range] if range.include? query
94
+ yield @hash[range] if range.cover? query
96
95
  end
97
96
 
98
97
  when Regexp
@@ -110,10 +109,9 @@ module Hashie
110
109
  private
111
110
 
112
111
  def optimize_if_necessary!
113
- if (@lookups += 1) >= @optimize_every
114
- @regexes = @regex_counts.sort_by { |_, count| -count }.map { |regex, _| regex }
115
- @lookups = 0
116
- end
112
+ return unless (@lookups += 1) >= @optimize_every
113
+ @regexes = @regex_counts.sort_by { |_, count| -count }.map { |regex, _| regex }
114
+ @lookups = 0
117
115
  end
118
116
  end
119
117
  end
@@ -1,3 +1,3 @@
1
1
  module Hashie
2
- VERSION = '3.1.0'
2
+ VERSION = '3.2.0'
3
3
  end
@@ -50,6 +50,48 @@ describe Hashie::Extensions::Coercion do
50
50
  expect(instance[:bar]).to be_coerced
51
51
  end
52
52
 
53
+ it 'supports coercion for Array' do
54
+ subject.coerce_key :foo, Array[Coercable]
55
+
56
+ instance[:foo] = %w('bar', 'bar2')
57
+ expect(instance[:foo]).to all(be_coerced)
58
+ expect(instance[:foo]).to be_a(Array)
59
+ end
60
+
61
+ it 'supports coercion for Set' do
62
+ subject.coerce_key :foo, Set[Coercable]
63
+
64
+ instance[:foo] = Set.new(%w('bar', 'bar2'))
65
+ expect(instance[:foo]).to all(be_coerced)
66
+ expect(instance[:foo]).to be_a(Set)
67
+ end
68
+
69
+ it 'supports coercion for Set of primitive' do
70
+ subject.coerce_key :foo, Set[Initializable]
71
+
72
+ instance[:foo] = %w('bar', 'bar2')
73
+ expect(instance[:foo].map(&:value)).to all(eq 'String')
74
+ expect(instance[:foo]).to be_none { |v| v.coerced? }
75
+ expect(instance[:foo]).to be_a(Set)
76
+ end
77
+
78
+ it 'supports coercion for Hash' do
79
+ subject.coerce_key :foo, Hash[Coercable => Coercable]
80
+
81
+ instance[:foo] = { 'bar_key' => 'bar_value', 'bar2_key' => 'bar2_value' }
82
+ expect(instance[:foo].keys).to all(be_coerced)
83
+ expect(instance[:foo].values).to all(be_coerced)
84
+ expect(instance[:foo]).to be_a(Hash)
85
+ end
86
+
87
+ it 'supports coercion for Hash with primitive as value' do
88
+ subject.coerce_key :foo, Hash[Coercable => Initializable]
89
+
90
+ instance[:foo] = { 'bar_key' => '1', 'bar2_key' => '2' }
91
+ expect(instance[:foo].values.map(&:value)).to all(eq 'String')
92
+ expect(instance[:foo].keys).to all(be_coerced)
93
+ end
94
+
53
95
  it 'calls #new if no coerce method is available' do
54
96
  subject.coerce_key :foo, Initializable
55
97
 
@@ -114,6 +156,55 @@ describe Hashie::Extensions::Coercion do
114
156
  expect(tweet[:user]).to be_a(UserMash)
115
157
  end
116
158
  end
159
+
160
+ context 'when used with a Trash' do
161
+ class UserTrash < Hashie::Trash
162
+ property :email
163
+ end
164
+ class TweetTrash < Hashie::Trash
165
+ include Hashie::Extensions::Coercion
166
+
167
+ property :user, from: :user_data
168
+ coerce_key :user, UserTrash
169
+ end
170
+
171
+ it 'coerces with instance initialization' do
172
+ tweet = TweetTrash.new(user_data: { email: 'foo@bar.com' })
173
+ expect(tweet[:user]).to be_a(UserTrash)
174
+ end
175
+ end
176
+
177
+ context 'when used with IndifferentAccess to coerce a Mash' do
178
+ class MyHash < Hash
179
+ include Hashie::Extensions::Coercion
180
+ include Hashie::Extensions::IndifferentAccess
181
+ include Hashie::Extensions::MergeInitializer
182
+ end
183
+
184
+ class UserHash < MyHash
185
+ end
186
+
187
+ class TweetHash < MyHash
188
+ coerce_key :user, UserHash
189
+ end
190
+
191
+ it 'coerces with instance initialization' do
192
+ tweet = TweetHash.new(user: Hashie::Mash.new(email: 'foo@bar.com'))
193
+ expect(tweet[:user]).to be_a(UserHash)
194
+ end
195
+
196
+ it 'coerces when setting with string index' do
197
+ tweet = TweetHash.new
198
+ tweet['user'] = Hashie::Mash.new(email: 'foo@bar.com')
199
+ expect(tweet[:user]).to be_a(UserHash)
200
+ end
201
+
202
+ it 'coerces when setting with symbol index' do
203
+ tweet = TweetHash.new
204
+ tweet[:user] = Hashie::Mash.new(email: 'foo@bar.com')
205
+ expect(tweet[:user]).to be_a(UserHash)
206
+ end
207
+ end
117
208
  end
118
209
 
119
210
  describe '#coerce_value' do
@@ -0,0 +1,177 @@
1
+ # This set of tests verifies that Hashie::Extensions::IndifferentAccess works with
2
+ # ActiveSupport HashWithIndifferentAccess hashes. See #164 and #166 for details.
3
+
4
+ require 'spec_helper'
5
+ require 'active_support/hash_with_indifferent_access'
6
+
7
+ describe Hashie::Extensions::IndifferentAccess do
8
+ class IndifferentHashWithMergeInitializer < Hash
9
+ include Hashie::Extensions::MergeInitializer
10
+ include Hashie::Extensions::IndifferentAccess
11
+
12
+ class << self
13
+ alias_method :build, :new
14
+ end
15
+ end
16
+
17
+ class IndifferentHashWithArrayInitializer < Hash
18
+ include Hashie::Extensions::IndifferentAccess
19
+
20
+ class << self
21
+ alias_method :build, :[]
22
+ end
23
+ end
24
+
25
+ class IndifferentHashWithTryConvertInitializer < Hash
26
+ include Hashie::Extensions::IndifferentAccess
27
+
28
+ class << self
29
+ alias_method :build, :try_convert
30
+ end
31
+ end
32
+
33
+ shared_examples_for 'hash with indifferent access' do
34
+ it 'is able to access via string or symbol' do
35
+ indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(abc: 123)
36
+ h = subject.build(indifferent_hash)
37
+ expect(h[:abc]).to eq 123
38
+ expect(h['abc']).to eq 123
39
+ end
40
+
41
+ describe '#values_at' do
42
+ it 'indifferently finds values' do
43
+ indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(
44
+ :foo => 'bar', 'baz' => 'qux'
45
+ )
46
+ h = subject.build(indifferent_hash)
47
+ expect(h.values_at('foo', :baz)).to eq %w(bar qux)
48
+ end
49
+ end
50
+
51
+ describe '#fetch' do
52
+ it 'works like normal fetch, but indifferent' do
53
+ indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
54
+ h = subject.build(indifferent_hash)
55
+ expect(h.fetch(:foo)).to eq h.fetch('foo')
56
+ expect(h.fetch(:foo)).to eq 'bar'
57
+ end
58
+ end
59
+
60
+ describe '#delete' do
61
+ it 'deletes indifferently' do
62
+ indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(
63
+ :foo => 'bar',
64
+ 'baz' => 'qux'
65
+ )
66
+ h = subject.build(indifferent_hash)
67
+ h.delete('foo')
68
+ h.delete(:baz)
69
+ expect(h).to be_empty
70
+ end
71
+ end
72
+
73
+ describe '#key?' do
74
+ let(:h) do
75
+ indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
76
+ subject.build(indifferent_hash)
77
+ end
78
+
79
+ it 'finds it indifferently' do
80
+ expect(h).to be_key(:foo)
81
+ expect(h).to be_key('foo')
82
+ end
83
+
84
+ %w(include? member? has_key?).each do |key_alias|
85
+ it "is aliased as #{key_alias}" do
86
+ expect(h.send(key_alias.to_sym, :foo)).to be(true)
87
+ expect(h.send(key_alias.to_sym, 'foo')).to be(true)
88
+ end
89
+ end
90
+ end
91
+
92
+ describe '#update' do
93
+ let(:h) do
94
+ indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
95
+ subject.build(indifferent_hash)
96
+ end
97
+
98
+ it 'allows keys to be indifferent still' do
99
+ h.update(baz: 'qux')
100
+ expect(h['foo']).to eq 'bar'
101
+ expect(h['baz']).to eq 'qux'
102
+ end
103
+
104
+ it 'recursively injects indifference into sub-hashes' do
105
+ h.update(baz: { qux: 'abc' })
106
+ expect(h['baz']['qux']).to eq 'abc'
107
+ end
108
+
109
+ it 'does not change the ancestors of the injected object class' do
110
+ h.update(baz: { qux: 'abc' })
111
+ expect(Hash.new).not_to be_respond_to(:indifferent_access?)
112
+ end
113
+ end
114
+
115
+ describe '#replace' do
116
+ let(:h) do
117
+ indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
118
+ subject.build(indifferent_hash).replace(bar: 'baz', hi: 'bye')
119
+ end
120
+
121
+ it 'returns self' do
122
+ expect(h).to be_a(subject)
123
+ end
124
+
125
+ it 'removes old keys' do
126
+ [:foo, 'foo'].each do |k|
127
+ expect(h[k]).to be_nil
128
+ expect(h.key?(k)).to be_falsy
129
+ end
130
+ end
131
+
132
+ it 'creates new keys with indifferent access' do
133
+ [:bar, 'bar', :hi, 'hi'].each { |k| expect(h.key?(k)).to be_truthy }
134
+ expect(h[:bar]).to eq 'baz'
135
+ expect(h['bar']).to eq 'baz'
136
+ expect(h[:hi]).to eq 'bye'
137
+ expect(h['hi']).to eq 'bye'
138
+ end
139
+ end
140
+
141
+ describe '#try_convert' do
142
+ describe 'with conversion' do
143
+ let(:h) do
144
+ indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
145
+ subject.try_convert(indifferent_hash)
146
+ end
147
+
148
+ it 'is a subject' do
149
+ expect(h).to be_a(subject)
150
+ end
151
+ end
152
+
153
+ describe 'without conversion' do
154
+ let(:h) { subject.try_convert('{ :foo => bar }') }
155
+
156
+ it 'is nil' do
157
+ expect(h).to be_nil
158
+ end
159
+ end
160
+ end
161
+ end
162
+
163
+ describe 'with merge initializer' do
164
+ subject { IndifferentHashWithMergeInitializer }
165
+ it_should_behave_like 'hash with indifferent access'
166
+ end
167
+
168
+ describe 'with array initializer' do
169
+ subject { IndifferentHashWithArrayInitializer }
170
+ it_should_behave_like 'hash with indifferent access'
171
+ end
172
+
173
+ describe 'with try convert initializer' do
174
+ subject { IndifferentHashWithTryConvertInitializer }
175
+ it_should_behave_like 'hash with indifferent access'
176
+ end
177
+ end
@@ -13,10 +13,10 @@ describe Hash do
13
13
  expect(hash).to eq Hashie::Hash['a' => 'hey', '123' => 'bob']
14
14
  end
15
15
 
16
- it '#stringify_keys! turns all keys into strings non-recursively' do
16
+ it '#stringify_keys! turns all keys into strings recursively' do
17
17
  hash = Hashie::Hash[:a => 'hey', 123 => { 345 => 'hey' }]
18
18
  hash.stringify_keys!
19
- expect(hash).to eq Hashie::Hash['a' => 'hey', '123' => { 345 => 'hey' }]
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
@@ -476,4 +476,27 @@ describe Hashie::Mash do
476
476
  expect(hash).to eq Hashie::Hash['a' => 'hey', '123' => { '345' => 'hey' }]
477
477
  end
478
478
  end
479
+
480
+ describe '#values_at' do
481
+ let(:hash) { { 'key_one' => 1, :key_two => 2 } }
482
+ let(:mash) { Hashie::Mash.new(hash) }
483
+
484
+ context 'when the original type is given' do
485
+ it 'returns the values' do
486
+ expect(mash.values_at('key_one', :key_two)).to eq([1, 2])
487
+ end
488
+ end
489
+
490
+ context 'when a different, but acceptable type is given' do
491
+ it 'returns the values' do
492
+ expect(mash.values_at(:key_one, 'key_two')).to eq([1, 2])
493
+ end
494
+ end
495
+
496
+ context 'when a key is given that is not in the Mash' do
497
+ it 'returns nil for that value' do
498
+ expect(mash.values_at('key_one', :key_three)).to eq([1, nil])
499
+ end
500
+ end
501
+ end
479
502
  end
@@ -10,7 +10,7 @@ describe Hashie::Rash do
10
10
  1 => 'awesome',
11
11
  1..1000 => 'rangey',
12
12
  /(bcd)/ => proc { |m| m[1] }
13
- # /.+/ => "EVERYTHING"
13
+ # /.+/ => "EVERYTHING"
14
14
  )
15
15
  end
16
16
 
@@ -37,6 +37,12 @@ describe Hashie::Rash do
37
37
  expect(subject[1001]).to be_nil
38
38
  end
39
39
 
40
+ it 'finds floats from ranges' do
41
+ expect(subject[10.1]).to eq 'rangey'
42
+ expect(subject[1.0]).to eq 'rangey'
43
+ expect(subject[1000.1]).to be_nil
44
+ end
45
+
40
46
  it 'evaluates proc values' do
41
47
  expect(subject['abcdef']).to eq 'bcd'
42
48
  expect(subject['ffffff']).to be_nil
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.1.0
4
+ version: 3.2.0
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: 2014-06-25 00:00:00.000000000 Z
12
+ date: 2014-07-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -89,6 +89,7 @@ files:
89
89
  - spec/hashie/extensions/deep_merge_spec.rb
90
90
  - spec/hashie/extensions/ignore_undeclared_spec.rb
91
91
  - spec/hashie/extensions/indifferent_access_spec.rb
92
+ - spec/hashie/extensions/indifferent_access_with_rails_hwia_spec.rb
92
93
  - spec/hashie/extensions/key_conversion_spec.rb
93
94
  - spec/hashie/extensions/merge_initializer_spec.rb
94
95
  - spec/hashie/extensions/method_access_spec.rb
@@ -118,7 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
118
119
  version: '0'
119
120
  requirements: []
120
121
  rubyforge_project:
121
- rubygems_version: 2.0.14
122
+ rubygems_version: 2.1.11
122
123
  signing_key:
123
124
  specification_version: 4
124
125
  summary: Your friendly neighborhood hash library.
@@ -131,6 +132,7 @@ test_files:
131
132
  - spec/hashie/extensions/deep_merge_spec.rb
132
133
  - spec/hashie/extensions/ignore_undeclared_spec.rb
133
134
  - spec/hashie/extensions/indifferent_access_spec.rb
135
+ - spec/hashie/extensions/indifferent_access_with_rails_hwia_spec.rb
134
136
  - spec/hashie/extensions/key_conversion_spec.rb
135
137
  - spec/hashie/extensions/merge_initializer_spec.rb
136
138
  - spec/hashie/extensions/method_access_spec.rb