methodchain 0.0.5

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 ADDED
@@ -0,0 +1,85 @@
1
+ == Summary
2
+ methodchain - ruby helpers for method chaining: tap, then, else
3
+ Easy ways to navigate around nil without creating local variables.
4
+
5
+ == Author and License
6
+ Copyright (c) 2008 Greg Weber, http://gregweber.info
7
+ Licensed under the MIT license
8
+
9
+ == Example
10
+ = tap
11
+ if you don't already know about this method, look it up on the net. The tap included here allows message sending.
12
+
13
+ OLD WAY (still valid with this tap)
14
+ [1].tap {|arr| arr.compact!}.first # => 1
15
+ NEW WAY
16
+ [1].tap(:compact!).first # => 1
17
+
18
+ = #then and #else
19
+ OLD WAY
20
+ name = person ? person.name : nil
21
+
22
+ NEW WaY
23
+ name = person.then {|p| p.name}
24
+
25
+ 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
+
27
+ OLD WAY
28
+ location = Location.find(:first, ...)
29
+ @phone = location && location.phone
30
+
31
+ NEW WaY
32
+ @phone = Location.find(:first, ...).then {phone}
33
+ here we have reduced a line of code and removed a local variable
34
+
35
+ OLD WAY
36
+ if(customer && customer.order && customer.order.id == new_customer_id)
37
+ 'success'
38
+ else
39
+ 'fail'
40
+ end
41
+
42
+ NEW WaY
43
+ customer.then {order}.then {id == new_customer_id}.then('success').else('fail')
44
+
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
+ end
51
+
52
+ == Usage
53
+ require 'rubygems'
54
+
55
+ === import all MethodChain methods into Object
56
+
57
+ require 'methodchain'
58
+
59
+ === selectively import MethodChain methods
60
+
61
+ then_else will load just the then and else methods and not the tap method
62
+
63
+ require 'methodchain/then_else'
64
+
65
+ not_included will load the MethodChain module without including it anywhere.
66
+
67
+ require 'methodchain/not_included'
68
+
69
+ == Implementation
70
+ 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.
71
+
72
+ == Install
73
+ gem install methodchain
74
+
75
+ == Source
76
+ === browser
77
+ http://github.com/gregwebs/methodchain/tree/master
78
+ === repository
79
+ git clone git://github.com/gregwebs/methodchain.git
80
+
81
+ == Homepage
82
+ http://gregweber.info/projects/methodchain.html
83
+
84
+ == RDoc documentation
85
+ included with gem
data/doc/created.rid ADDED
@@ -0,0 +1 @@
1
+ Sat, 08 Mar 2008 09:49:50 -0600
@@ -0,0 +1,28 @@
1
+
2
+ <?xml version="1.0" encoding="iso-8859-1"?>
3
+ <!DOCTYPE html
4
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
5
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
6
+
7
+ <!--
8
+
9
+ Classes
10
+
11
+ -->
12
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
13
+ <head>
14
+ <title>Classes</title>
15
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
16
+ <link rel="stylesheet" href="rdoc-style.css" type="text/css" />
17
+ <base target="docwin" />
18
+ </head>
19
+ <body>
20
+ <div id="index">
21
+ <h1 class="section-bar">Classes</h1>
22
+ <div id="index-entries">
23
+ <a href="classes/MethodChain/Tap.html">MethodChain::Tap</a><br />
24
+ <a href="classes/MethodChain/ThenElse.html">MethodChain::ThenElse</a><br />
25
+ </div>
26
+ </div>
27
+ </body>
28
+ </html>
@@ -0,0 +1,32 @@
1
+
2
+ <?xml version="1.0" encoding="iso-8859-1"?>
3
+ <!DOCTYPE html
4
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
5
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
6
+
7
+ <!--
8
+
9
+ Files
10
+
11
+ -->
12
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
13
+ <head>
14
+ <title>Files</title>
15
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
16
+ <link rel="stylesheet" href="rdoc-style.css" type="text/css" />
17
+ <base target="docwin" />
18
+ </head>
19
+ <body>
20
+ <div id="index">
21
+ <h1 class="section-bar">Files</h1>
22
+ <div id="index-entries">
23
+ <a href="files/README.html">README</a><br />
24
+ <a href="files/lib/methodchain_rb.html">lib/methodchain.rb</a><br />
25
+ <a href="files/lib/methodchain/import_rb.html">lib/methodchain/import.rb</a><br />
26
+ <a href="files/lib/methodchain/methodchain_rb.html">lib/methodchain/methodchain.rb</a><br />
27
+ <a href="files/lib/methodchain/not_included_rb.html">lib/methodchain/not_included.rb</a><br />
28
+ <a href="files/lib/methodchain/then_else_rb.html">lib/methodchain/then_else.rb</a><br />
29
+ </div>
30
+ </div>
31
+ </body>
32
+ </html>
@@ -0,0 +1,29 @@
1
+
2
+ <?xml version="1.0" encoding="iso-8859-1"?>
3
+ <!DOCTYPE html
4
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
5
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
6
+
7
+ <!--
8
+
9
+ Methods
10
+
11
+ -->
12
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
13
+ <head>
14
+ <title>Methods</title>
15
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
16
+ <link rel="stylesheet" href="rdoc-style.css" type="text/css" />
17
+ <base target="docwin" />
18
+ </head>
19
+ <body>
20
+ <div id="index">
21
+ <h1 class="section-bar">Methods</h1>
22
+ <div id="index-entries">
23
+ <a href="classes/MethodChain/ThenElse.html#M000002">else (MethodChain::ThenElse)</a><br />
24
+ <a href="classes/MethodChain/Tap.html#M000003">tap (MethodChain::Tap)</a><br />
25
+ <a href="classes/MethodChain/ThenElse.html#M000001">then (MethodChain::ThenElse)</a><br />
26
+ </div>
27
+ </div>
28
+ </body>
29
+ </html>
data/doc/index.html ADDED
@@ -0,0 +1,24 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <!DOCTYPE html
3
+ PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
4
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
5
+
6
+ <!--
7
+
8
+ RDoc Documentation
9
+
10
+ -->
11
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
12
+ <head>
13
+ <title>RDoc Documentation</title>
14
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
15
+ </head>
16
+ <frameset rows="20%, 80%">
17
+ <frameset cols="25%,35%,45%">
18
+ <frame src="fr_file_index.html" title="Files" name="Files" />
19
+ <frame src="fr_class_index.html" name="Classes" />
20
+ <frame src="fr_method_index.html" name="Methods" />
21
+ </frameset>
22
+ <frame src="files/README.html" name="docwin" />
23
+ </frameset>
24
+ </html>
@@ -0,0 +1,208 @@
1
+
2
+ body {
3
+ font-family: Verdana,Arial,Helvetica,sans-serif;
4
+ font-size: 90%;
5
+ margin: 0;
6
+ margin-left: 40px;
7
+ padding: 0;
8
+ background: white;
9
+ }
10
+
11
+ h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; }
12
+ h1 { font-size: 150%; }
13
+ h2,h3,h4 { margin-top: 1em; }
14
+
15
+ a { background: #eef; color: #039; text-decoration: none; }
16
+ a:hover { background: #039; color: #eef; }
17
+
18
+ /* Override the base stylesheet's Anchor inside a table cell */
19
+ td > a {
20
+ background: transparent;
21
+ color: #039;
22
+ text-decoration: none;
23
+ }
24
+
25
+ /* and inside a section title */
26
+ .section-title > a {
27
+ background: transparent;
28
+ color: #eee;
29
+ text-decoration: none;
30
+ }
31
+
32
+ /* === Structural elements =================================== */
33
+
34
+ div#index {
35
+ margin: 0;
36
+ margin-left: -40px;
37
+ padding: 0;
38
+ font-size: 90%;
39
+ }
40
+
41
+
42
+ div#index a {
43
+ margin-left: 0.7em;
44
+ }
45
+
46
+ div#index .section-bar {
47
+ margin-left: 0px;
48
+ padding-left: 0.7em;
49
+ background: #ccc;
50
+ font-size: small;
51
+ }
52
+
53
+
54
+ div#classHeader, div#fileHeader {
55
+ width: auto;
56
+ color: white;
57
+ padding: 0.5em 1.5em 0.5em 1.5em;
58
+ margin: 0;
59
+ margin-left: -40px;
60
+ border-bottom: 3px solid #006;
61
+ }
62
+
63
+ div#classHeader a, div#fileHeader a {
64
+ background: inherit;
65
+ color: white;
66
+ }
67
+
68
+ div#classHeader td, div#fileHeader td {
69
+ background: inherit;
70
+ color: white;
71
+ }
72
+
73
+
74
+ div#fileHeader {
75
+ background: #057;
76
+ }
77
+
78
+ div#classHeader {
79
+ background: #048;
80
+ }
81
+
82
+
83
+ .class-name-in-header {
84
+ font-size: 180%;
85
+ font-weight: bold;
86
+ }
87
+
88
+
89
+ div#bodyContent {
90
+ padding: 0 1.5em 0 1.5em;
91
+ }
92
+
93
+ div#description {
94
+ padding: 0.5em 1.5em;
95
+ background: #efefef;
96
+ border: 1px dotted #999;
97
+ }
98
+
99
+ div#description h1,h2,h3,h4,h5,h6 {
100
+ color: #125;;
101
+ background: transparent;
102
+ }
103
+
104
+ div#validator-badges {
105
+ text-align: center;
106
+ }
107
+ div#validator-badges img { border: 0; }
108
+
109
+ div#copyright {
110
+ color: #333;
111
+ background: #efefef;
112
+ font: 0.75em sans-serif;
113
+ margin-top: 5em;
114
+ margin-bottom: 0;
115
+ padding: 0.5em 2em;
116
+ }
117
+
118
+
119
+ /* === Classes =================================== */
120
+
121
+ table.header-table {
122
+ color: white;
123
+ font-size: small;
124
+ }
125
+
126
+ .type-note {
127
+ font-size: small;
128
+ color: #DEDEDE;
129
+ }
130
+
131
+ .xxsection-bar {
132
+ background: #eee;
133
+ color: #333;
134
+ padding: 3px;
135
+ }
136
+
137
+ .section-bar {
138
+ color: #333;
139
+ border-bottom: 1px solid #999;
140
+ margin-left: -20px;
141
+ }
142
+
143
+
144
+ .section-title {
145
+ background: #79a;
146
+ color: #eee;
147
+ padding: 3px;
148
+ margin-top: 2em;
149
+ margin-left: -30px;
150
+ border: 1px solid #999;
151
+ }
152
+
153
+ .top-aligned-row { vertical-align: top }
154
+ .bottom-aligned-row { vertical-align: bottom }
155
+
156
+ /* --- Context section classes ----------------------- */
157
+
158
+ .context-row { }
159
+ .context-item-name { font-family: monospace; font-weight: bold; color: black; }
160
+ .context-item-value { font-size: small; color: #448; }
161
+ .context-item-desc { color: #333; padding-left: 2em; }
162
+
163
+ /* --- Method classes -------------------------- */
164
+ .method-detail {
165
+ background: #efefef;
166
+ padding: 0;
167
+ margin-top: 0.5em;
168
+ margin-bottom: 1em;
169
+ border: 1px dotted #ccc;
170
+ }
171
+ .method-heading {
172
+ color: black;
173
+ background: #ccc;
174
+ border-bottom: 1px solid #666;
175
+ padding: 0.2em 0.5em 0 0.5em;
176
+ }
177
+ .method-signature { color: black; background: inherit; }
178
+ .method-name { font-weight: bold; }
179
+ .method-args { font-style: italic; }
180
+ .method-description { padding: 0 0.5em 0 0.5em; }
181
+
182
+ /* --- Source code sections -------------------- */
183
+
184
+ a.source-toggle { font-size: 90%; }
185
+ div.method-source-code {
186
+ background: #262626;
187
+ color: #ffdead;
188
+ margin: 1em;
189
+ padding: 0.5em;
190
+ border: 1px dashed #999;
191
+ overflow: hidden;
192
+ }
193
+
194
+ div.method-source-code pre { color: #ffdead; overflow: hidden; }
195
+
196
+ /* --- Ruby keyword styles --------------------- */
197
+
198
+ .standalone-code { background: #221111; color: #ffdead; overflow: hidden; }
199
+
200
+ .ruby-constant { color: #7fffd4; background: transparent; }
201
+ .ruby-keyword { color: #00ffff; background: transparent; }
202
+ .ruby-ivar { color: #eedd82; background: transparent; }
203
+ .ruby-operator { color: #00ffee; background: transparent; }
204
+ .ruby-identifier { color: #ffdead; background: transparent; }
205
+ .ruby-node { color: #ffa07a; background: transparent; }
206
+ .ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
207
+ .ruby-regexp { color: #ffa07a; background: transparent; }
208
+ .ruby-value { color: #7fffd4; background: transparent; }
@@ -0,0 +1,4 @@
1
+ require File.dirname(__FILE__) + '/methodchain/not_included'
2
+
3
+ class Object # :nodoc:
4
+ include MethodChain end
Binary file
Binary file
data/rakefile ADDED
@@ -0,0 +1,42 @@
1
+ desc "test"
2
+ task :test do
3
+ Dir[ 'spec/*' ].each do |file|
4
+ puts `spec #{file}`
5
+ end
6
+ end
7
+
8
+ desc "release a new gem to rubyforge"
9
+ task :release => [:rdoc,:package] do
10
+ Dir.chdir('pkg') do
11
+ release = Dir['*.gem'].sort_by {|file| File.mtime(file)}.last
12
+ release =~ /^[^-]+-([.0-9]+).gem$/
13
+ `rubyforge login && rubyforge add_release methodchain methodchain #$1 #{release}`
14
+ end
15
+ end
16
+
17
+ desc "generate documentation"
18
+ task :rdoc do
19
+ fail unless system 'rdoc --force-update --quiet README lib/*'
20
+ end
21
+
22
+ require 'rubygems'
23
+ require 'rake/gempackagetask'
24
+
25
+ spec = Gem::Specification.new do |s|
26
+ s.name = "methodchain"
27
+ s.rubyforge_project = "methodchain"
28
+ s.version = "0.0.5"
29
+ s.author = "Greg Weber"
30
+ s.email = "greg@gregweber.info"
31
+ s.homepage = "http://projects.gregweber.info/methodchain"
32
+ s.platform = Gem::Platform::RUBY
33
+ s.summary = "convenience methods for method chaining"
34
+ s.files = Dir['./**'] + Dir['*/**']
35
+ s.require_path = "lib"
36
+ s.has_rdoc = true
37
+ s.extra_rdoc_files = ["README"]
38
+ end
39
+
40
+ Rake::GemPackageTask.new(spec) do |pkg|
41
+ pkg.need_tar = false
42
+ end
@@ -0,0 +1,60 @@
1
+ require File.dirname(__FILE__) + '/../lib/methodchain'
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
13
+ end
14
+ end
15
+
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
+ end
22
+
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)}
27
+ end
28
+ end
29
+
30
+ describe Object do
31
+ test_then_else('a',true)
32
+ test_then_else(nil,false)
33
+
34
+ it "#tap should yield self to a block and return self if block has one argument" do
35
+ [true,false,'a'].each do |o|
36
+ o.tap {|s| s.should == o }.should == o
37
+ o.tap {|s| not s }.should == o
38
+ end
39
+ end
40
+ it "#tap should raise an error if a block has more than one argument" do
41
+ [true,false,'a'].each do |o|
42
+ lambda{ o.tap {|s,a|} }.should raise_error(ArgumentError)
43
+ lambda{ o.tap {|s,*args|} }.should raise_error(ArgumentError)
44
+ end
45
+ end
46
+ it "#tap should instance_eval if a block has return self" do
47
+ [true,false,'a'].each do |o|
48
+ o.tap { self.should == o }.should == o
49
+ o.tap {|*args| self.should == o }.should == o
50
+ end
51
+ end
52
+ it "#tap should send a method to itself" do
53
+ [1, 2, 3, 4, 5].tap { |arr| arr.pop }.should == [1, 2, 3, 4]
54
+ [1, 2, 3, 4, 5].tap(:pop).should == [1, 2, 3, 4]
55
+ [1, 2, 3, 4, 5].tap(:pop) {|arr| arr.pop}.should == [1, 2, 3]
56
+ end
57
+ it "#tap should do nothing if tap is called with no method or block" do
58
+ [1, 2, 3, 4, 5].tap.should == [1, 2, 3, 4, 5]
59
+ end
60
+ end
@@ -0,0 +1,11 @@
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 ADDED
@@ -0,0 +1,11 @@
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
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.4
3
+ specification_version: 1
4
+ name: methodchain
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.0.5
7
+ date: 2008-03-08 00:00:00 -06:00
8
+ summary: convenience methods for method chaining
9
+ require_paths:
10
+ - lib
11
+ email: greg@gregweber.info
12
+ homepage: http://projects.gregweber.info/methodchain
13
+ rubyforge_project: methodchain
14
+ description:
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Greg Weber
31
+ files:
32
+ - ./doc
33
+ - ./lib
34
+ - ./pkg
35
+ - ./spec
36
+ - ./README
37
+ - ./rakefile
38
+ - doc/files
39
+ - doc/index.html
40
+ - doc/rdoc-style.css
41
+ - doc/fr_method_index.html
42
+ - doc/fr_class_index.html
43
+ - doc/fr_file_index.html
44
+ - doc/created.rid
45
+ - doc/classes
46
+ - lib/methodchain
47
+ - lib/methodchain.rb
48
+ - pkg/methodchain-0.0.1.gem
49
+ - pkg/methodchain-0.0.3.gem
50
+ - spec/not_included.rb
51
+ - spec/then_else.rb
52
+ - spec/methodchain_spec.rb
53
+ - README
54
+ test_files: []
55
+
56
+ rdoc_options: []
57
+
58
+ extra_rdoc_files:
59
+ - README
60
+ executables: []
61
+
62
+ extensions: []
63
+
64
+ requirements: []
65
+
66
+ dependencies: []
67
+