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
@@ -1,20 +1,23 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Hashie::Extensions::MergeInitializer do
4
- class MergeInitializerHash < Hash; include Hashie::Extensions::MergeInitializer end
5
- subject{ MergeInitializerHash }
4
+ class MergeInitializerHash < Hash
5
+ include Hashie::Extensions::MergeInitializer
6
+ end
7
+
8
+ subject { MergeInitializerHash }
6
9
 
7
- it 'should initialize fine with no arguments' do
8
- subject.new.should == {}
10
+ it 'initializes with no arguments' do
11
+ subject.new.should eq({})
9
12
  end
10
13
 
11
- it 'should initialize with a hash' do
12
- subject.new(:abc => 'def').should == {:abc => 'def'}
14
+ it 'initializes with a hash' do
15
+ subject.new(abc: 'def').should eq(abc: 'def')
13
16
  end
14
17
 
15
- it 'should initialize with a hash and a default' do
16
- h = subject.new({:abc => 'def'}, 'bar')
17
- h[:foo].should == 'bar'
18
- h[:abc].should == 'def'
18
+ it 'initializes with a hash and a default' do
19
+ h = subject.new({ abc: 'def' }, 'bar')
20
+ h[:foo].should eq 'bar'
21
+ h[:abc].should eq 'def'
19
22
  end
20
23
  end
@@ -2,39 +2,43 @@ require 'spec_helper'
2
2
 
3
3
  describe Hashie::Extensions::MethodReader do
4
4
  class ReaderHash < Hash
5
- def initialize(hash = {}); self.update(hash) end
6
5
  include Hashie::Extensions::MethodReader
6
+
7
+ def initialize(hash = {})
8
+ update(hash)
9
+ end
7
10
  end
8
- subject{ ReaderHash }
9
11
 
10
- it 'should read string keys from the method' do
11
- subject.new('awesome' => 'sauce').awesome.should == 'sauce'
12
+ subject { ReaderHash }
13
+
14
+ it 'reads string keys from the method' do
15
+ subject.new('awesome' => 'sauce').awesome.should eq 'sauce'
12
16
  end
13
17
 
14
- it 'should read symbol keys from the method' do
15
- subject.new(:awesome => 'sauce').awesome.should == 'sauce'
18
+ it 'reads symbol keys from the method' do
19
+ subject.new(awesome: 'sauce').awesome.should eq 'sauce'
16
20
  end
17
21
 
18
- it 'should read nil and false values out properly' do
19
- h = subject.new(:nil => nil, :false => false)
20
- h.nil.should == nil
21
- h.false.should == false
22
+ it 'reads nil and false values out properly' do
23
+ h = subject.new(nil: nil, false: false)
24
+ h.nil.should eq nil
25
+ h.false.should eq false
22
26
  end
23
27
 
24
- it 'should raise a NoMethodError for undefined keys' do
25
- lambda{ subject.new.awesome }.should raise_error(NoMethodError)
28
+ it 'raises a NoMethodError for undefined keys' do
29
+ lambda { subject.new.awesome }.should raise_error(NoMethodError)
26
30
  end
27
31
 
28
32
  describe '#respond_to?' do
29
- it 'should be true for string keys' do
33
+ it 'is true for string keys' do
30
34
  subject.new('awesome' => 'sauce').should be_respond_to(:awesome)
31
35
  end
32
36
 
33
- it 'should be true for symbol keys' do
34
- subject.new(:awesome => 'sauce').should be_respond_to(:awesome)
37
+ it 'is true for symbol keys' do
38
+ subject.new(awesome: 'sauce').should be_respond_to(:awesome)
35
39
  end
36
40
 
37
- it 'should be false for non-keys' do
41
+ it 'is false for non-keys' do
38
42
  subject.new.should_not be_respond_to(:awesome)
39
43
  end
40
44
  end
@@ -44,24 +48,25 @@ describe Hashie::Extensions::MethodWriter do
44
48
  class WriterHash < Hash
45
49
  include Hashie::Extensions::MethodWriter
46
50
  end
47
- subject{ WriterHash.new }
48
51
 
49
- it 'should write from a method call' do
52
+ subject { WriterHash.new }
53
+
54
+ it 'writes from a method call' do
50
55
  subject.awesome = 'sauce'
51
- subject['awesome'].should == 'sauce'
56
+ subject['awesome'].should eq 'sauce'
52
57
  end
53
58
 
54
- it 'should convert the key using the #convert_key method' do
59
+ it 'converts the key using the #convert_key method' do
55
60
  subject.stub!(:convert_key).and_return(:awesome)
56
61
  subject.awesome = 'sauce'
57
- subject[:awesome].should == 'sauce'
62
+ subject[:awesome].should eq 'sauce'
58
63
  end
59
64
 
60
- it 'should still NoMethodError on non equals-ending methods' do
61
- lambda{ subject.awesome }.should raise_error(NoMethodError)
65
+ it 'raises NoMethodError on non equals-ending methods' do
66
+ lambda { subject.awesome }.should raise_error(NoMethodError)
62
67
  end
