gorillib 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +49 -0
- data/.rspec +2 -0
- data/CHANGELOG.textile +49 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +36 -0
- data/README.textile +6 -1
- data/Rakefile +42 -9
- data/VERSION +1 -1
- data/gorillib.gemspec +110 -73
- data/lib/gorillib/array/deep_compact.rb +3 -12
- data/lib/gorillib/datetime/#flat.rb# +30 -0
- data/lib/gorillib/datetime/flat.rb +2 -10
- data/lib/gorillib/datetime/parse.rb +3 -1
- data/lib/gorillib/enumerable/sum.rb +37 -35
- data/lib/gorillib/hash/deep_compact.rb +3 -13
- data/lib/gorillib/logger/log.rb +1 -1
- data/lib/gorillib/numeric/clamp.rb +9 -0
- data/lib/gorillib/object/try.rb +10 -0
- data/lib/gorillib/object/try_dup.rb +44 -0
- data/lib/gorillib/string/human.rb +1 -3
- data/lib/gorillib/string/truncate.rb +2 -2
- data/spec/array/compact_blank_spec.rb +37 -0
- data/spec/array/extract_options_spec.rb +47 -0
- data/spec/datetime/flat_spec.rb +38 -0
- data/spec/datetime/parse_spec.rb +48 -0
- data/spec/enumerable/sum_spec.rb +56 -0
- data/spec/hash/compact_spec.rb +70 -0
- data/spec/hash/deep_compact_spec.rb +37 -0
- data/spec/hash/deep_merge_spec.rb +117 -0
- data/spec/hash/keys_spec.rb +111 -0
- data/spec/hash/reverse_merge_spec.rb +25 -0
- data/spec/hash/slice_spec.rb +43 -0
- data/spec/hash/zip_spec.rb +31 -0
- data/spec/logger/log_spec.rb +31 -0
- data/spec/metaprogramming/aliasing_spec.rb +177 -0
- data/spec/metaprogramming/cattr_accessor_spec.rb +41 -0
- data/spec/metaprogramming/class_attribute_spec.rb +75 -0
- data/spec/metaprogramming/delegation_spec.rb +166 -0
- data/spec/metaprogramming/mattr_accessor_spec.rb +44 -0
- data/spec/metaprogramming/singleton_class_spec.rb +9 -0
- data/spec/{numeric_spec.rb → numeric/clamp_spec.rb} +2 -2
- data/spec/object/blank_spec.rb +93 -0
- data/spec/object/try_dup_spec.rb +47 -0
- data/spec/object/try_spec.rb +20 -0
- data/spec/spec_helper.rb +13 -8
- data/spec/string/constantize_spec.rb +56 -0
- data/spec/string/human_spec.rb +66 -0
- data/spec/string/inflections_spec.rb +74 -0
- data/{test → spec}/string/inflector_test_cases.rb +0 -0
- data/spec/string/truncate_spec.rb +42 -0
- data/spec/support/kcode_test_helper.rb +16 -0
- metadata +209 -96
- data/.document +0 -5
- data/fiddle/hubahuba.rb +0 -62
- data/spec/blank_spec.rb +0 -86
- data/spec/deep_compact_spec.rb +0 -36
- data/spec/gorillib_spec.rb +0 -7
- data/spec/rcov.opts +0 -6
- data/spec/spec.opts +0 -4
- data/spec/spec_tasks.rake +0 -15
- data/test/abstract_unit.rb +0 -25
- data/test/array/compact_blank_test.rb +0 -33
- data/test/array/extract_options_test.rb +0 -39
- data/test/datetime/flat_test.rb +0 -0
- data/test/datetime/parse_test.rb +0 -0
- data/test/enumerable/sum_test.rb +0 -50
- data/test/hash/compact_test.rb +0 -38
- data/test/hash/deep_merge_test.rb +0 -30
- data/test/hash/keys_test.rb +0 -110
- data/test/hash/reverse_merge_test.rb +0 -20
- data/test/hash/slice_test.rb +0 -47
- data/test/hash/zip_test.rb +0 -0
- data/test/logger/log_test.rb +0 -0
- data/test/metaprogramming/aliasing_test.rb +0 -188
- data/test/metaprogramming/cattr_accessor_test.rb +0 -38
- data/test/metaprogramming/class_attribute_test.rb +0 -73
- data/test/metaprogramming/delegation_test.rb +0 -166
- data/test/metaprogramming/mattr_accessor_test.rb +0 -40
- data/test/metaprogramming/singleton_class_test.rb +0 -9
- data/test/object/blank_test.rb +0 -22
- data/test/string/constantize_test.rb +0 -30
- data/test/string/human_test.rb +0 -65
- data/test/string/inflections_test.rb +0 -57
- data/test/string/truncate_test.rb +0 -37
@@ -0,0 +1,111 @@
|
|
1
|
+
require File.dirname(__FILE__)+'/../spec_helper'
|
2
|
+
require 'gorillib/hash/keys'
|
3
|
+
|
4
|
+
describe Hash do
|
5
|
+
class SubclassingArray < Array
|
6
|
+
end
|
7
|
+
|
8
|
+
class SubclassingHash < Hash
|
9
|
+
end
|
10
|
+
|
11
|
+
before do
|
12
|
+
@strings = { 'a' => 1, 'b' => 2 }
|
13
|
+
@symbols = { :a => 1, :b => 2 }
|
14
|
+
@mixed = { :a => 1, 'b' => 2 }
|
15
|
+
@fixnums = { 0 => 1, 1 => 2 }
|
16
|
+
if RUBY_VERSION < '1.9.0'
|
17
|
+
@illegal_symbols = { "\0" => 1, "" => 2, [] => 3 }
|
18
|
+
else
|
19
|
+
@illegal_symbols = { [] => 3 }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'responds to #symbolize_keys, #symbolize_keys!, #stringify_keys, #stringify_keys!' do
|
24
|
+
{}.should respond_to(:symbolize_keys )
|
25
|
+
{}.should respond_to(:symbolize_keys!)
|
26
|
+
{}.should respond_to(:stringify_keys )
|
27
|
+
{}.should respond_to(:stringify_keys!)
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#symbolize_keys' do
|
31
|
+
it 'converts keys that are all symbols' do
|
32
|
+
@symbols.symbolize_keys.should == @symbols
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'converts keys that are all strings' do
|
36
|
+
@strings.symbolize_keys.should == @symbols
|
37
|
+
@strings['a'].should == 1
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'converts keys that are mixed' do
|
41
|
+
@mixed.symbolize_keys.should == @symbols
|
42
|
+
@mixed['b'].should == 2
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '#symbolize_keys!' do
|
47
|
+
it 'converts keys that are all symbols' do
|
48
|
+
@symbols.symbolize_keys!.should == @symbols
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'converts keys that are all strings' do
|
52
|
+
@strings.symbolize_keys!.should == @symbols
|
53
|
+
@strings[:a].should == 1
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'converts keys that are mixed' do
|
57
|
+
@mixed.symbolize_keys!.should == @symbols
|
58
|
+
@mixed[:b].should == 2
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'preserves keys that can not be symbolized' do
|
62
|
+
@illegal_symbols.symbolize_keys.should == @illegal_symbols
|
63
|
+
@illegal_symbols.dup.symbolize_keys!.should == @illegal_symbols
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'preserves fixnum keys' do
|
67
|
+
@fixnums.symbolize_keys.should == @fixnums
|
68
|
+
@fixnums.dup.symbolize_keys!.should == @fixnums
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '#stringify_keys' do
|
73
|
+
it 'converts keys that are all symbols' do
|
74
|
+
@symbols.stringify_keys.should == @strings
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'converts keys that are all strings' do
|
78
|
+
@strings.stringify_keys.should == @strings
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'converts keys that are mixed' do
|
82
|
+
@mixed.stringify_keys.should == @strings
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe '#stringify_keys!' do
|
87
|
+
it 'converts keys that are all symbols' do
|
88
|
+
@symbols.dup.stringify_keys!.should == @strings
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'converts keys that are all strings' do
|
92
|
+
@strings.dup.stringify_keys!.should == @strings
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'converts keys that are all mixed' do
|
96
|
+
@mixed.dup.stringify_keys!.should == @strings
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe '#assert_valid_keys' do
|
101
|
+
it 'succeeds when valid' do
|
102
|
+
{ :failure => "stuff", :funny => "business" }.assert_valid_keys([ :failure, :funny ]).should be_nil
|
103
|
+
{ :failure => "stuff", :funny => "business" }.assert_valid_keys(:failure, :funny).should be_nil
|
104
|
+
end
|
105
|
+
it 'raises when there are invalid keys' do
|
106
|
+
lambda{ { :failore => "stuff", :funny => "business" }.assert_valid_keys([ :failure, :funny ]) }.should raise_error(ArgumentError, "Unknown key(s): failore")
|
107
|
+
lambda{ { :failore => "stuff", :funny => "business" }.assert_valid_keys(:failure, :funny) }.should raise_error(ArgumentError, "Unknown key(s): failore")
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.dirname(__FILE__)+'/../spec_helper'
|
2
|
+
require 'gorillib/hash/reverse_merge'
|
3
|
+
|
4
|
+
describe Hash do
|
5
|
+
describe 'reverse_merge' do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@defaults = { :a => "x", :b => "y", :c => 10 }.freeze
|
9
|
+
@options = { :a => 1, :b => 2 }
|
10
|
+
@expected = { :a => 1, :b => 2, :c => 10 }
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'Should merge defaults into options, creating a new hash' do
|
14
|
+
@options.reverse_merge(@defaults).should == @expected
|
15
|
+
@options.should_not == @expected
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
it 'Should merge! defaults into options, replacing options.' do
|
20
|
+
@merged = @options.dup
|
21
|
+
@merged.reverse_merge!(@defaults).should == @expected
|
22
|
+
@merged.should == @expected
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require File.dirname(__FILE__)+'/../spec_helper'
|
2
|
+
require 'gorillib/hash/slice'
|
3
|
+
|
4
|
+
describe Hash do
|
5
|
+
describe '#slice' do
|
6
|
+
it 'should return a new hash with only the given keys' do
|
7
|
+
original = { :a => 'x', :b => 'y', :c => 10 }
|
8
|
+
expected = { :a => 'x', :b => 'y' }
|
9
|
+
|
10
|
+
original.slice(:a, :b).should == expected
|
11
|
+
original.should_not == expected
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'Should replace the hash with only the given keys' do
|
15
|
+
original = { :a => 'x', :b => 'y', :c => 10 }
|
16
|
+
expected = { :c => 10 }
|
17
|
+
|
18
|
+
original.slice!(:a, :b).should == expected
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should return a new hash with only the given keys when given an array key' do
|
22
|
+
original = { :a => 'x', :b => 'y', :c => 10, [:a, :b] => "an array key" }
|
23
|
+
expected = { [:a, :b] => "an array key", :c => 10 }
|
24
|
+
|
25
|
+
original.slice([:a, :b], :c).should == expected
|
26
|
+
original.should_not == expected
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should replace the hash with only the given keys when given an array key' do
|
30
|
+
original = { :a => 'x', :b => 'y', :c => 10, [:a, :b] => "an array key" }
|
31
|
+
expected = { :a => 'x', :b => 'y' }
|
32
|
+
|
33
|
+
original.slice!([:a, :b], :c).should == expected
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'Should grab each of the splatted keys' do
|
37
|
+
original = { :a => 'x', :b => 'y', :c => 10, [:a, :b] => "an array key" }
|
38
|
+
expected = { :a => 'x', :b => "y" }
|
39
|
+
|
40
|
+
original.slice(*[:a, :b]).should == expected
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require File.dirname(__FILE__)+'/../spec_helper'
|
2
|
+
require 'gorillib/hash/zip'
|
3
|
+
|
4
|
+
describe Hash do
|
5
|
+
describe '#zip' do
|
6
|
+
it 'builds a hash from keys and values' do
|
7
|
+
Hash.zip([:a, :b, :c], [1, 2, 3]).should == { :a => 1, :b => 2, :c => 3 }
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'ignores extra values' do
|
11
|
+
Hash.zip([:a, :b, :c], [1, 2, 3, 4, 5]).should == { :a => 1, :b => 2, :c => 3 }
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'supplies nil values for extra keys' do
|
15
|
+
Hash.zip([:a, :b, :c, :d], [1, 2, 3]).should == { :a => 1, :b => 2, :c => 3, :d => nil }
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'uses the default block if given' do
|
19
|
+
hsh = Hash.zip([:a, :b, :c], [1, 2, 3]){|h,k| h[k] = :foo }
|
20
|
+
hsh.should == { :a => 1, :b => 2, :c => 3 }
|
21
|
+
hsh[:d].should == :foo
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'uses the default value if given' do
|
25
|
+
hsh = Hash.zip([:a, :b, :c], [1, 2, 3], :bar)
|
26
|
+
hsh.should == { :a => 1, :b => 2, :c => 3 }
|
27
|
+
hsh[:d].should == :bar
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require File.dirname(__FILE__)+'/../spec_helper'
|
2
|
+
CODE_FILE = File.dirname(__FILE__)+'/../../lib/gorillib/logger/log.rb'
|
3
|
+
require CODE_FILE
|
4
|
+
|
5
|
+
describe 'Logger' do
|
6
|
+
describe '#dump' do
|
7
|
+
it 'inspects each arg and sends tab-separated to Log.debug' do
|
8
|
+
Log.should_receive(:debug).with(%Q{{:hi=>"there"}\t3\t"bye"})
|
9
|
+
Log.dump({ :hi => "there" }, 3, "bye")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'does not create a log if one exists' do
|
14
|
+
dummy = 'dummy'
|
15
|
+
Object.instance_eval{ remove_const(:Log) rescue nil ; ::Log = dummy }
|
16
|
+
load(CODE_FILE)
|
17
|
+
::Log.should equal(dummy)
|
18
|
+
Object.instance_eval{ remove_const(:Log) rescue nil }
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'creates a new log to STDERR' do
|
22
|
+
@old_stderr = $stderr
|
23
|
+
$stderr = StringIO.new
|
24
|
+
Object.instance_eval{ remove_const(:Log) rescue nil }
|
25
|
+
load(CODE_FILE)
|
26
|
+
Log.info 'hi mom'
|
27
|
+
$stderr.string.should =~ /hi mom/
|
28
|
+
$stderr = @old_stderr
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
require File.dirname(__FILE__)+'/../spec_helper'
|
2
|
+
require 'gorillib/metaprogramming/aliasing'
|
3
|
+
|
4
|
+
module BarMethodAliaser
|
5
|
+
def self.included(foo_class)
|
6
|
+
foo_class.class_eval do
|
7
|
+
include BarMethods
|
8
|
+
alias_method_chain :bar, :baz
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module BarMethods
|
14
|
+
def bar_with_baz
|
15
|
+
bar_without_baz << '_with_baz'
|
16
|
+
end
|
17
|
+
|
18
|
+
def quux_with_baz!
|
19
|
+
quux_without_baz! << '_with_baz'
|
20
|
+
end
|
21
|
+
|
22
|
+
def quux_with_baz?
|
23
|
+
false
|
24
|
+
end
|
25
|
+
|
26
|
+
def quux_with_baz=(v)
|
27
|
+
send(:quux_without_baz=, v) << '_with_baz'
|
28
|
+
end
|
29
|
+
|
30
|
+
def duck_with_orange
|
31
|
+
duck_without_orange << '_with_orange'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'metaprogramming' do
|
36
|
+
before do
|
37
|
+
Object.const_set :FooClassWithBarMethod, Class.new{ def bar() 'bar' end }
|
38
|
+
@instance = FooClassWithBarMethod.new
|
39
|
+
end
|
40
|
+
|
41
|
+
after do
|
42
|
+
Object.instance_eval { remove_const :FooClassWithBarMethod }
|
43
|
+
end
|
44
|
+
|
45
|
+
describe 'alias_method_chain' do
|
46
|
+
it 'creates a with_ and without_ method that chain' do
|
47
|
+
@instance.should respond_to(:bar)
|
48
|
+
feature_aliases = [:bar_with_baz, :bar_without_baz]
|
49
|
+
|
50
|
+
feature_aliases.each do |method|
|
51
|
+
@instance.should_not respond_to(method)
|
52
|
+
end
|
53
|
+
@instance.bar.should == 'bar'
|
54
|
+
|
55
|
+
FooClassWithBarMethod.class_eval{ include BarMethodAliaser }
|
56
|
+
feature_aliases.each do |method|
|
57
|
+
@instance.should respond_to(method)
|
58
|
+
end
|
59
|
+
@instance.bar.should == 'bar_with_baz'
|
60
|
+
@instance.bar_without_baz.should == 'bar'
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'with bang' do
|
64
|
+
FooClassWithBarMethod.class_eval do
|
65
|
+
def quux!; 'quux' end
|
66
|
+
end
|
67
|
+
|
68
|
+
@instance.should_not respond_to(:quux_with_baz!)
|
69
|
+
FooClassWithBarMethod.class_eval do
|
70
|
+
include BarMethodAliaser
|
71
|
+
alias_method_chain :quux!, :baz
|
72
|
+
end
|
73
|
+
@instance.should respond_to(:quux_with_baz!)
|
74
|
+
|
75
|
+
@instance.quux!.should == 'quux_with_baz'
|
76
|
+
@instance.quux_without_baz!.should == 'quux'
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'with same names between predicates and bang methods' do
|
80
|
+
FooClassWithBarMethod.class_eval do
|
81
|
+
def quux!; 'quux!' end
|
82
|
+
def quux?; true end
|
83
|
+
def quux=(v); 'quux=' end
|
84
|
+
end
|
85
|
+
|
86
|
+
@instance.should_not respond_to(:quux_with_baz!)
|
87
|
+
@instance.should_not respond_to(:quux_with_baz?)
|
88
|
+
@instance.should_not respond_to(:quux_with_baz=)
|
89
|
+
|
90
|
+
FooClassWithBarMethod.class_eval { include BarMethodAliaser }
|
91
|
+
@instance.should respond_to(:quux_with_baz!)
|
92
|
+
@instance.should respond_to(:quux_with_baz?)
|
93
|
+
@instance.should respond_to(:quux_with_baz=)
|
94
|
+
|
95
|
+
FooClassWithBarMethod.alias_method_chain :quux!, :baz
|
96
|
+
@instance.quux!.should == 'quux!_with_baz'
|
97
|
+
@instance.quux_without_baz!.should == 'quux!'
|
98
|
+
|
99
|
+
FooClassWithBarMethod.alias_method_chain :quux?, :baz
|
100
|
+
@instance.quux?.should == false
|
101
|
+
@instance.quux_without_baz?.should == true
|
102
|
+
|
103
|
+
FooClassWithBarMethod.alias_method_chain :quux=, :baz
|
104
|
+
@instance.send(:quux=, 1234).should == 'quux=_with_baz'
|
105
|
+
@instance.send(:quux_without_baz=, 1234).should == 'quux='
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'with_feature_punctuation' do
|
109
|
+
FooClassWithBarMethod.class_eval do
|
110
|
+
def quux; 'quux' end
|
111
|
+
def quux?; 'quux?' end
|
112
|
+
include BarMethodAliaser
|
113
|
+
alias_method_chain :quux, :baz!
|
114
|
+
end
|
115
|
+
|
116
|
+
@instance.quux_with_baz!.should == 'quux_with_baz'
|
117
|
+
|
118
|
+
lambda{ FooClassWithBarMethod.alias_method_chain :quux?, :baz! }.should raise_error(NameError)
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'yields target and punctuation' do
|
122
|
+
args = nil
|
123
|
+
FooClassWithBarMethod.class_eval do
|
124
|
+
def quux?; end
|
125
|
+
include BarMethods
|
126
|
+
|
127
|
+
FooClassWithBarMethod.alias_method_chain :quux?, :baz do |target, punctuation|
|
128
|
+
args = [target, punctuation]
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
args.should_not be_nil
|
133
|
+
args[0].should == 'quux'
|
134
|
+
args[1].should == '?'
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'preserves private method status' do
|
138
|
+
FooClassWithBarMethod.class_eval do
|
139
|
+
def duck; 'duck' end
|
140
|
+
include BarMethodAliaser
|
141
|
+
private :duck
|
142
|
+
alias_method_chain :duck, :orange
|
143
|
+
end
|
144
|
+
|
145
|
+
lambda{ @instance.duck }.should raise_error(NoMethodError)
|
146
|
+
|
147
|
+
@instance.instance_eval{ duck }.should == 'duck_with_orange'
|
148
|
+
FooClassWithBarMethod.should be_private_method_defined(:duck)
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'preserves protected method status' do
|
152
|
+
FooClassWithBarMethod.class_eval do
|
153
|
+
def duck; 'duck' end
|
154
|
+
include BarMethodAliaser
|
155
|
+
protected :duck
|
156
|
+
alias_method_chain :duck, :orange
|
157
|
+
end
|
158
|
+
|
159
|
+
lambda{ @instance.duck }.should raise_error(NoMethodError)
|
160
|
+
|
161
|
+
@instance.instance_eval{ duck }.should == 'duck_with_orange'
|
162
|
+
FooClassWithBarMethod.should be_protected_method_defined(:duck)
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'preserves public method status' do
|
166
|
+
FooClassWithBarMethod.class_eval do
|
167
|
+
def duck; 'duck' end
|
168
|
+
include BarMethodAliaser
|
169
|
+
public :duck
|
170
|
+
alias_method_chain :duck, :orange
|
171
|
+
end
|
172
|
+
|
173
|
+
@instance.duck.should == 'duck_with_orange'
|
174
|
+
FooClassWithBarMethod.should be_public_method_defined(:duck)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.dirname(__FILE__)+'/../spec_helper'
|
2
|
+
require 'gorillib/metaprogramming/cattr_accessor'
|
3
|
+
|
4
|
+
describe 'metaprogramming' do
|
5
|
+
describe 'cattr_accessor' do
|
6
|
+
before do
|
7
|
+
@class = Class.new do
|
8
|
+
cattr_accessor :foo
|
9
|
+
cattr_accessor :bar, :instance_writer => false
|
10
|
+
cattr_reader :shaq, :instance_reader => false
|
11
|
+
end
|
12
|
+
@object = @class.new
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'uses mattr default' do
|
16
|
+
@class.foo.should be_nil
|
17
|
+
@object.foo.should be_nil
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'sets mattr value' do
|
21
|
+
@class.foo = :test
|
22
|
+
@object.foo.should == :test
|
23
|
+
|
24
|
+
@object.foo = :test2
|
25
|
+
@class.foo.should == :test2
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'with instance_writer => false, does not create an instance writer' do
|
29
|
+
@class.should respond_to(:foo)
|
30
|
+
@class.should respond_to(:foo=)
|
31
|
+
@object.should respond_to(:bar)
|
32
|
+
@object.should_not respond_to(:bar=)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'with instance_reader => false, does not create an instance reader' do
|
36
|
+
@class.should respond_to(:shaq)
|
37
|
+
@object.should_not respond_to(:shaq)
|
38
|
+
@object.should_not respond_to(:shaq=)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require File.dirname(__FILE__)+'/../spec_helper'
|
2
|
+
require 'gorillib/metaprogramming/class_attribute'
|
3
|
+
|
4
|
+
describe 'metaprogramming' do
|
5
|
+
describe 'class_attribute' do
|
6
|
+
before do
|
7
|
+
@klass = Class.new { class_attribute :setting }
|
8
|
+
@sub = Class.new(@klass)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'defaults to nil' do
|
12
|
+
@klass.setting.should be_nil
|
13
|
+
@sub.setting.should be_nil
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'is inheritable' do
|
17
|
+
@klass.setting = 1
|
18
|
+
@sub.setting == 1
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'is overridable' do
|
22
|
+
@sub.setting = 1
|
23
|
+
@klass.setting.should be_nil
|
24
|
+
|
25
|
+
@klass.setting = 2
|
26
|
+
@sub.setting.should == 1
|
27
|
+
|
28
|
+
Class.new(@sub).setting.should == 1
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'creates a query? method' do
|
32
|
+
@klass.setting?.should == false
|
33
|
+
@klass.setting = 1
|
34
|
+
@klass.setting?.should == true
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'instance reader delegates to class' do
|
38
|
+
@klass.new.setting.should be_nil
|
39
|
+
|
40
|
+
@klass.setting = 1
|
41
|
+
@klass.new.setting.should == 1
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'instance override' do
|
45
|
+
object = @klass.new
|
46
|
+
object.setting = 1
|
47
|
+
@klass.setting.should be_nil
|
48
|
+
@klass.setting = 2
|
49
|
+
object.setting.should == 1
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'instance query' do
|
53
|
+
object = @klass.new
|
54
|
+
object.setting?.should == false
|
55
|
+
object.setting = 1
|
56
|
+
object.setting?.should == true
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'disabling instance writer' do
|
60
|
+
object = Class.new { class_attribute :setting, :instance_writer => false }.new
|
61
|
+
lambda{ object.setting = 'boom' }.should raise_error(NoMethodError)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'works well with singleton classes' do
|
65
|
+
object = @klass.new
|
66
|
+
object.singleton_class.setting = 'foo'
|
67
|
+
object.setting.should == 'foo'
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'setter returns set value' do
|
71
|
+
val = @klass.send(:setting=, 1)
|
72
|
+
val.should == 1
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
require File.dirname(__FILE__)+'/../spec_helper'
|
2
|
+
require 'gorillib/metaprogramming/delegation'
|
3
|
+
|
4
|
+
module One
|
5
|
+
Constant1 = "Hello World"
|
6
|
+
Constant2 = "What\'s up?"
|
7
|
+
end
|
8
|
+
|
9
|
+
class Ab
|
10
|
+
include One
|
11
|
+
Constant1 = "Hello World" # Will have different object id than One::Constant1
|
12
|
+
Constant3 = "Goodbye World"
|
13
|
+
end
|
14
|
+
|
15
|
+
module Xy
|
16
|
+
class Bc
|
17
|
+
include One
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module Yz
|
22
|
+
module Zy
|
23
|
+
class Cd
|
24
|
+
include One
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
Somewhere = Struct.new(:street, :city)
|
30
|
+
|
31
|
+
Someone = Struct.new(:name, :place) do
|
32
|
+
delegate :street, :city, :to_f, :to => :place
|
33
|
+
delegate :upcase, :to => "place.city"
|
34
|
+
end
|
35
|
+
|
36
|
+
Invoice = Struct.new(:client) do
|
37
|
+
delegate :street, :city, :name, :to => :client, :prefix => true
|
38
|
+
delegate :street, :city, :name, :to => :client, :prefix => :customer
|
39
|
+
end
|
40
|
+
|
41
|
+
Project = Struct.new(:description, :person) do
|
42
|
+
delegate :name, :to => :person, :allow_nil => true
|
43
|
+
delegate :to_f, :to => :description, :allow_nil => true
|
44
|
+
end
|
45
|
+
|
46
|
+
Developer = Struct.new(:client) do
|
47
|
+
delegate :name, :to => :client, :prefix => nil
|
48
|
+
end
|
49
|
+
|
50
|
+
Tester = Struct.new(:client) do
|
51
|
+
delegate :name, :to => :client, :prefix => false
|
52
|
+
end
|
53
|
+
|
54
|
+
class Name
|
55
|
+
delegate :upcase, :to => :@full_name
|
56
|
+
|
57
|
+
def initialize(first, last)
|
58
|
+
@full_name = "#{first} #{last}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# ===========================================================================
|
63
|
+
#
|
64
|
+
# Tests start
|
65
|
+
|
66
|
+
describe 'metaprogramming' do
|
67
|
+
describe 'delegation' do
|
68
|
+
before do
|
69
|
+
@david = Someone.new("David", Somewhere.new("Paulina", "Chicago"))
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'delegates to methods' do
|
73
|
+
@david.street.should == "Paulina"
|
74
|
+
@david.city.should == "Chicago"
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'delegates down hierarchy' do
|
78
|
+
@david.upcase.should == "CHICAGO"
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'delegates to instance variables' do
|
82
|
+
david = Name.new("David", "Hansson")
|
83
|
+
david.upcase.should == "DAVID HANSSON"
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'raises with a missing delegation target' do
|
87
|
+
lambda{ Name.send :delegate, :nowhere }.should raise_error(ArgumentError)
|
88
|
+
lambda{ Name.send :delegate, :noplace, :tos => :hollywood }.should raise_error(ArgumentError)
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'uses a prefix' do
|
92
|
+
invoice = Invoice.new(@david)
|
93
|
+
invoice.client_name.should == "David"
|
94
|
+
invoice.client_street.should == "Paulina"
|
95
|
+
invoice.client_city.should == "Chicago"
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'accepts a custom prefix' do
|
99
|
+
invoice = Invoice.new(@david)
|
100
|
+
invoice.customer_name.should == "David"
|
101
|
+
invoice.customer_street.should == "Paulina"
|
102
|
+
invoice.customer_city.should == "Chicago"
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'delegation prefix with nil or false' do
|
106
|
+
Developer.new(@david).name.should == "David"
|
107
|
+
Tester.new(@david).name.should == "David"
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'delegation prefix with instance variable' do
|
111
|
+
lambda{
|
112
|
+
Class.new do
|
113
|
+
def initialize(client)
|
114
|
+
@client = client
|
115
|
+
end
|
116
|
+
delegate :name, :address, :to => :@client, :prefix => true
|
117
|
+
end
|
118
|
+
}.should raise_error(ArgumentError)
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'with allow_nil' do
|
122
|
+
rails = Project.new("Rails", Someone.new("David"))
|
123
|
+
rails.name.should == "David"
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'with allow_nil, accepts a nil value' do
|
127
|
+
rails = Project.new("Rails")
|
128
|
+
rails.name.should be_nil
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'with allow_nil, accepts a nil value and prefix' do
|
132
|
+
Project.class_eval do
|
133
|
+
delegate :name, :to => :person, :allow_nil => true, :prefix => true
|
134
|
+
end
|
135
|
+
rails = Project.new("Rails")
|
136
|
+
rails.person_name.should be_nil
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'without allow_nil, raises an error on nil vlaue' do
|
140
|
+
david = Someone.new("David")
|
141
|
+
lambda{ david.street }.should raise_error(RuntimeError)
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'delegates to method that exists on nil' do
|
145
|
+
nil_person = Someone.new(nil)
|
146
|
+
nil_person.to_f.should == 0.0
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'delegates to method that exists on nil when allowing nil' do
|
150
|
+
nil_project = Project.new(nil)
|
151
|
+
nil_project.to_f.should == 0.0
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'does not raise error when removing singleton instance methods' do
|
155
|
+
parent = Class.new do
|
156
|
+
def self.parent_method; end
|
157
|
+
end
|
158
|
+
|
159
|
+
Class.new(parent) do
|
160
|
+
class << self
|
161
|
+
delegate :parent_method, :to => :superclass
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|