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 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
- == Example
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
- here we have reduced a line of code and removed a local variable
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
- if(customer && customer.order && customer.order.id == new_customer_id)
37
- 'success'
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
- Here we have removed one call to order and reduced the code to a one-liner. There is also an equivalent block form
46
- customer.then {order}.then {id == new_customer_id}.then do |o|
47
- 'success'
48
- end.else do
49
- 'fail'
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, these are simply function calls, so it should be fast.
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 12:16:13 -0500
1
+ Sun, 09 Mar 2008 15:08:53 -0500
@@ -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#M000003">else (MethodChain)</a><br />
24
- <a href="classes/MethodChain.html#M000001">self_eval (MethodChain)</a><br />
25
- <a href="classes/MethodChain.html#M000004">tap (MethodChain)</a><br />
26
- <a href="classes/MethodChain.html#M000002">then (MethodChain)</a><br />
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.1.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}"
@@ -1,36 +1,44 @@
1
1
  require File.dirname(__FILE__) + '/../lib/methodchain'
2
2
 
3
- def test_then_else *vals
4
- bool = !!vals.first
5
- same,opp = bool ? [:then,:else] : [:else,:then]
6
-
7
- it "should return self if self evaluates to #{!bool}" do
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 "if self evaluates to #{bool} ##{same} should yield self to a block if one is given, and return that block's value" do
17
- vals.each do |val|
18
- val.send(same) {|v| v.should == val; 'foo'}.should == 'foo'
19
- val.send(same,1) {|v| v.should == val; 'foo'}.should == 'foo'
20
- end
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
- it "should validate arguments if self evaluates to #{bool}" do
24
- vals.each {|val| lambda{val.send(same)}.should raise_error(ArgumentError)}
25
- vals.each {|val| lambda{val.send(same){|a,b|}}.should raise_error(ArgumentError)}
26
- vals.each {|val| lambda{val.send(same){|a,*b|}}.should raise_error(ArgumentError)}
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 Object do
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.1.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
- - spec/not_included.rb
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