63
68
 
64
- it 'should #respond_to? properly' do
69
+ it '#respond_to? correctly' do
65
70
  subject.should be_respond_to(:abc=)
66
71
  subject.should_not be_respond_to(:abc)
67
72
  end
@@ -69,44 +74,48 @@ end
69
74
 
70
75
  describe Hashie::Extensions::MethodQuery do
71
76
  class QueryHash < Hash
72
- def initialize(hash = {}); self.update(hash) end
73
77
  include Hashie::Extensions::MethodQuery
78
+
79
+ def initialize(hash = {})
80
+ update(hash)
81
+ end
74
82
  end
75
- subject{ QueryHash }
76
-
77
- it 'should be true for non-nil string key values' do
83
+
84
+ subject { QueryHash }
85
+
86
+ it 'is true for non-nil string key values' do
78
87
  subject.new('abc' => 123).should be_abc
79
88
  end
80
89
 
81
- it 'should be true for non-nil symbol key values' do
82
- subject.new(:abc => 123).should be_abc
90
+ it 'is true for non-nil symbol key values' do
91
+ subject.new(abc: 123).should be_abc
83
92
  end
84
93
 
85
- it 'should be false for nil key values' do
86
- subject.new(:abc => false).should_not be_abc
94
+ it 'is false for nil key values' do
95
+ subject.new(abc: false).should_not be_abc
87
96
  end
88
97
 
89
- it 'should raise a NoMethodError for non-set keys' do
90
- lambda{ subject.new.abc? }.should raise_error(NoMethodError)
98
+ it 'raises a NoMethodError for non-set keys' do
99
+ lambda { subject.new.abc? }.should raise_error(NoMethodError)
91
100
  end
92
101
 
93
- it 'should respond_to? for existing string keys' do
102
+ it '#respond_to? for existing string keys' do
94
103
  subject.new('abc' => 'def').should be_respond_to('abc?')
95
104
  end
96
105
 
97
- it 'should respond_to? for existing symbol keys' do
98
- subject.new(:abc => 'def').should be_respond_to(:abc?)
106
+ it '#respond_to? for existing symbol keys' do
107
+ subject.new(abc: 'def').should be_respond_to(:abc?)
99
108
  end
100
109
 
101
- it 'should not respond_to? for non-existent keys' do
110
+ it 'does not #respond_to? for non-existent keys' do
102
111
  subject.new.should_not be_respond_to('abc?')
103
112
  end
104
113
  end
105
114
 
106
115
  describe Hashie::Extensions::MethodAccess do
107
- it 'should include all of the other method mixins' do
116
+ it 'includes all of the other method mixins' do
108
117
  klass = Class.new(Hash)
109
118
  klass.send :include, Hashie::Extensions::MethodAccess
110
- (klass.ancestors & [Hashie::Extensions::MethodReader, Hashie::Extensions::MethodWriter, Hashie::Extensions::MethodQuery]).size.should == 3
119
+ (klass.ancestors & [Hashie::Extensions::MethodReader, Hashie::Extensions::MethodWriter, Hashie::Extensions::MethodQuery]).size.should eq 3
111
120
  end
112
121
  end
@@ -1,22 +1,34 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Hash do
4
- it "should be convertible to a Hashie::Mash" do
5
- mash = Hashie::Hash[:some => "hash"].to_mash
4
+ it 'is convertible to a Hashie::Mash' do
5
+ mash = Hashie::Hash[some: 'hash'].to_mash
6
6
  mash.is_a?(Hashie::Mash).should be_true
7
- mash.some.should == "hash"
7
+ mash.some.should eq 'hash'
8
8
  end
9
-
10
- it "#stringify_keys! should turn all keys into strings" do
11
- hash = Hashie::Hash[:a => "hey", 123 => "bob"]
9
+
10
+ it '#stringify_keys! turns all keys into strings' do
11
+ hash = Hashie::Hash[:a => 'hey', 123 => 'bob']
12
12
  hash.stringify_keys!
13
- hash.should == Hashie::Hash["a" => "hey", "123" => "bob"]
13
+ hash.should eq Hashie::Hash['a' => 'hey', '123' => 'bob']
14
14
  end
15
-
16
- it "#stringify_keys should return a hash with stringified keys" do
17
- hash = Hashie::Hash[:a => "hey", 123 => "bob"]
15
+
16
+ it '#stringify_keys returns a hash with stringified keys' do
17
+ hash = Hashie::Hash[:a => 'hey', 123 => 'bob']
18
18
  stringified_hash = hash.stringify_keys
