ruby_ext 0.4.11 → 0.4.12
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +6 -6
- data/lib/rake_ext.rb +10 -5
- data/lib/rake_ext/project.rb +31 -16
- data/lib/rspec_ext.rb +82 -19
- data/lib/ruby_ext.rb +1 -52
- data/lib/ruby_ext/core.rb +24 -0
- data/lib/ruby_ext/{array.rb → core/array.rb} +4 -2
- data/lib/ruby_ext/core/basic_object.rb +8 -0
- data/lib/ruby_ext/core/class.rb +0 -0
- data/lib/ruby_ext/{deep_clone.rb → core/deep_clone.rb} +3 -4
- data/lib/ruby_ext/core/enumerable.rb +17 -0
- data/lib/ruby_ext/{file.rb → core/file.rb} +5 -2
- data/lib/ruby_ext/core/hash.rb +23 -0
- data/lib/ruby_ext/{kernel.rb → core/kernel.rb} +0 -0
- data/lib/ruby_ext/{micelaneous.rb → core/micelaneous.rb} +0 -0
- data/lib/ruby_ext/{module.rb → core/module.rb} +13 -2
- data/lib/ruby_ext/{multiple_inheritance.rb → core/multiple_inheritance.rb} +30 -14
- data/lib/ruby_ext/{must.rb → core/must.rb} +30 -27
- data/lib/ruby_ext/{not_defined.rb → core/not_defined.rb} +0 -0
- data/lib/ruby_ext/{object.rb → core/object.rb} +0 -0
- data/lib/ruby_ext/{open_object.rb → core/open_object.rb} +21 -16
- data/lib/ruby_ext/{string.rb → core/string.rb} +27 -0
- data/lib/ruby_ext/{symbol.rb → core/symbol.rb} +0 -0
- data/lib/ruby_ext/fixes.rb +6 -0
- data/lib/ruby_ext/gems.rb +0 -1
- data/lib/ruby_ext/more.rb +11 -0
- data/lib/ruby_ext/more/declarative_cache.rb +96 -0
- data/lib/ruby_ext/more/micelaneous.rb +7 -0
- data/lib/ruby_ext/{observable2.rb → more/observable2.rb} +0 -0
- data/lib/ruby_ext/{open_constructor.rb → more/open_constructor.rb} +2 -2
- data/lib/ruby_ext/more/safe_hash.rb +214 -0
- data/lib/ruby_ext/{synchronize.rb → more/synchronize.rb} +5 -5
- data/lib/ruby_ext/{tuple.rb → more/tuple.rb} +0 -0
- data/lib/yaml_fix.rb +9 -0
- data/readme.md +46 -42
- data/spec/core/array_spec.rb +7 -0
- data/spec/{deep_clone_spec.rb → core/deep_clone_spec.rb} +2 -3
- data/spec/core/enumerable.rb +9 -0
- data/spec/{kernel_spec.rb → core/kernel_spec.rb} +4 -6
- data/spec/{kernel_spec → core/kernel_spec}/TheNamespace/ClassA.rb +0 -0
- data/spec/{kernel_spec → core/kernel_spec}/another_class.rb +0 -0
- data/spec/{kernel_spec → core/kernel_spec}/the_namespace/class_b.rb +0 -0
- data/spec/{module_spec.rb → core/module_spec.rb} +2 -4
- data/spec/{multiple_inheritance_spec.rb → core/multiple_inheritance_spec.rb} +28 -12
- data/spec/core/must_spec.rb +32 -0
- data/spec/{open_object_spec.rb → core/open_object_spec.rb} +6 -7
- data/spec/core/spec_helper.rb +2 -0
- data/spec/{declarative_cache_spec.rb → more/declarative_cache_spec.rb} +35 -8
- data/spec/{observable2_spec.rb → more/observable2_spec.rb} +3 -4
- data/spec/{open_constructor_spec.rb → more/open_constructor_spec.rb} +6 -7
- data/spec/more/safe_hash_spec.rb +133 -0
- data/spec/more/spec_helper.rb +2 -0
- data/spec/{synchronize_spec.rb → more/synchronize_spec.rb} +2 -3
- metadata +67 -100
- data/lib/ruby_ext/basic_object.rb +0 -22
- data/lib/ruby_ext/class.rb +0 -11
- data/lib/ruby_ext/declarative_cache.rb +0 -85
- data/lib/ruby_ext/extra_blank_slate.rb +0 -17
- data/lib/ruby_ext/hash.rb +0 -15
- data/lib/ruby_ext/prepare_arguments.rb +0 -105
- data/lib/ruby_ext/prototype_inheritance.rb +0 -110
- data/lib/ruby_ext/should.rb +0 -166
- data/lib/rubyopt.rb +0 -7
- data/spec/_prototype_inheritance_spec.rb +0 -190
- data/spec/array_spec.rb +0 -8
- data/spec/must_spec.rb +0 -29
- data/spec/prepare_arguments_spec.rb +0 -46
- data/spec/should_spec.rb +0 -24
- data/spec/spec_helper.rb +0 -19
@@ -1,5 +1,4 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
require "ruby_ext/deep_clone"
|
1
|
+
require "core/spec_helper"
|
3
2
|
|
4
3
|
describe 'deep_clone' do
|
5
4
|
it "basic" do
|
@@ -32,6 +31,6 @@ describe 'deep_clone' do
|
|
32
31
|
m2.registry.should include(:a)
|
33
32
|
m2.registry[:b] = 2
|
34
33
|
|
35
|
-
m.registry.should == {:
|
34
|
+
m.registry.should == {a: 1}
|
36
35
|
end
|
37
36
|
end
|
@@ -1,5 +1,4 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
require "ruby_ext/kernel"
|
1
|
+
require "core/spec_helper"
|
3
2
|
|
4
3
|
describe 'Kernel' do
|
5
4
|
class Respond
|
@@ -17,10 +16,9 @@ describe 'Kernel' do
|
|
17
16
|
end
|
18
17
|
|
19
18
|
it "raise_without_self" do
|
20
|
-
|
21
|
-
require "#{
|
22
|
-
require "#{
|
23
|
-
require "#{dir}/kernel_spec/another_class"
|
19
|
+
require "#{spec_dir}/TheNamespace/ClassA"
|
20
|
+
require "#{spec_dir}/the_namespace/class_b"
|
21
|
+
require "#{spec_dir}/another_class"
|
24
22
|
|
25
23
|
begin
|
26
24
|
TheNamespace::ClassA.problem_method
|
File without changes
|
File without changes
|
File without changes
|
@@ -1,11 +1,10 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
require "ruby_ext/multiple_inheritance"
|
1
|
+
require "core/spec_helper"
|
3
2
|
|
4
3
|
describe "Multiple Inheritance" do
|
5
|
-
after
|
4
|
+
after do
|
6
5
|
remove_constants %w(M A M2 B AddedAfterInheritance)
|
7
6
|
end
|
8
|
-
|
7
|
+
|
9
8
|
it "showcase" do
|
10
9
|
module M
|
11
10
|
def instance_method; end
|
@@ -14,8 +13,8 @@ describe "Multiple Inheritance" do
|
|
14
13
|
def class_method; end
|
15
14
|
end
|
16
15
|
|
17
|
-
|
18
|
-
|
16
|
+
inherited do
|
17
|
+
attr_accessor :some_accessor
|
19
18
|
end
|
20
19
|
end
|
21
20
|
|
@@ -106,10 +105,10 @@ describe "Multiple Inheritance" do
|
|
106
105
|
inherit M
|
107
106
|
end
|
108
107
|
|
109
|
-
A.instance_methods.should_not include(
|
108
|
+
A.instance_methods.should_not include(:method_added_after_inheritance)
|
110
109
|
M.send(:define_method, :method_added_after_inheritance){}
|
111
|
-
M.instance_methods.should include(
|
112
|
-
A.instance_methods.should include(
|
110
|
+
M.instance_methods.should include(:method_added_after_inheritance)
|
111
|
+
A.instance_methods.should include(:method_added_after_inheritance)
|
113
112
|
end
|
114
113
|
|
115
114
|
it "modules included in base class after inheritance must be propagated to all descendants" do
|
@@ -123,9 +122,26 @@ describe "Multiple Inheritance" do
|
|
123
122
|
def module_added_after_inheritance; end
|
124
123
|
end
|
125
124
|
|
126
|
-
M.instance_methods.should_not include(
|
125
|
+
M.instance_methods.should_not include(:module_added_after_inheritance)
|
127
126
|
M.inherit AddedAfterInheritance
|
128
|
-
M.instance_methods.should include(
|
129
|
-
A.instance_methods.should include(
|
127
|
+
M.instance_methods.should include(:module_added_after_inheritance)
|
128
|
+
A.instance_methods.should include(:module_added_after_inheritance)
|
129
|
+
end
|
130
|
+
|
131
|
+
it "use case from error" do
|
132
|
+
class ItemSpec
|
133
|
+
end
|
134
|
+
|
135
|
+
class PageSpec < ItemSpec
|
136
|
+
end
|
137
|
+
|
138
|
+
module ::ItemSpecHelper
|
139
|
+
end
|
140
|
+
|
141
|
+
module ::PageSpecHelper
|
142
|
+
end
|
143
|
+
|
144
|
+
ItemSpec.inherit ItemSpecHelper
|
145
|
+
PageSpec.inherit PageSpecHelper
|
130
146
|
end
|
131
147
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require "core/spec_helper"
|
2
|
+
|
3
|
+
describe 'Assert' do
|
4
|
+
it 'must & must_not' do
|
5
|
+
-> {must_be.never_called}.should raise_error(/ever/)
|
6
|
+
-> {nil.must_not_be.nil}.should raise_error(/nil/)
|
7
|
+
1.must_not_be.nil
|
8
|
+
1.must_be.== 1
|
9
|
+
-> {1.must_be.== 2}.should raise_error(%r{==})
|
10
|
+
1.must_be.in 1, 2
|
11
|
+
1.must_be.in [1, 2]
|
12
|
+
0.must_be.in 0..1
|
13
|
+
"".must_be.a String
|
14
|
+
"".must_be.a String, Symbol
|
15
|
+
1.must_be.< 2
|
16
|
+
|
17
|
+
1.must_be.defined
|
18
|
+
-> {nil.must_be.defined}.should raise_error(/must be defined/)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'must_be & must_not_be' do
|
22
|
+
[].must_be.empty
|
23
|
+
[''].must_not_be.empty
|
24
|
+
|
25
|
+
-> {[''].must_be.empty}.should raise_error(/must be/)
|
26
|
+
-> {[].must_not_be.empty}.should raise_error(/must not be/)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should return result" do
|
30
|
+
[].must_be.empty.should == []
|
31
|
+
end
|
32
|
+
end
|
@@ -1,18 +1,17 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
require "ruby_ext/array"
|
1
|
+
require "core/spec_helper"
|
3
2
|
|
4
3
|
describe 'OpenObject' do
|
5
4
|
it 'should be comparable with hashes' do
|
6
5
|
{}.to_openobject.should == {}
|
7
6
|
{}.should == {}.to_openobject
|
8
7
|
|
9
|
-
{:
|
10
|
-
{'a' => :b}.to_openobject.should == {:
|
8
|
+
{a: :b}.to_openobject.should == {a: :b}
|
9
|
+
{'a' => :b}.to_openobject.should == {a: :b}
|
11
10
|
|
12
|
-
{:
|
11
|
+
{a: :b}.to_openobject.should == {'a' => :b}
|
13
12
|
{'a' => :b}.to_openobject.should == {'a' => :b}
|
14
13
|
|
15
|
-
{:
|
14
|
+
{a: :b}.to_openobject.should_not == {a: :c}
|
16
15
|
end
|
17
16
|
|
18
17
|
it "must be hash (from error)" do
|
@@ -21,7 +20,7 @@ describe 'OpenObject' do
|
|
21
20
|
|
22
21
|
it 'merge! should be indifferent to string and symbol' do
|
23
22
|
oo = OpenObject.new
|
24
|
-
oo.merge! :
|
23
|
+
oo.merge! a: true
|
25
24
|
oo.a.should be_true
|
26
25
|
oo.merge! 'b' => true
|
27
26
|
oo.b.should be_true
|
@@ -1,5 +1,4 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
require "ruby_ext/declarative_cache"
|
1
|
+
require "more/spec_helper"
|
3
2
|
|
4
3
|
describe 'DeclarativeCache' do
|
5
4
|
class CachedClass
|
@@ -36,7 +35,27 @@ describe 'DeclarativeCache' do
|
|
36
35
|
o.value2_get.should == 0
|
37
36
|
end
|
38
37
|
|
39
|
-
it "
|
38
|
+
it "should define <method>_with_cache and <method>_without_cache methods" do
|
39
|
+
o = CachedClass.new
|
40
|
+
|
41
|
+
# without params
|
42
|
+
o.value = 0
|
43
|
+
o.value_get.should == 0
|
44
|
+
o.value = 1
|
45
|
+
o.value_get.should == 0
|
46
|
+
o.value_get_with_cache.should == 0
|
47
|
+
o.value_get_without_cache.should == 1
|
48
|
+
|
49
|
+
# with params
|
50
|
+
o.params = {a: :b}
|
51
|
+
o.params_get(:a).should == :b
|
52
|
+
o.params = {a: :c}
|
53
|
+
o.params_get(:a).should == :b
|
54
|
+
o.params_get_with_cache(:a).should == :b
|
55
|
+
o.params_get_without_cache(:a).should == :c
|
56
|
+
end
|
57
|
+
|
58
|
+
it "clear_cache" do
|
40
59
|
o = CachedClass.new
|
41
60
|
o.value = 0
|
42
61
|
o.value_get.should == 0
|
@@ -44,7 +63,7 @@ describe 'DeclarativeCache' do
|
|
44
63
|
o.value = 1
|
45
64
|
o.value_get.should == 0
|
46
65
|
|
47
|
-
o.
|
66
|
+
o.clear_cache
|
48
67
|
o.value_get.should == 1
|
49
68
|
end
|
50
69
|
|
@@ -55,9 +74,9 @@ describe 'DeclarativeCache' do
|
|
55
74
|
|
56
75
|
it "Cache With Params" do
|
57
76
|
o = CachedClass.new
|
58
|
-
o.params = {:
|
77
|
+
o.params = {a: :b}
|
59
78
|
o.params_get(:a).should == :b
|
60
|
-
o.params = {:
|
79
|
+
o.params = {a: :c}
|
61
80
|
o.params_get(:a).should == :b
|
62
81
|
end
|
63
82
|
|
@@ -108,8 +127,16 @@ describe 'DeclarativeCache' do
|
|
108
127
|
def value_get; @value end
|
109
128
|
end
|
110
129
|
|
111
|
-
it "should not
|
130
|
+
it "should not cache twice, and should works" do
|
131
|
+
CachedClass4.cache_method :value_get
|
132
|
+
|
133
|
+
Object.should_receive(:warn){|msg| msg =~ /twice/}
|
112
134
|
CachedClass4.cache_method :value_get
|
113
|
-
|
135
|
+
|
136
|
+
o = CachedClass.new
|
137
|
+
o.value = 0
|
138
|
+
o.value_get.should == 0
|
139
|
+
o.value = 1
|
140
|
+
o.value_get.should == 0
|
114
141
|
end
|
115
142
|
end
|
@@ -1,5 +1,4 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
require "ruby_ext/observable2"
|
1
|
+
require "more/spec_helper"
|
3
2
|
|
4
3
|
describe "Observable" do
|
5
4
|
class AnObservable
|
@@ -17,7 +16,7 @@ describe "Observable" do
|
|
17
16
|
# it "Method without Parameters" do
|
18
17
|
# mock = mock("Observer")
|
19
18
|
# obs = AnObservable.new
|
20
|
-
# obs.add_observer(mock, :
|
19
|
+
# obs.add_observer(mock, method: :custom_update, filter: -> {|o| o == 2})
|
21
20
|
# mock.should_receive(:custom_update).with(2)
|
22
21
|
# obs.notify_observers 2
|
23
22
|
# obs.notify_observers 4
|
@@ -34,7 +33,7 @@ describe "Observable" do
|
|
34
33
|
# it "With Block and Filter" do
|
35
34
|
# mock = mock("Observer")
|
36
35
|
# obs = AnObservable.new
|
37
|
-
# obs.add_observer(:
|
36
|
+
# obs.add_observer(filter: -> {|o| o == 2}){|o| mock.got o}
|
38
37
|
# mock.should_receive(:got).with(2)
|
39
38
|
# obs.notify_observers 2
|
40
39
|
# obs.notify_observers 4
|
@@ -1,5 +1,4 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
require "ruby_ext/open_constructor"
|
1
|
+
require "more/spec_helper"
|
3
2
|
|
4
3
|
describe 'OpenConstructor' do
|
5
4
|
class Test
|
@@ -8,28 +7,28 @@ describe 'OpenConstructor' do
|
|
8
7
|
end
|
9
8
|
|
10
9
|
it 'should initialize atributes from Hash' do
|
11
|
-
t = Test.new.set(:
|
10
|
+
t = Test.new.set(name: 'name', value: 'value')
|
12
11
|
[t.name, t.value].should == ['name', 'value']
|
13
12
|
end
|
14
13
|
|
15
14
|
it 'should initialize atributes from any Object' do
|
16
|
-
t = Test.new.set(:
|
15
|
+
t = Test.new.set(name: 'name', value: 'value')
|
17
16
|
t2 = Test.new.set t
|
18
17
|
[t2.name, t2.value].should == ['name', 'value']
|
19
18
|
end
|
20
19
|
|
21
20
|
it 'restrict copied values' do
|
22
|
-
t = Test.new.set(:
|
21
|
+
t = Test.new.set(name: 'name', value: 'value')
|
23
22
|
t2 = Test.new.set t, [:name]
|
24
23
|
[t2.name, t2.value].should == ['name', nil]
|
25
24
|
|
26
|
-
t = {:
|
25
|
+
t = {name: 'name', value: 'value'}
|
27
26
|
t2 = Test.new.set t, [:name]
|
28
27
|
[t2.name, t2.value].should == ['name', nil]
|
29
28
|
end
|
30
29
|
|
31
30
|
it 'to_hash' do
|
32
|
-
h = {:
|
31
|
+
h = {name: 'name', value: 'value'}
|
33
32
|
t = Test.new.set h
|
34
33
|
t.to_hash.should == h
|
35
34
|
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'more/spec_helper'
|
2
|
+
|
3
|
+
describe "SafeHash and SafeNil" do
|
4
|
+
it "should allow check for value presence" do
|
5
|
+
h = SafeHash.new a: :b
|
6
|
+
h.a?.should be_true
|
7
|
+
h.b?.should be_false
|
8
|
+
|
9
|
+
h.should include(:a)
|
10
|
+
h.should_not include(:b)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "? should return boolean (from error)" do
|
14
|
+
h = SafeHash.new
|
15
|
+
lambda{raise "" unless h.a?.class.equal?(NilClass)}.should raise_error
|
16
|
+
lambda{raise "" unless h.a.a?.class.equal?(NilClass)}.should raise_error
|
17
|
+
end
|
18
|
+
|
19
|
+
it "passing block should be threated as invalid usage" do
|
20
|
+
h = SafeHash.new
|
21
|
+
lambda{h.development{}}.should raise_error(/invalid usage/)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should treat assigned nil as value (from error)" do
|
25
|
+
h = SafeHash.new v: nil
|
26
|
+
h.v?.should be_true
|
27
|
+
h.v!.should == nil
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should not allow direct modification of hash" do
|
31
|
+
h = SafeHash.new
|
32
|
+
lambda{h.a = 1}.should raise_error(/forbidden/)
|
33
|
+
lambda{h[:a] = 1}.should raise_error(/forbidden/)
|
34
|
+
lambda{h.a.b = 1}.should raise_error(/forbidden/)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should not allo"
|
38
|
+
|
39
|
+
# it "should allow owerride values" do
|
40
|
+
# h = SafeHash.new a: :b
|
41
|
+
# h.b = :c
|
42
|
+
# h.b!.should == :c
|
43
|
+
# end
|
44
|
+
|
45
|
+
it "general behaviour" do
|
46
|
+
h = SafeHash.new key: :value
|
47
|
+
|
48
|
+
h.key.should == :value
|
49
|
+
h.key(:missing).should == :value
|
50
|
+
|
51
|
+
h[:key].should == :value
|
52
|
+
h[:key, :missing].should == :value
|
53
|
+
|
54
|
+
h['key'].should == :value
|
55
|
+
h['key', :missing].should == :value
|
56
|
+
|
57
|
+
h.a.b.c[:d].e('missing').should == 'missing'
|
58
|
+
h.a.b.c[:d][:e, 'missing'].should == 'missing'
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should build hierarchies of SafeHash" do
|
62
|
+
h = SafeHash.new a: {a: :b}
|
63
|
+
|
64
|
+
h.a.a.should == :b
|
65
|
+
h.a.missing.b.c('missing').should == 'missing'
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should require setting if ! used" do
|
69
|
+
h = SafeHash.new a: :v, b: {c: :v}
|
70
|
+
|
71
|
+
h.a!.should == :v
|
72
|
+
h.b.c!.should == :v
|
73
|
+
h.b!.c!.should == :v
|
74
|
+
|
75
|
+
lambda{h.j!}.should raise_error(/no key :j/)
|
76
|
+
lambda{h.j.b.c!}.should raise_error(/no key :c/)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should be able to update itself" do
|
80
|
+
h = SafeHash.new
|
81
|
+
h.b?.should be_false
|
82
|
+
h.merge! a: :a
|
83
|
+
h.a!.should == :a
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should implement include?" do
|
87
|
+
h = SafeHash.new a: :b
|
88
|
+
h.include?(:a).should be_true
|
89
|
+
h.include?('a').should be_true
|
90
|
+
h.include?(:b).should be_false
|
91
|
+
|
92
|
+
h.b.include?(:a).should be_false
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "merge" do
|
96
|
+
it "should not override by default" do
|
97
|
+
h = SafeHash.new a: :b
|
98
|
+
lambda{h.merge! a: :c}.should raise_error(/can't override/)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should skip existing if specified" do
|
102
|
+
h = SafeHash.new a: :b
|
103
|
+
h.merge!({a: :c, d: :e}, blank: true)
|
104
|
+
h.a!.should == :b
|
105
|
+
h.d!.should == :e
|
106
|
+
end
|
107
|
+
|
108
|
+
it "merging hashes should not be countig as overriding" do
|
109
|
+
h = SafeHash.new b: {c: :d}
|
110
|
+
h.merge! b: {e: :f}, override: false
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should override if specified" do
|
114
|
+
h = SafeHash.new a: {b: :c}
|
115
|
+
h.merge!({a: {b: :c2}}, override: true)
|
116
|
+
h.a!.b!.should == :c2
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should perform deep merge by default" do
|
120
|
+
h = SafeHash.new a: {b: {c: :d}}
|
121
|
+
h.merge!({a: {b: {c2: :d2}}})
|
122
|
+
h.a!.b!.c?.should be_true
|
123
|
+
h.a!.b!.c2?.should be_true
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
it "merge_if_blank" do
|
128
|
+
h = SafeHash.new a: :b
|
129
|
+
h.merge_if_blank! a: :c, d: :e
|
130
|
+
h.a!.should == :b
|
131
|
+
h.d!.should == :e
|
132
|
+
end
|
133
|
+
end
|