function_chain 0.0.1

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.
@@ -0,0 +1,404 @@
1
+ require "spec_helper"
2
+
3
+ describe FunctionChain::PullChain do
4
+
5
+ before(:context) do
6
+ City = Struct.new(:bookstore)
7
+ BookStore = Struct.new(:shelves, :recommended_shelf)
8
+ Shelf = Struct.new(:books, :recommended_book_num)
9
+ Book = Struct.new(:title, :author)
10
+
11
+ programing_books = []
12
+ programing_books << Book.new("The Ruby Programming Language",
13
+ "David Flanagan and Yukihiro Matsumoto")
14
+ programing_books << Book.new("Ruby Best Practices", "Gregory T Brown")
15
+ programing_books << Book.new("Metaprogramming Ruby", "Paolo Perrotta")
16
+
17
+ mystery_books = []
18
+ mystery_books << Book.new("And Then There Were None", "Agatha Christie")
19
+ mystery_books << Book.new("Tragedy of X", "Ellery Queen")
20
+
21
+ shelves = {
22
+ programing: Shelf.new(programing_books, 0),
23
+ mystery: Shelf.new(mystery_books, 1)
24
+ }
25
+ @city = City.new(BookStore.new(shelves, :mystery))
26
+
27
+ PullChain = FunctionChain::PullChain
28
+ end
29
+
30
+ it "[success case] symbol type function" do
31
+ chain = PullChain.new(@city) << :bookstore << :shelves
32
+ expect(chain.call).to eq(@city.bookstore.shelves)
33
+ end
34
+
35
+ it "[success case] array type function with args [:symbol, [args]]" do
36
+ chain = PullChain.new(@city)
37
+ chain << :bookstore << :shelves << [:[], [:mystery]]
38
+ expect(chain.call).to eq(@city.bookstore.shelves[:mystery])
39
+ end
40
+
41
+ it "[success case] array type function with args [:symbol, [proc]" do
42
+ chain = PullChain.new([1, 2, 3, 4, 5])
43
+ chain << [:find_all, [lambda { |n| n.even? }]]
44
+ expect(chain.call).to eq([2, 4])
45
+ end
46
+
47
+ it "[success case] array type function with args [:symbol, [arg, proc]]" do
48
+ chain = PullChain.new([1, 2, 3, 4, 5])
49
+ chain << [:inject, [0, lambda { |sum, n| sum + n }]]
50
+ expect(chain.call).to eq(15)
51
+ end
52
+
53
+ it "[success case] array type function with args [:symbol, [args, proc]]" do
54
+ chain = PullChain.new(self)
55
+ def block_caller(v1, v2, v3, v4, &block)
56
+ block.call(v1, v2, v3, v4)
57
+ end
58
+ union_args = lambda { |v1, v2, v3, v4| "#{v1}&#{v2}&#{v3}&#{v4}" }
59
+ chain << [:block_caller, [2, 4, 6, 8, union_args]]
60
+ expect(chain.call).to eq("2&4&6&8")
61
+ end
62
+
63
+ it "[success case] array type function with proc [:symbol, Proc]" do
64
+ chain = PullChain.new(@city) << :bookstore
65
+ chain << :shelves << [:[], Proc.new { |_| bookstore.recommended_shelf }]
66
+ expect(chain.call).to eq(@city.bookstore.shelves[:mystery])
67
+ end
68
+
69
+ it "[success case] string type function" do
70
+ chain = PullChain.new(@city)
71
+ chain << "/bookstore/shelves[:programing]/books[1]/title"
72
+ title = @city.bookstore.shelves[:programing].books[1].title
73
+ expect(chain.call).to eq(title)
74
+ end
75
+
76
+ it "[success case] string type function, add a plurality of times" do
77
+ chain = PullChain.new(@city)
78
+ chain << "/bookstore/shelves[:programing]"
79
+ chain << "/books[1]/title"
80
+ title = @city.bookstore.shelves[:programing].books[1].title
81
+ expect(chain.call).to eq(title)
82
+ end
83
+
84
+ it "[success case] string type function, with reference" do
85
+ chain = PullChain.new(@city)
86
+ chain << "/bookstore/shelves[bookstore.recommended_shelf]/books[0]/author"
87
+ store = @city.bookstore
88
+ author = @city.bookstore.shelves[store.recommended_shelf].books[0].author
89
+ expect(chain.call).to eq(author)
90
+ end
91
+
92
+ it "[success case] string type function, with reference & assign variable" do
93
+ chain = PullChain.new(@city)
94
+ chain << "/bookstore/@shelf = shelves[:mystery]"
95
+ chain << "/books[shelf.recommended_book_num]/title"
96
+ shelf = @city.bookstore.shelves[:mystery]
97
+ title = shelf.books[shelf.recommended_book_num].title
98
+ expect(chain.call).to eq(title)
99
+ end
100
+
101
+ it "[success case] string type function, with escaped /" do
102
+ chain = PullChain.new("AC") << "concat '\\/DC'"
103
+ expect(chain.call).to eq("AC".concat("/DC"))
104
+ end
105
+
106
+ it "[success case] mix type string, symbol, array" do
107
+ chain = PullChain.new(@city)
108
+ chain.add_all(:bookstore, "shelves[:programing]")
109
+ chain << "books" << [:[], [0]] << :title
110
+ title = @city.bookstore.shelves[:programing].books[0].title
111
+ expect(chain.call).to eq(title)
112
+ end
113
+
114
+ it "[success case] insert_all" do
115
+ chain = PullChain.new(@city, "/bookstore/shelves[:programing]/title")
116
+ chain.insert(2, "books[1]")
117
+ title = @city.bookstore.shelves[:programing].books[1].title
118
+ expect(chain.call).to eq(title)
119
+ end
120
+
121
+ it "[success case] inserts" do
122
+ chain = PullChain.new(@city, "/bookstore/title")
123
+ chain.insert_all(1, "shelves[:programing]", "books[1]")
124
+ title = @city.bookstore.shelves[:programing].books[1].title
125
+ expect(chain.call).to eq(title)
126
+ end
127
+
128
+ it "[success case] delete" do
129
+ chain = PullChain.new(@city, "/bookstore/shelves[:programing]/title")
130
+ chain.delete_at(2)
131
+ expect(chain.call).to eq(@city.bookstore.shelves[:programing])
132
+ end
133
+
134
+ it "[success case] clear" do
135
+ chain = PullChain.new(@city, "/bookstore/shelves[:programing]/title")
136
+ chain.clear
137
+ expect(chain.call).to eq(@city)
138
+ end
139
+
140
+ it "[success case] get a value of not exist key" do
141
+ chain = PullChain.new(@city)
142
+ chain << "/bookstore/shelves['not exist key']/books[1]/title"
143
+ expect(chain.call).to be_nil
144
+ end
145
+
146
+ it "[success case] get a nil at error(symbol)" do
147
+ chain = PullChain.new(@city) << :aaaa << :bbbb
148
+ chain.return_nil_at_error = true
149
+ expect(chain.call).to be_nil
150
+ end
151
+
152
+ it "[success case] get a nil at error(string)" do
153
+ chain = PullChain.new(@city) << "/bookstore/xyz/afasd"
154
+ chain.return_nil_at_error = true
155
+ expect(chain.call).to be_nil
156
+ end
157
+
158
+ it "[success case] get a nil at error(array)" do
159
+ chain = PullChain.new(@city) << :bookstore << :shelves << [:x, [:mystery]]
160
+ chain.return_nil_at_error = true
161
+ expect(chain.call).to be_nil
162
+ end
163
+
164
+ it "[success case] get a false" do
165
+ chain = PullChain.new(Object.new) << :nil? << :to_s << :upcase
166
+ expect(chain.call).to eq(false.to_s.upcase)
167
+ end
168
+
169
+ it "[success case] to_s" do
170
+ chain = PullChain.new(@city) << "bookstore/shelves[:programing]"
171
+ chain << :books << [:[], [1]] << :title
172
+ names = ["bookstore", "shelves[:programing]", :books, [:[], [1]], :title]
173
+ expect(chain.to_s).to eq("#{PullChain}#{names}")
174
+ end
175
+
176
+ it "[fail case] NameError" do
177
+ expect do
178
+ FunctionChain.pull(@city, "/bookstore/shelvesassss/")
179
+ end.to raise_error(NameError)
180
+ end
181
+
182
+ it "[fail case] NoMethodError" do
183
+ expect do
184
+ FunctionChain.pull(@city, :bookstore, :create_common_chain_element)
185
+ end.to raise_error(NoMethodError)
186
+ end
187
+
188
+ it "[fail case] ArgumentError:add not supported type" do
189
+ expect do
190
+ FunctionChain.pull(@city, :bookstore, 100)
191
+ end.to raise_error(ArgumentError)
192
+ end
193
+
194
+ it "[fail case] ArgumentError:array format wrong 1" do
195
+ expect do
196
+ FunctionChain.pull(@city, :bookstore, :shelves, [:[]])
197
+ end.to raise_error(ArgumentError)
198
+ end
199
+
200
+ it "[fail case] ArgumentError:array format wrong 2" do
201
+ expect do
202
+ FunctionChain.pull(@city, :bookstore, :shelves, [:[], 1])
203
+ end.to raise_error(ArgumentError)
204
+ end
205
+
206
+ it "[fail case] ArgumentError:wrong format variable define 1" do
207
+ expect do
208
+ chain = PullChain.new(@city)
209
+ chain << "/bookstore/@1shelf = shelves[:mystery]/books[0]/title"
210
+ chain.call
211
+ end.to raise_error(ArgumentError)
212
+ end
213
+
214
+ %w(! " ' # % & ( ) = ~ \\ ` @ [ ] * + < > ? 1 ; : . , ^).each do |e|
215
+ it "[fail case] ArgumentError:wrong format variable define #{e}" do
216
+ expect do
217
+ FunctionChain.pull(@city, "/@#{e}x = bookstore")
218
+ end.to raise_error(ArgumentError)
219
+ end
220
+ end
221
+
222
+ end
223
+
224
+ describe FunctionChain::RelayChain do
225
+
226
+ before(:context) do
227
+
228
+ class Decorator
229
+ def decorate1(value)
230
+ "#{value} is decorated"
231
+ end
232
+
233
+ def decorate2(value)
234
+ "#{value} is more decorated"
235
+ end
236
+ end
237
+
238
+ class EncloseDecorator
239
+ def decorate(value)
240
+ "'#{value}'"
241
+ end
242
+ end
243
+
244
+ class PrefixSuffixDecorator
245
+ def decorate(value, prefix, suffix)
246
+ "#{prefix}#{value}#{suffix}"
247
+ end
248
+ end
249
+
250
+ class MultivalueIO
251
+ def four_values
252
+ return "value1", [1, 2, 3, 4], [4, 3, 2, 1], "value4"
253
+ end
254
+
255
+ def union_four_values(value1, array1, array2, value4)
256
+ "#{value1} & #{array1} & #{array2} & #{value4}"
257
+ end
258
+ end
259
+
260
+ @decorator = Decorator.new
261
+ @enclose_decorator = EncloseDecorator.new
262
+ @prefix_suffix_decorator = PrefixSuffixDecorator.new
263
+ @multivalue_io = MultivalueIO.new
264
+ RelayChain = FunctionChain::RelayChain
265
+ end
266
+
267
+ it "[success case] same instance, use symbol" do
268
+ chain = RelayChain.new(@decorator) >> :decorate1 >> :decorate2
269
+ decorated_value = @decorator.decorate2(@decorator.decorate1("Evans"))
270
+ expect(chain.call("Evans")).to eq(decorated_value)
271
+ end
272
+
273
+ it "[success case] same instance, use string" do
274
+ chain = RelayChain.new(@decorator, "decorate1/decorate2")
275
+ decorated_value = @decorator.decorate2(@decorator.decorate1("Davis"))
276
+ expect(chain.call("Davis")).to eq(decorated_value)
277
+ end
278
+
279
+ it "[success case] same instance, insert_all" do
280
+ chain = RelayChain.new(@decorator) >> :decorate2
281
+ chain.insert(0, :decorate1)
282
+ decorated_value = @decorator.decorate2(@decorator.decorate1("Coltrane"))
283
+ expect(chain.call("Coltrane")).to eq(decorated_value)
284
+ end
285
+
286
+ it "[success case] same instance, delete" do
287
+ chain = RelayChain.new(@decorator) >> :decorate1 >> :decorate2
288
+ chain.delete_at(0)
289
+ expect(chain.call("Petrucciani")).to eq(@decorator.decorate2("Petrucciani"))
290
+ end
291
+
292
+ it "[success case] same instance, clear" do
293
+ chain = RelayChain.new(@decorator) >> :decorate1 >> :decorate2
294
+ chain.clear
295
+ expect(chain.call("Petrucciani")).to be_nil
296
+ end
297
+
298
+ it "[success case] same instance, multiple io" do
299
+ chain = RelayChain.new(@multivalue_io) >> :four_values >> :union_four_values
300
+ value = @multivalue_io.union_four_values(*@multivalue_io.four_values)
301
+ expect(chain.call).to eq(value)
302
+ end
303
+
304
+ it "[success case] differ instance" do
305
+ chain = RelayChain.new(@decorator, :decorate1)
306
+ chain.add_all(:decorate2, [@enclose_decorator, :decorate])
307
+ decorated_value = @decorator.decorate2(@decorator.decorate1("Peterson"))
308
+ decorated_value = @enclose_decorator.decorate(decorated_value)
309
+ expect(chain.call("Peterson")).to eq(decorated_value)
310
+ end
311
+
312
+ it "[success case] differ instance, designate of method name as string" do
313
+ chain = RelayChain.new(@decorator, :decorate1)
314
+ chain.add_all(:decorate2, [@enclose_decorator, "decorate"])
315
+ decorated_value = @decorator.decorate2(@decorator.decorate1("Peterson"))
316
+ decorated_value = @enclose_decorator.decorate(decorated_value)
317
+ expect(chain.call("Peterson")).to eq(decorated_value)
318
+ end
319
+
320
+ it "[success case] differ instance use string & add receiver" do
321
+ chain = RelayChain.new(@decorator)
322
+ chain >> "decorate1/decorate2/e_decorator.decorate"
323
+ chain.add_receiver("e_decorator", @enclose_decorator)
324
+ decorated_value = @decorator.decorate2(@decorator.decorate1("Brown"))
325
+ decorated_value = @enclose_decorator.decorate(decorated_value)
326
+ expect(chain.call("Brown")).to eq(decorated_value)
327
+ end
328
+
329
+ it "[success case] connect to methods that the different num of argument" do
330
+ connector = lambda { |c, value| c.call(value, "Bernard", "Purdie") }
331
+ chain = RelayChain.new >> [@enclose_decorator, :decorate]
332
+ chain >> connector >> [@prefix_suffix_decorator, :decorate]
333
+ decorated_value = @enclose_decorator.decorate("Pretty")
334
+ decorated_value = @prefix_suffix_decorator.decorate(decorated_value,
335
+ "Bernard", "Purdie")
336
+ expect(chain.call("Pretty")).to eq(decorated_value)
337
+ end
338
+
339
+ it "[success case] differ instance, use str & connector & receiver_table" do
340
+ chain = RelayChain.new(@decorator)
341
+ chain.add_receiver_table("e_decorator" => @enclose_decorator,
342
+ "ps_decorator" => @prefix_suffix_decorator)
343
+ connector = lambda { |c, value| c.call(value, "I Say ", ".") }
344
+ chain >> "decorate1/e_decorator.decorate"
345
+ chain >> connector >> "ps_decorator.decorate"
346
+
347
+ value = @enclose_decorator.decorate(@decorator.decorate1("Cake"))
348
+ value = @prefix_suffix_decorator.decorate(value, "I Say ", ".")
349
+ expect(chain.call("Cake")).to eq(value)
350
+ end
351
+
352
+ it "[success case] differ instance, use Method" do
353
+ chain = RelayChain.new
354
+ chain >> @decorator.method(:decorate1)
355
+ chain >> @enclose_decorator.method(:decorate)
356
+ v = @enclose_decorator.decorate(@decorator.decorate1("Skunk"))
357
+ expect(chain.call("Skunk")).to eq(v)
358
+ end
359
+
360
+ it "[success case] use Proc" do
361
+ process1 = lambda { |chain, arr| chain.call(arr.select(&:even?)) }
362
+ process2 = lambda { |_, arr| arr.map { |num| num * 10 } }
363
+ chain = RelayChain.new >> process1 >> process2
364
+ array = [1, 2, 3, 4, 5]
365
+ value = array.select(&:even?).map { |num| num * 10 }
366
+ expect(chain.call(array)).to eq(value)
367
+ end
368
+
369
+ it "[success case] stop of chain" do
370
+ chain = RelayChain.new(@decorator)
371
+ chain.add_all(:decorate1, :decorate2, [@enclose_decorator, :decorate])
372
+ stopper = lambda { |_, value| value }
373
+ chain.insert(2, stopper)
374
+ decorated_value = @decorator.decorate2(@decorator.decorate1("Montgomery"))
375
+ expect(chain.call("Montgomery")).to eq(decorated_value)
376
+ end
377
+
378
+ it "[success case] to_s" do
379
+ chain = RelayChain.new
380
+ stopper = lambda { |_, value| value }
381
+ chain >> @decorator.method(:decorate1) >> stopper
382
+ names = [@decorator.method(:decorate1), stopper]
383
+ expect(chain.to_s).to eq("#{RelayChain}#{names}")
384
+ end
385
+
386
+ it "[fail case] ArgumentError:add not supported type" do
387
+ expect do
388
+ RelayChain.new(@decorator) >> :decorate1 >> 100
389
+ end.to raise_error(ArgumentError)
390
+ end
391
+
392
+ it "[fail case] ArgumentError: wrong number of array's element" do
393
+ expect do
394
+ RelayChain.new(@decorator) >> [@enclose_decorator]
395
+ end.to raise_error(ArgumentError)
396
+ end
397
+
398
+ it "[fail case] ArgumentError: wrong type of array's second element" do
399
+ expect do
400
+ RelayChain.new(@decorator) >> [@enclose_decorator, 10]
401
+ end.to raise_error(ArgumentError)
402
+ end
403
+
404
+ end
@@ -0,0 +1,13 @@
1
+ require "simplecov"
2
+ require "coveralls"
3
+
4
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
5
+ SimpleCov::Formatter::HTMLFormatter,
6
+ Coveralls::SimpleCov::Formatter
7
+ ]
8
+ SimpleCov.start do
9
+ add_filter ".bundle/"
10
+ end
11
+
12
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
13
+ require "function_chain"
data/tasks/flay.rake ADDED
@@ -0,0 +1,11 @@
1
+ require "rake/tasklib"
2
+ require "flay"
3
+ require "flay_task"
4
+
5
+ FlayTask.new do |t|
6
+ t.dirs = FileList["lib/**/*.rb"].map do |each|
7
+ each[%r{[^/]+}]
8
+ end.uniq
9
+ t.threshold = 0
10
+ t.verbose = true
11
+ end
data/tasks/flog.rake ADDED
@@ -0,0 +1,18 @@
1
+ require "flog"
2
+
3
+ desc "Analyze for code complexity"
4
+ task :flog do
5
+ flog = Flog.new(continue: true)
6
+ flog.flog(*FileList["lib/**/*.rb"])
7
+ threshold = 28
8
+
9
+ bad_methods = flog.totals.select do |name, score|
10
+ !(/##{flog.no_method}$/ =~ name) && score > threshold
11
+ end
12
+ bad_methods.sort { |a, b| a[1] <=> b[1] }.reverse.each do |name, score|
13
+ printf "%8.1f: %s\n", score, name
14
+ end
15
+ unless bad_methods.empty?
16
+ $stderr.puts "#{bad_methods.size} methods have a complexity > #{threshold}"
17
+ end
18
+ end
data/tasks/rspec.rake ADDED
@@ -0,0 +1,3 @@
1
+ require "rspec/core/rake_task"
2
+
3
+ RSpec::Core::RakeTask.new
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: function_chain
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Kenji Suzuki
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-14 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: 'FunctionChain objectifies of the method chain.chain objects can call
14
+ later or add chain or insert chain or delete chain.supported chain type is following:
15
+ foo.bar.baz, baz(bar(foo(value))).'
16
+ email:
17
+ - pujoheadsoft@gmail.com
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - .coveralls.yml
23
+ - .gitignore
24
+ - .rspec
25
+ - .rubocop.yml
26
+ - .travis.yml
27
+ - Gemfile
28
+ - LICENSE.txt
29
+ - README.md
30
+ - Rakefile
31
+ - function_chain.gemspec
32
+ - lib/function_chain.rb
33
+ - lib/function_chain/base_chain.rb
34
+ - lib/function_chain/pull_chain.rb
35
+ - lib/function_chain/relay_chain.rb
36
+ - lib/function_chain/version.rb
37
+ - spec/function_chain_spec.rb
38
+ - spec/spec_helper.rb
39
+ - tasks/flay.rake
40
+ - tasks/flog.rake
41
+ - tasks/rspec.rake
42
+ homepage: https://github.com/pujoheadsoft/function_chain
43
+ licenses:
44
+ - MIT
45
+ metadata: {}
46
+ post_install_message:
47
+ rdoc_options: []
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: 1.9.3
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - '>='
58
+ - !ruby/object:Gem::Version
59
+ version: 1.3.5
60
+ requirements: []
61
+ rubyforge_project:
62
+ rubygems_version: 2.4.1
63
+ signing_key:
64
+ specification_version: 4
65
+ summary: FunctionChain objectifies of the method chain.
66
+ test_files:
67
+ - spec/function_chain_spec.rb
68
+ - spec/spec_helper.rb