19
- hash.should == Hashie::Hash[:a => "hey", 123 => "bob"]
20
- stringified_hash.should == Hashie::Hash["a" => "hey", "123" => "bob"]
19
+ hash.should eq Hashie::Hash[:a => 'hey', 123 => 'bob']
20
+ stringified_hash.should eq Hashie::Hash['a' => 'hey', '123' => 'bob']
21
+ end
22
+
23
+ it '#to_hash returns a hash with stringified keys' do
24
+ hash = Hashie::Hash['a' => 'hey', 123 => 'bob', 'array' => [1, 2, 3]]
25
+ stringified_hash = hash.to_hash
26
+ stringified_hash.should eq('a' => 'hey', '123' => 'bob', 'array' => [1, 2, 3])
27
+ end
28
+
29
+ it '#to_hash with symbolize_keys set to true returns a hash with symbolized keys' do
30
+ hash = Hashie::Hash['a' => 'hey', 123 => 'bob', 'array' => [1, 2, 3]]
31
+ symbolized_hash = hash.to_hash(symbolize_keys: true)
32
+ symbolized_hash.should eq(:a => 'hey', :"123" => 'bob', :array => [1, 2, 3])
21
33
  end
22
- end
34
+ end
@@ -2,207 +2,232 @@ require 'spec_helper'
2
2
  require 'delegate'
3
3
 
4
4
  describe Hashie::Mash do
5
- before(:each) do
6
- @mash = Hashie::Mash.new
7
- end
5
+ subject { Hashie::Mash.new }
8
6
 
9
- it "should inherit from hash" do
10
- @mash.is_a?(Hash).should be_true
7
+ it 'inherits from Hash' do
8
+ subject.is_a?(Hash).should be_true
11
9
  end
12
10
 
13
- it "should be able to set hash values through method= calls" do
14
- @mash.test = "abc"
15
- @mash["test"].should == "abc"
11
+ it 'sets hash values through method= calls' do
12
+ subject.test = 'abc'
13
+ subject['test'].should eq 'abc'
16
14
  end
17
15
 
18
- it "should be able to retrieve set values through method calls" do
19
- @mash["test"] = "abc"
20
- @mash.test.should == "abc"
16
+ it 'retrieves set values through method calls' do
17
+ subject['test'] = 'abc'
18
+ subject.test.should eq 'abc'
21
19
  end
22
20
 
23
- it "should be able to retrieve set values through blocks" do
24
- @mash["test"] = "abc"
21
+ it 'retrieves set values through blocks' do
22
+ subject['test'] = 'abc'
25
23
  value = nil
26
- @mash.[]("test") { |v| value = v }
27
- value.should == "abc"
24
+ subject.[]('test') { |v| value = v }
25
+ value.should eq 'abc'
28
26
  end
29
27
 
30
- it "should be able to retrieve set values through blocks with method calls" do
31
- @mash["test"] = "abc"
28
+ it 'retrieves set values through blocks with method calls' do
29
+ subject['test'] = 'abc'
32
30
  value = nil
33
- @mash.test { |v| value = v }
34
- value.should == "abc"
31
+ subject.test { |v| value = v }
32
+ value.should eq 'abc'
33
+ end
34
+
35
+ it 'tests for already set values when passed a ? method' do
36
+ subject.test?.should be_false
37
+ subject.test = 'abc'
38
+ subject.test?.should be_true
35
39
  end
36
40
 
37
- it "should test for already set values when passed a ? method" do
38
- @mash.test?.should be_false
39
- @mash.test = "abc"
40
- @mash.test?.should be_true
41
+ it 'returns false on a ? method if a value has been set to nil or false' do
42
+ subject.test = nil
43
+ subject.should_not be_test
44
+ subject.test = false
45
+ subject.should_not be_test
41
46
  end
42
47
 
43
- it "should return false on a ? method if a value has been set to nil or false" do
44
- @mash.test = nil
45
- @mash.should_not be_test
46
- @mash.test = false
47
- @mash.should_not be_test
48
+ it 'makes all [] and []= into strings for consistency' do
49
+ subject['abc'] = 123
50
+ subject.key?('abc').should be_true
51
+ subject['abc'].should eq 123
48
52
  end
49
53
 
50
- it "should make all [] and []= into strings for consistency" do
51
- @mash["abc"] = 123
52
- @mash.key?('abc').should be_true
53
- @mash["abc"].should == 123
54
+ it 'has a to_s that is identical to its inspect' do
55
+ subject.abc = 123
56
+ subject.to_s.should eq subject.inspect
54
57
  end
55
58
 
56
- it "should have a to_s that is identical to its inspect" do
57
- @mash.abc = 123
58
- @mash.to_s.should == @mash.inspect
59
+ it 'returns nil instead of raising an error for attribute-esque method calls' do
60
+ subject.abc.should be_nil
59
61
  end
60
62
 
61
- it "should return nil instead of raising an error for attribute-esque method calls" do
62
- @mash.abc.should be_nil
63
+ it 'returns the default value if set like Hash' do
64
+ subject.default = 123
65
+ subject.abc.should eq 123
63
66
  end
64
67
 
65
- it "should return a Hashie::Mash when passed a bang method to a non-existenct key" do
66
- @mash.abc!.is_a?(Hashie::Mash).should be_true
68
+ it 'gracefully handles being accessed with arguments' do
69
+ subject.abc('foobar').should eq nil
70
+ subject.abc = 123
71
+ subject.abc('foobar').should eq 123
67
72
  end
