ruby_ext 0.4.11 → 0.4.12
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.
- 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
|