methodchain 0.3.1 → 0.4.0
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/README +32 -4
- data/Rakefile +2 -2
- data/doc/created.rid +1 -1
- data/lib/methodchain/not-included.rb +48 -13
- data/spec/methodchain_spec.rb +57 -8
- metadata +2 -2
data/README
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
== Summary
|
2
|
-
methodchain - ruby helpers for method chaining: chain, tap, then, else
|
2
|
+
methodchain - ruby helpers for method chaining: chain, tap, then, else, and, or
|
3
3
|
Easy ways to navigate around nil without creating local variables.
|
4
4
|
|
5
5
|
== Author and License
|
@@ -14,6 +14,8 @@ Licensed under the MIT license
|
|
14
14
|
|
15
15
|
==== new way
|
16
16
|
name = person.then {|p| p.name}
|
17
|
+
# or
|
18
|
+
name = person.then {name}
|
17
19
|
|
18
20
|
not a huge savings. But sometimes the person variable is actually a function call, and then we must save it in a variable first.
|
19
21
|
|
@@ -29,10 +31,36 @@ not a huge savings. But sometimes the person variable is actually a function cal
|
|
29
31
|
@phone = find(:first).then {phone} # => nil
|
30
32
|
|
31
33
|
We have reduced a line of code and removed a local variable.
|
32
|
-
|
34
|
+
##else is the opposite of #then, and the two methods can be used together
|
35
|
+
|
36
|
+
'a'.then{'b'} #=> 'b'
|
37
|
+
nil.then{'b'}.else{'c'} #=> 'c'
|
38
|
+
|
39
|
+
==== message sending
|
40
|
+
The normal conditional for ##then and ##else is self
|
41
|
+
|
42
|
+
if self # inside MethodChain#then
|
43
|
+
# evaluate block
|
44
|
+
end
|
45
|
+
|
46
|
+
##then and ##else allow message sending as the conditional. See more examples of message sending with the MethodChain#chain examples below
|
47
|
+
|
48
|
+
"not empty".then(:empty?) {"N/A"} # => "not empty"
|
49
|
+
"".then(:empty?) {"N/A"} # => "N/A"
|
50
|
+
|
51
|
+
=== ##and, ##or
|
52
|
+
==== old way
|
53
|
+
Return a default value or the original value depending on whether multiple conditions are met
|
54
|
+
Person = Struct.new(:phone )
|
55
|
+
blank = Person.new('') # or {:phone => nil}
|
56
|
+
blank.phone && (not blank.phone.empty?) ? blank.phone : "N/A" # => "N/A"
|
57
|
+
p = Person.new('123')
|
58
|
+
p.phone && (not p.phone.empty?) ? p.phone : "N/A" # => "123"
|
59
|
+
|
60
|
+
==== new way
|
61
|
+
blank.phone.and {not empty?} || "N/A" # => "N/A"
|
62
|
+
p.phone.and {not empty?} || "N/A" # => "123"
|
33
63
|
|
34
|
-
'a'.then('b') #=> 'b'
|
35
|
-
nil.then('b').else('c') #=> 'c'
|
36
64
|
|
37
65
|
=== ##tap
|
38
66
|
if you don't already know about this method, look it up on the net. The tap included here allows message sending.
|
data/Rakefile
CHANGED
@@ -89,7 +89,7 @@ namespace :readme do
|
|
89
89
|
doc.at('#description').search('pre').each do |ex|
|
90
90
|
#select {|elem| elem.inner_html =~ /class |module /}.each do |ex|
|
91
91
|
# add coderay and undo what rdoc has done in the example code
|
92
|
-
ex.swap("<coderay lang='ruby'>#{ex.inner_html.gsub('"', '"').gsub('>','>')}</coderay>")
|
92
|
+
ex.swap("<coderay lang='ruby'>#{ex.inner_html.gsub('"', '"').gsub('>','>').gsub('<', '<')}</coderay>")
|
93
93
|
end
|
94
94
|
puts doc.at('#description').to_html
|
95
95
|
end
|
@@ -134,7 +134,7 @@ require 'rake/gempackagetask'
|
|
134
134
|
spec = Gem::Specification.new do |s|
|
135
135
|
s.name = project
|
136
136
|
s.rubyforge_project = project
|
137
|
-
s.version = "0.
|
137
|
+
s.version = "0.4.0"
|
138
138
|
s.author = "Greg Weber"
|
139
139
|
s.email = "greg@gregweber.info"
|
140
140
|
s.homepage = "http://projects.gregweber.info/#{project}"
|
data/doc/created.rid
CHANGED
@@ -1 +1 @@
|
|
1
|
-
Mon,
|
1
|
+
Mon, 24 Mar 2008 13:06:03 -0500
|
@@ -48,24 +48,59 @@ public
|
|
48
48
|
(send_as_function (messages.shift)).chain(*messages, &guard)
|
49
49
|
end
|
50
50
|
|
51
|
-
# return self if self evaluates to false,
|
52
|
-
#
|
53
|
-
def then
|
54
|
-
if
|
55
|
-
|
56
|
-
ArgumentError, "#then must be called with an argument or a block"))
|
51
|
+
# return self if self or a guard evaluates to false,
|
52
|
+
# otherwise return the evaluation of the block
|
53
|
+
def then *guards, &block
|
54
|
+
if guards.empty?
|
55
|
+
return self if not self
|
57
56
|
else
|
58
|
-
|
57
|
+
guards.each do |cond|
|
58
|
+
return self if not send_as_function(cond)
|
59
|
+
end
|
59
60
|
end
|
61
|
+
|
62
|
+
block_given? ? yield_or_eval(&block) : self
|
63
|
+
end
|
64
|
+
|
65
|
+
# return self if self or a guard evaluates to true
|
66
|
+
# otherwise return the evaluation of the block
|
67
|
+
def else *guards, &block
|
68
|
+
if guards.empty?
|
69
|
+
return self if self
|
70
|
+
else
|
71
|
+
guards.each do |cond|
|
72
|
+
return self if send_as_function(cond)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
block_given? ? yield_or_eval(&block) : self
|
60
77
|
end
|
61
78
|
|
62
|
-
#
|
63
|
-
|
64
|
-
|
65
|
-
|
79
|
+
# with no guards, is equivalent to self && yield_or_eval(&block) && self
|
80
|
+
# same as: <tt>self.then(*guards, &block) && self</tt>
|
81
|
+
def and *guards, &block
|
82
|
+
if guards.empty?
|
83
|
+
return self if not self
|
66
84
|
else
|
67
|
-
|
68
|
-
|
85
|
+
guards.each do |cond|
|
86
|
+
return self if not send_as_function(cond)
|
87
|
+
end
|
69
88
|
end
|
89
|
+
|
90
|
+
block_given? ? (yield_or_eval(&block) && self) : self
|
91
|
+
end
|
92
|
+
|
93
|
+
# with no guards, is equivalent to <tt>self || (yield_or_eval(&block) && self)</tt>
|
94
|
+
# same as: <tt>self.else(*guards, &block) && self</tt>
|
95
|
+
def or *guards, &block
|
96
|
+
if guards.empty?
|
97
|
+
return self if self
|
98
|
+
else
|
99
|
+
guards.each do |cond|
|
100
|
+
return self if send_as_function(cond)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
block_given? ? yield_or_eval(&block) : self
|
70
105
|
end
|
71
106
|
end
|
data/spec/methodchain_spec.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../lib/methodchain'
|
2
2
|
|
3
|
+
#TODO
|
4
|
+
# test message sending with #and and #or
|
5
|
+
|
3
6
|
describe "#chain" do
|
4
7
|
it "should return self when no arguments or just a block are given" do
|
5
8
|
[nil,'a'].each do |var|
|
@@ -88,30 +91,76 @@ describe "#tap" do
|
|
88
91
|
end
|
89
92
|
end
|
90
93
|
|
94
|
+
describe "Object#and" do
|
95
|
+
it "should return self or a value that evaluates to false" do
|
96
|
+
[true,'testing'].each do |val|
|
97
|
+
val.and {false}.should == false
|
98
|
+
val.and {'a'}.should == val
|
99
|
+
end
|
100
|
+
[false,nil].each do |val|
|
101
|
+
val.and {false}.should == val
|
102
|
+
val.and {nil}.should == val
|
103
|
+
val.and {true}.should == val
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "Object#or" do
|
109
|
+
it "should return self or a value that evaluates to false" do
|
110
|
+
[true,'testing'].each do |val|
|
111
|
+
val.or {false}.should == val
|
112
|
+
val.or {'a'}.should == val
|
113
|
+
end
|
114
|
+
[false,nil].each do |val|
|
115
|
+
val.or {false}.should == false
|
116
|
+
val.or {nil}.should == nil
|
117
|
+
val.or {true}.should == true
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
91
121
|
def test_then_else *vals
|
92
122
|
bool = !!vals.first
|
93
123
|
same,opp = bool ? [:then,:else] : [:else,:then]
|
94
124
|
|
95
|
-
it "should return self if self evaluates to #{!bool}" do
|
125
|
+
it "should return self if no conditions are given and self evaluates to #{!bool}" do
|
96
126
|
vals.each do |val|
|
97
127
|
val.send(opp).should == val
|
98
|
-
val.send(opp,'aye').should == val
|
99
|
-
val.send(opp,'aye') {|a,b,c| a}.should == val
|
100
128
|
val.send(opp) {|a,b,c| a}.should == val
|
101
129
|
end
|
102
130
|
end
|
103
131
|
|
132
|
+
it "should return self if no block is given" do
|
133
|
+
vals.each do |val|
|
134
|
+
val.send(same, proc{self}).should == val
|
135
|
+
val.send(same, proc{not self}).should == val
|
136
|
+
val.send(opp, proc{self}).should == val
|
137
|
+
val.send(opp, proc{not self}).should == val
|
138
|
+
|
139
|
+
lambda{val.send(same, proc{fail})}.should raise_error
|
140
|
+
lambda{val.send(opp, proc{fail})}.should raise_error
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
104
144
|
it "if self evaluates to #{bool} ##{same} should yield self to a block if one is given, and return that block's value" do
|
105
145
|
vals.each do |val|
|
106
146
|
val.send(same) {|v| v.should == val; 'foo'}.should == 'foo'
|
107
|
-
val.send(same,1) {|v| v.should == val; 'foo'}.should == 'foo'
|
108
147
|
end
|
109
148
|
end
|
110
149
|
|
111
|
-
it "
|
112
|
-
vals.each
|
113
|
-
|
114
|
-
|
150
|
+
it "if self evaluates to #{!bool} ##{opp} should yield self to a block if one is given, and return that block's value" do
|
151
|
+
vals.each do |val|
|
152
|
+
val.send(opp) {|v| v.should == val; 'foo'}.should == val
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should test conditions" do
|
157
|
+
vals.each do |val|
|
158
|
+
val.send(same, proc{self}) {"test"}.should == "test"
|
159
|
+
val.send(same, proc{not self}) {fail}.should == val
|
160
|
+
|
161
|
+
val.send(opp, proc{self}) {fail}.should == val
|
162
|
+
val.send(opp, proc{not self}) {"test"}.should == "test"
|
163
|
+
end
|
115
164
|
end
|
116
165
|
end
|
117
166
|
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: methodchain
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2008-03-
|
6
|
+
version: 0.4.0
|
7
|
+
date: 2008-03-24 00:00:00 -05:00
|
8
8
|
summary: convenience methods for method chaining
|
9
9
|
require_paths:
|
10
10
|
- lib
|