68
73
 
69
- it "should return the existing value when passed a bang method for an existing key" do
70
- @mash.name = "Bob"
71
- @mash.name!.should == "Bob"
74
+ it 'returns a Hashie::Mash when passed a bang method to a non-existenct key' do
75
+ subject.abc!.is_a?(Hashie::Mash).should be_true
72
76
  end
73
77
 
74
- it "should return a Hashie::Mash when passed an under bang method to a non-existenct key" do
75
- @mash.abc_.is_a?(Hashie::Mash).should be_true
78
+ it 'returns the existing value when passed a bang method for an existing key' do
79
+ subject.name = 'Bob'
80
+ subject.name!.should eq 'Bob'
76
81
  end
77
82
 
78
- it "should return the existing value when passed an under bang method for an existing key" do
79
- @mash.name = "Bob"
80
- @mash.name_.should == "Bob"
83
+ it 'returns a Hashie::Mash when passed an under bang method to a non-existenct key' do
84
+ subject.abc_.is_a?(Hashie::Mash).should be_true
81
85
  end
82
86
 
83
- it "#initializing_reader should return a Hashie::Mash when passed a non-existent key" do
84
- @mash.initializing_reader(:abc).is_a?(Hashie::Mash).should be_true
87
+ it 'returns the existing value when passed an under bang method for an existing key' do
88
+ subject.name = 'Bob'
89
+ subject.name_.should eq 'Bob'
85
90
  end
86
91
 
87
- it "should allow for multi-level assignment through bang methods" do
88
- @mash.author!.name = "Michael Bleigh"
89
- @mash.author.should == Hashie::Mash.new(:name => "Michael Bleigh")
90
- @mash.author!.website!.url = "http://www.mbleigh.com/"
91
- @mash.author.website.should == Hashie::Mash.new(:url => "http://www.mbleigh.com/")
92
+ it '#initializing_reader returns a Hashie::Mash when passed a non-existent key' do
93
+ subject.initializing_reader(:abc).is_a?(Hashie::Mash).should be_true
92
94
  end
93
95
 
94
- it "should allow for multi-level under bang testing" do
95
- @mash.author_.website_.url.should be_nil
96
- @mash.author_.website_.url?.should == false
97
- @mash.author.should be_nil
96
+ it 'allows for multi-level assignment through bang methods' do
97
+ subject.author!.name = 'Michael Bleigh'
98
+ subject.author.should eq Hashie::Mash.new(name: 'Michael Bleigh')
99
+ subject.author!.website!.url = 'http://www.mbleigh.com/'
100
+ subject.author.website.should eq Hashie::Mash.new(url: 'http://www.mbleigh.com/')
98
101
  end
99
102
 
100
- it "should not call super if id is not a key" do
101
- @mash.id.should == nil
103
+ it 'allows for multi-level under bang testing' do
104
+ subject.author_.website_.url.should be_nil
105
+ subject.author_.website_.url?.should eq false
106
+ subject.author.should be_nil
102
107
  end
103
108
 
104
- it "should return the value if id is a key" do
105
- @mash.id = "Steve"
106
- @mash.id.should == "Steve"
109
+ it 'does not call super if id is not a key' do
110
+ subject.id.should eq nil
107
111
  end
108
112
 
109
- it "should not call super if type is not a key" do
110
- @mash.type.should == nil
113
+ it 'returns the value if id is a key' do
114
+ subject.id = 'Steve'
115
+ subject.id.should eq 'Steve'
111
116
  end
112
117
 
113
- it "should return the value if type is a key" do
114
- @mash.type = "Steve"
115
- @mash.type.should == "Steve"
118
+ it 'does not call super if type is not a key' do
119
+ subject.type.should eq nil
116
120
  end
117
121
 
118
- context "updating" do
119
- subject {
120
- described_class.new :first_name => "Michael", :last_name => "Bleigh",
121
- :details => {:email => "michael@asf.com", :address => "Nowhere road"}
122
- }
122
+ it 'returns the value if type is a key' do
123
+ subject.type = 'Steve'
124
+ subject.type.should eq 'Steve'
125
+ end
123
126
 
124
- describe "#deep_update" do
125
- it "should recursively Hashie::Mash Hashie::Mashes and hashes together" do
126
- subject.deep_update(:details => {:email => "michael@intridea.com", :city => "Imagineton"})
127
- subject.first_name.should == "Michael"
128
- subject.details.email.should == "michael@intridea.com"
129
- subject.details.address.should == "Nowhere road"
130
- subject.details.city.should == "Imagineton"
127
+ context 'updating' do
128
+ subject do
129
+ described_class.new(
130
+ first_name: 'Michael',
131
+ last_name: 'Bleigh',
132
+ details: {
133
+ email: 'michael@asf.com',
134
+ address: 'Nowhere road'
135
+ })
136
+ end
137
+
138
+ describe '#deep_update' do
139
+ it 'recursively Hashie::Mash Hashie::Mashes and hashes together' do
140
+ subject.deep_update(details: { email: 'michael@intridea.com', city: 'Imagineton' })
141
+ subject.first_name.should eq 'Michael'
142
+ subject.details.email.should eq 'michael@intridea.com'
143
+ subject.details.address.should eq 'Nowhere road'
144
+ subject.details.city.should eq 'Imagineton'
131
145
  end
