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.
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