methodchain 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +34 -16
- data/doc/created.rid +1 -1
- data/doc/fr_method_index.html +5 -4
- data/pkg/methodchain-0.1.0.gem +0 -0
- data/rakefile +1 -1
- data/spec/methodchain_spec.rb +63 -23
- metadata +2 -3
- data/spec/not_included.rb +0 -11
- data/spec/then_else.rb +0 -11
data/README
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
== Summary
|
2
|
-
methodchain - ruby helpers for method chaining: tap, then, else
|
2
|
+
methodchain - ruby helpers for method chaining: chain, tap, then, else
|
3
3
|
Easy ways to navigate around nil without creating local variables.
|
4
4
|
|
5
5
|
== Author and License
|
6
6
|
Copyright (c) 2008 Greg Weber, http://gregweber.info
|
7
7
|
Licensed under the MIT license
|
8
8
|
|
9
|
-
==
|
9
|
+
== Examples
|
10
10
|
==== tap
|
11
11
|
if you don't already know about this method, look it up on the net. The tap included here allows message sending.
|
12
12
|
|
@@ -17,38 +17,56 @@ NEW WAY
|
|
17
17
|
|
18
18
|
==== #then and #else
|
19
19
|
OLD WAY
|
20
|
+
|
20
21
|
name = person ? person.name : nil
|
21
22
|
|
22
23
|
NEW WaY
|
24
|
+
|
23
25
|
name = person.then {|p| p.name}
|
24
26
|
|
25
27
|
not a huge savings. But sometimes the person variable is actually a function call, and then we must save it in a variable first.
|
26
28
|
|
27
29
|
OLD WAY
|
30
|
+
|
28
31
|
location = Location.find(:first, ...)
|
29
32
|
@phone = location && location.phone
|
30
33
|
|
31
34
|
NEW WaY
|
35
|
+
|
32
36
|
@phone = Location.find(:first, ...).then {phone}
|
33
|
-
|
37
|
+
|
38
|
+
here we have reduced a line of code and removed a local variable
|
39
|
+
#then and #else can return a default value instead of evaluating a block
|
40
|
+
'a'.then('b') #=> 'b'
|
41
|
+
nil.then('b').else('c') #=> 'c'
|
34
42
|
|
43
|
+
=== #chain
|
35
44
|
OLD WAY
|
36
|
-
|
37
|
-
|
38
|
-
else
|
39
|
-
'fail'
|
40
|
-
end
|
45
|
+
|
46
|
+
customer && customer.order && customer.order.id
|
41
47
|
|
42
48
|
NEW WaY
|
43
|
-
customer.then {order}.then {id == new_customer_id}.then('success').else('fail')
|
44
49
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
+
customer.chain(:order, :id)
|
51
|
+
|
52
|
+
note that this is equivalent to
|
53
|
+
|
54
|
+
customer.then {order}.then {id}
|
55
|
+
|
56
|
+
=== chain - Custom guards and multiple argumentes
|
57
|
+
OLD WAY - guarding against zero
|
58
|
+
|
59
|
+
result = if value == 0 then value else
|
60
|
+
tmp = calc(value)
|
61
|
+
|
62
|
+
if tmp == 0 then tmp else
|
63
|
+
more_calc(tmp, 20)
|
64
|
+
end
|
50
65
|
end
|
51
66
|
|
67
|
+
NEW WAY
|
68
|
+
value.chain(:calc, [:more_calc, 20]) {|s| s == 0 }
|
69
|
+
|
52
70
|
== Usage
|
53
71
|
require 'rubygems'
|
54
72
|
|
@@ -64,8 +82,8 @@ not_included will load the MethodChain module without including it anywhere.
|
|
64
82
|
Already have your own version of tap? use the module-import gem to decide what to include
|
65
83
|
|
66
84
|
== Implementation
|
67
|
-
* There are no proxy objects
|
68
|
-
* A helper method called self_eval is also exposed. This method allows the two different block forms {|p| p.name} and {name}, where the second form is called using instance_eval.
|
85
|
+
* There are no proxy objects and no use of method_missing- these are simply function calls, so it should be fast.
|
86
|
+
* A helper method called self_eval is also exposed. This method allows the two different block forms {|p| p.name} and {name}, where the first form yields self and the second form is called using instance_eval.
|
69
87
|
|
70
88
|
== Install
|
71
89
|
gem install methodchain
|
data/doc/created.rid
CHANGED
@@ -1 +1 @@
|
|
1
|
-
Sun, 09 Mar 2008
|
1
|
+
Sun, 09 Mar 2008 15:08:53 -0500
|
data/doc/fr_method_index.html
CHANGED
@@ -20,10 +20,11 @@
|
|
20
20
|
<div id="index">
|
21
21
|
<h1 class="section-bar">Methods</h1>
|
22
22
|
<div id="index-entries">
|
23
|
-
<a href="classes/MethodChain.html#
|
24
|
-
<a href="classes/MethodChain.html#
|
25
|
-
<a href="classes/MethodChain.html#
|
26
|
-
<a href="classes/MethodChain.html#
|
23
|
+
<a href="classes/MethodChain.html#M000001">chain (MethodChain)</a><br />
|
24
|
+
<a href="classes/MethodChain.html#M000004">else (MethodChain)</a><br />
|
25
|
+
<a href="classes/MethodChain.html#M000002">self_eval (MethodChain)</a><br />
|
26
|
+
<a href="classes/MethodChain.html#M000005">tap (MethodChain)</a><br />
|
27
|
+
<a href="classes/MethodChain.html#M000003">then (MethodChain)</a><br />
|
27
28
|
</div>
|
28
29
|
</div>
|
29
30
|
</body>
|
Binary file
|
data/rakefile
CHANGED
@@ -42,7 +42,7 @@ require 'rake/gempackagetask'
|
|
42
42
|
spec = Gem::Specification.new do |s|
|
43
43
|
s.name = project
|
44
44
|
s.rubyforge_project = project
|
45
|
-
s.version = "0.
|
45
|
+
s.version = "0.2.0"
|
46
46
|
s.author = "Greg Weber"
|
47
47
|
s.email = "greg@gregweber.info"
|
48
48
|
s.homepage = "http://projects.gregweber.info/#{project}"
|
data/spec/methodchain_spec.rb
CHANGED
@@ -1,36 +1,44 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../lib/methodchain'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
vals.each do |val|
|
9
|
-
val.send(opp).should == val
|
10
|
-
val.send(opp,'aye').should == val
|
11
|
-
val.send(opp,'aye') {|a,b,c| a}.should == val
|
12
|
-
val.send(opp) {|a,b,c| a}.should == val
|
3
|
+
describe "#chain" do
|
4
|
+
it "should return self when no arguments are given" do
|
5
|
+
[nil,'a'].each do |var|
|
6
|
+
var.chain.should == var
|
7
|
+
var.chain {fail}.should == var
|
13
8
|
end
|
14
9
|
end
|
10
|
+
it "should send symbols" do
|
11
|
+
[[]].chain(:flatten).should == []
|
12
|
+
end
|
13
|
+
it "should send procs" do
|
14
|
+
[[]].chain(:flatten, lambda{|arr| arr.push('a')}).should == ['a']
|
15
|
+
[[]].chain(:flatten, lambda{ push('a') }).should == ['a']
|
16
|
+
end
|
17
|
+
it "should send an array as a message with arguments" do
|
18
|
+
[['a']].chain(:flatten, lambda{|arr| arr.push('b')}, [:join, ' ']).should == 'a b'
|
19
|
+
end
|
15
20
|
|
16
|
-
it "
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
+
it "should guard the chain against nil and false" do
|
22
|
+
nil.chain(:foo,:bar,:baz).should == nil
|
23
|
+
false.chain(:foo,:bar,:baz).should == false
|
24
|
+
[].chain(:flatten!,:not_defined).should == nil
|
25
|
+
[].chain(:flatten!, lambda{|arr| arr.push('a')}).should == nil
|
26
|
+
lambda{"foo".chain(:to_s,:not_defined)}.should raise_error(NoMethodError)
|
21
27
|
end
|
28
|
+
it "should allow custom guards with blocks" do
|
29
|
+
nil.chain {nil?}.should == nil
|
30
|
+
'a'.chain {nil?}.should == 'a'
|
31
|
+
nil.chain(:to_s) {nil?}.should == ''
|
32
|
+
'a'.chain(lambda{fail}) {nil?}.should == 'a'
|
22
33
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
34
|
+
nil.chain {is_a?(String)}.should == nil
|
35
|
+
'a'.chain {is_a?(String)}.should == 'a'
|
36
|
+
nil.chain(lambda{fail}) {is_a?(String)}.should == nil
|
37
|
+
'a'.chain(:upcase) {is_a?(String)}.should == 'A'
|
27
38
|
end
|
28
39
|
end
|
29
40
|
|
30
|
-
describe
|
31
|
-
test_then_else('a',true)
|
32
|
-
test_then_else(nil,false)
|
33
|
-
|
41
|
+
describe "#tap" do
|
34
42
|
it "#tap should yield self to a block and return self if block has one argument" do
|
35
43
|
[true,false,'a'].each do |o|
|
36
44
|
o.tap {|s| s.should == o }.should == o
|
@@ -58,3 +66,35 @@ describe Object do
|
|
58
66
|
[1, 2, 3, 4, 5].tap.should == [1, 2, 3, 4, 5]
|
59
67
|
end
|
60
68
|
end
|
69
|
+
|
70
|
+
def test_then_else *vals
|
71
|
+
bool = !!vals.first
|
72
|
+
same,opp = bool ? [:then,:else] : [:else,:then]
|
73
|
+
|
74
|
+
it "should return self if self evaluates to #{!bool}" do
|
75
|
+
vals.each do |val|
|
76
|
+
val.send(opp).should == val
|
77
|
+
val.send(opp,'aye').should == val
|
78
|
+
val.send(opp,'aye') {|a,b,c| a}.should == val
|
79
|
+
val.send(opp) {|a,b,c| a}.should == val
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
it "if self evaluates to #{bool} ##{same} should yield self to a block if one is given, and return that block's value" do
|
84
|
+
vals.each do |val|
|
85
|
+
val.send(same) {|v| v.should == val; 'foo'}.should == 'foo'
|
86
|
+
val.send(same,1) {|v| v.should == val; 'foo'}.should == 'foo'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should validate arguments if self evaluates to #{bool}" do
|
91
|
+
vals.each {|val| lambda{val.send(same)}.should raise_error(ArgumentError)}
|
92
|
+
vals.each {|val| lambda{val.send(same){|a,b|}}.should raise_error(ArgumentError)}
|
93
|
+
vals.each {|val| lambda{val.send(same){|a,*b|}}.should raise_error(ArgumentError)}
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe "#then,#else" do
|
98
|
+
test_then_else('a',true)
|
99
|
+
test_then_else(nil,false)
|
100
|
+
end
|
metadata
CHANGED
@@ -3,7 +3,7 @@ rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: methodchain
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
6
|
+
version: 0.2.0
|
7
7
|
date: 2008-03-09 00:00:00 -06:00
|
8
8
|
summary: convenience methods for method chaining
|
9
9
|
require_paths:
|
@@ -48,8 +48,7 @@ files:
|
|
48
48
|
- pkg/methodchain-0.0.1.gem
|
49
49
|
- pkg/methodchain-0.0.3.gem
|
50
50
|
- pkg/methodchain-0.0.5.gem
|
51
|
-
-
|
52
|
-
- spec/then_else.rb
|
51
|
+
- pkg/methodchain-0.1.0.gem
|
53
52
|
- spec/methodchain_spec.rb
|
54
53
|
- README
|
55
54
|
test_files: []
|
data/spec/not_included.rb
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
# test optional imports
|
2
|
-
|
3
|
-
describe "requiring not_included" do
|
4
|
-
it "should not import methods into Object" do
|
5
|
-
require File.dirname(__FILE__) + '/../lib/methodchain/not_included'
|
6
|
-
Object.new.should_not respond_to(:tap)
|
7
|
-
Object.new.should_not respond_to(:then)
|
8
|
-
Object.new.should_not respond_to(:else)
|
9
|
-
MethodChain.should be_kind_of(Module)
|
10
|
-
end
|
11
|
-
end
|
data/spec/then_else.rb
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
# test optional imports
|
2
|
-
|
3
|
-
describe "requiring not_tap" do
|
4
|
-
it "should not import tap into Object" do
|
5
|
-
require File.dirname(__FILE__) + '/../lib/methodchain/then_else'
|
6
|
-
MethodChain.should be_kind_of(Module)
|
7
|
-
Object.new.should_not respond_to(:tap)
|
8
|
-
Object.new.should respond_to(:then)
|
9
|
-
Object.new.should respond_to(:else)
|
10
|
-
end
|
11
|
-
end
|