132
146
 
133
- it "should make #update deep by default" do
134
- subject.update(:details => {:address => "Fake street"}).should eql(subject)
135
- subject.details.address.should == "Fake street"
136
- subject.details.email.should == "michael@asf.com"
147
+ it 'converts values only once' do
148
+ class ConvertedMash < Hashie::Mash
149
+ end
150
+
151
+ rhs = ConvertedMash.new(email: 'foo@bar.com')
152
+ subject.should_receive(:convert_value).exactly(1).times
153
+ subject.deep_update(rhs)
154
+ end
155
+
156
+ it 'makes #update deep by default' do
157
+ subject.update(details: { address: 'Fake street' }).should eql(subject)
158
+ subject.details.address.should eq 'Fake street'
159
+ subject.details.email.should eq 'michael@asf.com'
137
160
  end
138
161
 
139
- it "should clone before a #deep_merge" do
140
- duped = subject.deep_merge(:details => {:address => "Fake street"})
162
+ it 'clones before a #deep_merge' do
163
+ duped = subject.deep_merge(details: { address: 'Fake street' })
141
164
  duped.should_not eql(subject)
142
- duped.details.address.should == "Fake street"
143
- subject.details.address.should == "Nowhere road"
144
- duped.details.email.should == "michael@asf.com"
165
+ duped.details.address.should eq 'Fake street'
166
+ subject.details.address.should eq 'Nowhere road'
167
+ duped.details.email.should eq 'michael@asf.com'
145
168
  end
146
169
 
147
- it "regular #merge should be deep" do
148
- duped = subject.merge(:details => {:email => "michael@intridea.com"})
170
+ it 'default #merge is deep' do
171
+ duped = subject.merge(details: { email: 'michael@intridea.com' })
149
172
  duped.should_not eql(subject)
150
- duped.details.email.should == "michael@intridea.com"
151
- duped.details.address.should == "Nowhere road"
173
+ duped.details.email.should eq 'michael@intridea.com'
174
+ duped.details.address.should eq 'Nowhere road'
152
175
  end
153
176
 
154
177
  # http://www.ruby-doc.org/core-1.9.3/Hash.html#method-i-update
155
- it "accepts a block" do
156
- duped = subject.merge(:details => {:address => "Pasadena CA"}) {|key, oldv, newv| [oldv, newv].join(', ')}
157
- duped.details.address.should == 'Nowhere road, Pasadena CA'
178
+ it 'accepts a block' do
179
+ duped = subject.merge(details: { address: 'Pasadena CA' }) { |key, oldv, newv| [oldv, newv].join(', ') }
180
+ duped.details.address.should eq 'Nowhere road, Pasadena CA'
158
181
  end
159
182
  end
160
183
 
161
- describe "shallow update" do
162
- it "should shallowly Hashie::Mash Hashie::Mashes and hashes together" do
163
- subject.shallow_update(:details => {
164
- :email => "michael@intridea.com", :city => "Imagineton"
184
+ describe 'shallow update' do
185
+ it 'shallowly Hashie::Mash Hashie::Mashes and hashes together' do
186
+ subject.shallow_update(details: {
187
+ email: 'michael@intridea.com', city: 'Imagineton'
165
188
  }).should eql(subject)
166
189
 
167
- subject.first_name.should == "Michael"
168
- subject.details.email.should == "michael@intridea.com"
190
+ subject.first_name.should eq 'Michael'
191
+ subject.details.email.should eq 'michael@intridea.com'
169
192
  subject.details.address.should be_nil
170
- subject.details.city.should == "Imagineton"
193
+ subject.details.city.should eq 'Imagineton'
171
194
  end
172
195
 
173
- it "should clone before a #regular_merge" do
174
- duped = subject.shallow_merge(:details => {:address => "Fake street"})
196
+ it 'clones before a #regular_merge' do
197
+ duped = subject.shallow_merge(details: { address: 'Fake street' })
175
198
  duped.should_not eql(subject)
176
199
  end
177
200
 
178
- it "regular merge should be shallow" do
179
- duped = subject.shallow_merge(:details => {:address => "Fake street"})
180
- duped.details.address.should == "Fake street"
181
- subject.details.address.should == "Nowhere road"
201
+ it 'default #merge is shallow' do
202
+ duped = subject.shallow_merge(details: { address: 'Fake street' })
203
+ duped.details.address.should eq 'Fake street'
204
+ subject.details.address.should eq 'Nowhere road'
182
205
  duped.details.email.should be_nil
183
206
  end
184
207
  end
185
208
 
186
209
  describe '#replace' do
187
210
  before do
188
- subject.replace(:middle_name => "Cain",
189
- :details => {:city => "Imagination"})
211
+ subject.replace(
212
+ middle_name: 'Cain',
213
+ details: { city: 'Imagination' }
214
+ )
190
215
  end
191
216
 
192
- it 'return self' do
193
- subject.replace(:foo => "bar").to_hash.should == {"foo" => "bar"}
217
+ it 'returns self' do
218
+ subject.replace(foo: 'bar').to_hash.should eq('foo' => 'bar')
194
219
  end
195
220
 
196
221
  it 'sets all specified keys to their corresponding values' do
197
222
  subject.middle_name?.should be_true
198
223
  subject.details?.should be_true
199
- subject.middle_name.should == "Cain"
224
+ subject.middle_name.should eq 'Cain'
200
225
  subject.details.city?.should be_true
201
- subject.details.city.should == "Imagination"
226
+ subject.details.city.should eq 'Imagination'
202
227
  end
203
228
 
204
229
  it 'leaves only specified keys' do
205
- subject.keys.sort.should == ['details', 'middle_name']
230
+ subject.keys.sort.should eq %w(details middle_name)
206
231
  subject.first_name?.should be_false
207
232
  subject.should_not respond_to(:first_name)
208
233
  subject.last_name?.should be_false
@@ -211,13 +236,13 @@ describe Hashie::Mash do
211
236
  end
212
237
 
213
238
  describe 'delete' do
214
- it 'should delete with String key' do
239
+ it 'deletes with String key' do
215
240
  subject.delete('details')
216
241
  subject.details.should be_nil
217
242
  subject.should_not be_respond_to :details
218
243
  end
219
244
 
220
- it 'should delete with Symbol key' do
245
+ it 'deletes with Symbol key' do
221
246
  subject.delete(:details)
222
247
  subject.details.should be_nil
223
248
  subject.should_not be_respond_to :details
@@ -225,22 +250,22 @@ describe Hashie::Mash do
225
250
  end
226
251
  end
227
252
 
228
- it "should convert hash assignments into Hashie::Mashes" do
229
- @mash.details = {:email => 'randy@asf.com', :address => {:state => 'TX'} }
230
- @mash.details.email.should == 'randy@asf.com'
231
- @mash.details.address.state.should == 'TX'
253
+ it 'converts hash assignments into Hashie::Mashes' do
254
+ subject.details = { email: 'randy@asf.com', address: { state: 'TX' } }
255
+ subject.details.email.should eq 'randy@asf.com'
256
+ subject.details.address.state.should eq 'TX'
232
257
  end
233
258
 
234
- it "should not convert the type of Hashie::Mashes childs to Hashie::Mash" do
259
+ it 'does not convert the type of Hashie::Mashes childs to Hashie::Mash' do
235
260
  class MyMash < Hashie::Mash
236
261
  end
237
262
 
238
263
  record = MyMash.new
239
264
  record.son = MyMash.new
240
- record.son.class.should == MyMash
265
+ record.son.class.should eq MyMash
241
266
  end
242
267
 
243
- it "should not change the class of Mashes when converted" do
268
+ it 'does not change the class of Mashes when converted' do
244
269
  class SubMash < Hashie::Mash
245
270
  end
246
271
 
@@ -250,7 +275,7 @@ describe Hashie::Mash do
250
275
  record['submash'].should be_kind_of(SubMash)
251
276
  end
252
277
 
253
- it "should respect the class when passed a bang method for a non-existent key" do
278
+ it 'respects the class when passed a bang method for a non-existent key' do
254
279
  record = Hashie::Mash.new
255
280
  record.non_existent!.should be_kind_of(Hashie::Mash)
256
281
 
@@ -261,7 +286,7 @@ describe Hashie::Mash do
261
286
  son.non_existent!.should be_kind_of(SubMash)
262
287
  end
263
288
 
264
- it "should respect the class when passed an under bang method for a non-existent key" do
289
+ it 'respects the class when passed an under bang method for a non-existent key' do
265
290
  record = Hashie::Mash.new
266
291
  record.non_existent_.should be_kind_of(Hashie::Mash)
267
292
 
@@ -272,141 +297,172 @@ describe Hashie::Mash do
272
297
  son.non_existent_.should be_kind_of(SubMash)
273
298
  end
274
299
 
275
- it "should respect the class when converting the value" do
300
+ it 'respects the class when converting the value' do
276
301
  record = Hashie::Mash.new
277
- record.details = Hashie::Mash.new({:email => "randy@asf.com"})
302
+ record.details = Hashie::Mash.new(email: 'randy@asf.com')
278
303
  record.details.should be_kind_of(Hashie::Mash)
279
304
  end
280
305
 
281
- it "should respect another subclass when converting the value" do
306
+ it 'respects another subclass when converting the value' do
282
307
  record = Hashie::Mash.new
283
308
 
284
309
  class SubMash < Hashie::Mash
285
310
  end
286
311
 
287
- son = SubMash.new({:email => "foo@bar.com"})
312
+ son = SubMash.new(email: 'foo@bar.com')
288
313
  record.details = son
289
314
  record.details.should be_kind_of(SubMash)
290
315
  end
291
316
 
292
- describe "#respond_to?" do
293
- it 'should respond to a normal method' do
317
+ describe '#respond_to?' do
318
+ it 'responds to a normal method' do
294
319
  Hashie::Mash.new.should be_respond_to(:key?)
295
320
  end
296
321
 
297
- it 'should respond to a set key' do
298
- Hashie::Mash.new(:abc => 'def').should be_respond_to(:abc)
322
+ it 'responds to a set key' do
323
+ Hashie::Mash.new(abc: 'def').should be_respond_to(:abc)
299
324
  end
300
325
 
301
- it 'should respond to a set key with a suffix' do
326
+ it 'responds to a set key with a suffix' do
302
327
  %w(= ? ! _).each do |suffix|
303
- Hashie::Mash.new(:abc => 'def').should be_respond_to(:"abc#{suffix}")
328
+ Hashie::Mash.new(abc: 'def').should be_respond_to(:"abc#{suffix}")
304
329
  end
305
330
  end
306
331
 
307
- it 'should respond to an unknown key with a suffix' do
332
+ it 'does not respond to an unknown key with a suffix' do
308
333
  %w(= ? ! _).each do |suffix|
309
- Hashie::Mash.new(:abc => 'def').should be_respond_to(:"xyz#{suffix}")
334
+ Hashie::Mash.new(abc: 'def').should_not be_respond_to(:"xyz#{suffix}")
310
335
  end
311
336
  end
312
337
 
313
- it "should not respond to an unknown key without a suffix" do
314
- Hashie::Mash.new(:abc => 'def').should_not be_respond_to(:xyz)
338
+ it 'does not respond to an unknown key without a suffix' do
339
+ Hashie::Mash.new(abc: 'def').should_not be_respond_to(:xyz)
340
+ end
341
+
342
+ it 'does not respond to permitted?' do
343
+ Hashie::Mash.new.should_not be_respond_to(:permitted?)
315
344
  end
316
345
  end
317
346
 
318
- context "#initialize" do
319
- it "should convert an existing hash to a Hashie::Mash" do
320
- converted = Hashie::Mash.new({:abc => 123, :name => "Bob"})
321
- converted.abc.should == 123
322
- converted.name.should == "Bob"
347
+ context '#initialize' do
348
+ it 'converts an existing hash to a Hashie::Mash' do
349
+ converted = Hashie::Mash.new(abc: 123, name: 'Bob')
350
+ converted.abc.should eq 123
351
+ converted.name.should eq 'Bob'
323
352
  end
324
353
 
325
- it "should convert hashes recursively into Hashie::Mashes" do
326
- converted = Hashie::Mash.new({:a => {:b => 1, :c => {:d => 23}}})
354
+ it 'converts hashes recursively into Hashie::Mashes' do
355
+ converted = Hashie::Mash.new(a: { b: 1, c: { d: 23 } })
327
356
  converted.a.is_a?(Hashie::Mash).should be_true
328
- converted.a.b.should == 1
329
- converted.a.c.d.should == 23
357
+ converted.a.b.should eq 1
358
+ converted.a.c.d.should eq 23
330
359
  end
331
360
 
332
- it "should convert hashes in arrays into Hashie::Mashes" do
333
- converted = Hashie::Mash.new({:a => [{:b => 12}, 23]})
334
- converted.a.first.b.should == 12
335
- converted.a.last.should == 23
361
+ it 'converts hashes in arrays into Hashie::Mashes' do
362
+ converted = Hashie::Mash.new(a: [{ b: 12 }, 23])
363
+ converted.a.first.b.should eq 12
364
+ converted.a.last.should eq 23
336
365
  end
337
366
 
338
- it "should convert an existing Hashie::Mash into a Hashie::Mash" do
339
- initial = Hashie::Mash.new(:name => 'randy', :address => {:state => 'TX'})
367
+ it 'converts an existing Hashie::Mash into a Hashie::Mash' do
368
+ initial = Hashie::Mash.new(name: 'randy', address: { state: 'TX' })
340
369
  copy = Hashie::Mash.new(initial)
341
- initial.name.should == copy.name
342
- initial.__id__.should_not == copy.__id__
343
- copy.address.state.should == 'TX'
370
+ initial.name.should eq copy.name
371
+ initial.__id__.should_not eq copy.__id__
372
+ copy.address.state.should eq 'TX'
344
373
  copy.address.state = 'MI'
345
- initial.address.state.should == 'TX'
346
- copy.address.__id__.should_not == initial.address.__id__
374
+ initial.address.state.should eq 'TX'
375
+ copy.address.__id__.should_not eq initial.address.__id__
347
376
  end
348
377
 
349
- it "should accept a default block" do
350
- initial = Hashie::Mash.new { |h,i| h[i] = []}
378
+ it 'accepts a default block' do
379
+ initial = Hashie::Mash.new { |h, i| h[i] = [] }
351
380
  initial.default_proc.should_not be_nil
352
381
  initial.default.should be_nil
353
- initial.test.should == []
382
+ initial.test.should eq []
354
383
  initial.test?.should be_true
355
384
  end
356
385
 
357
- it "should convert Hashie::Mashes within Arrays back to Hashes" do
358
- initial_hash = {"a" => [{"b" => 12, "c" =>["d" => 50, "e" => 51]}, 23]}
386
+ it 'converts Hashie::Mashes within Arrays back to Hashes' do
387
+ initial_hash = { 'a' => [{ 'b' => 12, 'c' => ['d' => 50, 'e' => 51] }, 23] }
359
388
  converted = Hashie::Mash.new(initial_hash)
360
- converted.to_hash["a"].first.is_a?(Hashie::Mash).should be_false
361
- converted.to_hash["a"].first.is_a?(Hash).should be_true
362
- converted.to_hash["a"].first["c"].first.is_a?(Hashie::Mash).should be_false
363
- converted.to_hash({:symbolize_keys => true}).keys[0].should == :a
389
+ converted.to_hash['a'].first.is_a?(Hashie::Mash).should be_false
390
+ converted.to_hash['a'].first.is_a?(Hash).should be_true
391
+ converted.to_hash['a'].first['c'].first.is_a?(Hashie::Mash).should be_false
364
392
  end
365
393
  end
366
394
 
367
- describe "#fetch" do
368
- let(:hash) { {:one => 1, :other => false} }
395
+ describe '#fetch' do
396
+ let(:hash) { { one: 1, other: false } }
369
397
  let(:mash) { Hashie::Mash.new(hash) }
370
398
 
371
- context "when key exists" do
372
- it "returns the value" do
399
+ context 'when key exists' do
400
+ it 'returns the value' do
373
401
  mash.fetch(:one).should eql(1)
374
402
  end
375
403
 
376
- it "returns the value even if the value is falsy" do
404
+ it 'returns the value even if the value is falsy' do
377
405
  mash.fetch(:other).should eql(false)
378
406
  end
379
407
 
380
- context "when key has other than original but acceptable type" do
381
- it "returns the value" do
408
+ context 'when key has other than original but acceptable type' do
409
+ it 'returns the value' do
382
410
  mash.fetch('one').should eql(1)
383
411
  end
384
412
  end
385
413
  end
386
414
 
387
- context "when key does not exist" do
388
- it "should raise KeyError" do
415
+ context 'when key does not exist' do
416
+ it 'raises KeyError' do
389
417
  error = RUBY_VERSION =~ /1.8/ ? IndexError : KeyError
390
418
  expect { mash.fetch(:two) }.to raise_error(error)
391
419
  end
392
420
 
393
- context "with default value given" do
394
- it "returns default value" do
421
+ context 'with default value given' do
422
+ it 'returns default value' do
395
423
  mash.fetch(:two, 8).should eql(8)
396
424
  end
397
425
 
398
- it "returns default value even if it is falsy" do
426
+ it 'returns default value even if it is falsy' do
399
427
  mash.fetch(:two, false).should eql(false)
400
428
  end
401
429
  end
402
430
 
403
- context "with block given" do
404
- it "returns default value" do
405
- mash.fetch(:two) {|key|
406
- "block default value"
407
- }.should eql("block default value")
431
+ context 'with block given' do
432
+ it 'returns default value' do
433
+ mash.fetch(:two) do |key|
434
+ 'block default value'
435
+ end.should eql('block default value')
408
436
  end
409
437
  end
410
438
  end
411
439
  end
440
+
441
+ describe '#to_hash' do
442
+ let(:hash) { { 'outer' => { 'inner' => 42 }, 'testing' => [1, 2, 3] } }
443
+ let(:mash) { Hashie::Mash.new(hash) }
444
+
445
+ it 'returns a standard Hash' do
446
+ mash.to_hash.should be_a(::Hash)
447
+ end
448
+
449
+ it 'includes all keys' do
450
+ mash.to_hash.keys.should eql(%w(outer testing))
451
+ end
452
+
453
+ it 'converts keys to symbols when symbolize_keys option is true' do
454
+ mash.to_hash(symbolize_keys: true).keys.should include(:outer)
455
+ mash.to_hash(symbolize_keys: true).keys.should_not include('outer')
456
+ end
457
+
458
+ it 'leaves keys as strings when symbolize_keys option is false' do
459
+ mash.to_hash(symbolize_keys: false).keys.should include('outer')
460
+ mash.to_hash(symbolize_keys: false).keys.should_not include(:outer)
461
+ end
462
+
463
+ it 'symbolizes keys recursively' do
464
+ mash.to_hash(symbolize_keys: true)[:outer].keys.should include(:inner)
465
+ mash.to_hash(symbolize_keys: true)[:outer].keys.should_not include('inner')
466
+ end
467
+ end
412
468
  end