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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cceaae212ecd1dba66efa5822e61947b5af1bcfa
4
+ data.tar.gz: 09a02eeac6d159f127d851d615ee543cde23402b
5
+ SHA512:
6
+ metadata.gz: 05d5b0e5ffae56ce85c88b5459fe7c68580e6872e86e456f2da24a17775c91e4e502905efd14ad8f3df6bd495e39b55b72537a5ce5b415ea63c25f159659a226
7
+ data.tar.gz: 22c3ec7ae4db1128e6cc75f2580a18345c5b2c8e33a051a22f6b7fa3bf44976ace7eb65253219c9490c1368481a15d395b962060c0dc0d3f037f7e0d962bffb3
data/.coveralls.yml ADDED
@@ -0,0 +1 @@
1
+ service_name: travis-ci
data/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /Guardfile
5
+ /_yardoc/
6
+ /coverage/
7
+ /doc/
8
+ /pkg/
9
+ /spec/reports/
10
+ /tmp/
11
+ *.bundle
12
+ *.so
13
+ *.o
14
+ *.a
15
+ mkmf.log
16
+ /.idea/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,41 @@
1
+ HashSyntax:
2
+ EnforcedStyle: ruby19
3
+ SupportedStyles:
4
+ - ruby19
5
+ - hash_rockets
6
+
7
+ Documentation:
8
+ Enabled: false
9
+
10
+ LineLength:
11
+ Enabled: false
12
+
13
+ ClassLength:
14
+ Enabled: false
15
+
16
+ RegexpLiteral:
17
+ MaxSlashes: 0
18
+
19
+ GuardClause:
20
+ MinBodyLength: 3
21
+
22
+ TrivialAccessors:
23
+ AllowPredicates: true
24
+
25
+ RedundantReturn:
26
+ AllowMultipleReturnValues: true
27
+
28
+ RedundantBegin:
29
+ Enabled: false
30
+
31
+ SpaceInsideHashLiteralBraces:
32
+ EnforcedStyle: no_space
33
+
34
+ Style/Lambda:
35
+ Enabled: false
36
+
37
+ Style/Proc:
38
+ Enabled: false
39
+
40
+ StringLiterals:
41
+ EnforcedStyle: double_quotes
data/.travis.yml ADDED
@@ -0,0 +1,10 @@
1
+ bundler_args: --without development
2
+ language: ruby
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - 2.1
7
+ script: bundle exec rspec
8
+ branches:
9
+ only:
10
+ - master
data/Gemfile ADDED
@@ -0,0 +1,20 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rake", ">= 0.9"
4
+ gem "rdoc", ">= 3.9"
5
+
6
+ group :development do
7
+ gem "guard-rubocop"
8
+ gem "terminal-notifier-guard"
9
+ gem "flay"
10
+ gem "flog"
11
+ end
12
+
13
+ group :test do
14
+ gem "coveralls", require: false
15
+ gem "rubocop", ">= 0.19"
16
+ gem "rspec", ">= 3"
17
+ gem "simplecov", ">= 0.9"
18
+ end
19
+
20
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Kenji Suzuki
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,421 @@
1
+ # FunctionChain
2
+
3
+ [![Build Status](http://img.shields.io/travis/pujoheadsoft/function_chain.svg)][travis]
4
+ [![Coverage Status](http://img.shields.io/coveralls/pujoheadsoft/function_chain.svg)][coveralls]
5
+ [![Code Climate](http://img.shields.io/codeclimate/github/pujoheadsoft/function_chain.svg)][codeclimate]
6
+
7
+ [travis]: http://travis-ci.org/pujoheadsoft/function_chain
8
+ [coveralls]: https://coveralls.io/r/pujoheadsoft/function_chain
9
+ [codeclimate]: https://codeclimate.com/github/pujoheadsoft/function_chain
10
+
11
+ ## Description
12
+ **FunctionChain** objectifies of the method chain.
13
+ Chain object can following.
14
+ * Call later.
15
+ * Add method to chain
16
+ * Insert method to chain.
17
+ * Delete method from chain.
18
+
19
+ ## Installation
20
+ gem install function_chain
21
+
22
+ ## PullChain & RelayChain
23
+ **PullChain & RelayChain** is FunctionChain module's classes.
24
+ PullChain & RelayChain will support call chain type, each different.
25
+
26
+ * PullChain to support the call chain type such as the following:
27
+ ```ruby
28
+ account.user.name
29
+ ```
30
+ If used the PullChain (detail description is [here](#pullchain))
31
+ ```ruby
32
+ chain = PullChain.new(account) << :user << :name
33
+ chain.call
34
+ ```
35
+
36
+ * RelayChain to support the call chain type such as the following:
37
+ ```ruby
38
+ filter3(filter2(filter1(value)))
39
+ ```
40
+ If used the RelayChain (detail description is [here](#relaychain))
41
+ ```ruby
42
+ chain = RelayChain.new >> :filter1 >> :filter2 >> :filter3
43
+ chain.call("XXX")
44
+ ```
45
+
46
+
47
+ ## Usage and documentation
48
+ The following is necessary call to use the PullChain or RelayChain.
49
+ ```ruby
50
+ require "function_chain"
51
+ include FunctionChain
52
+ ```
53
+ **Note:** This document omit the above code from now on.
54
+ ## PullChain
55
+ PullChain is object as represent method call chain.
56
+ Can inner object's method call of object.
57
+ ### Example
58
+ ```ruby
59
+ Account = Struct.new(:user)
60
+ User = Struct.new(:name)
61
+ account = Account.new(User.new("Louis"))
62
+
63
+ chain = PullChain.new(account, :user, :name, :upcase)
64
+ chain.call # => LOUIS
65
+ ```
66
+
67
+ #### Similar
68
+ 1. **Strings separated by a slash**
69
+ ```ruby
70
+ PullChain.new(account, "user/name/upcase").call
71
+ ```
72
+
73
+ 2. **Use << operator**
74
+ ```ruby
75
+ chain = PullChain.new(account)
76
+ chain << :user << :name << :upcase
77
+ chain.call
78
+ ```
79
+
80
+ 3. **Use add method**
81
+ ```ruby
82
+ chain.add(:user).add(:name).add(:upcase).call
83
+ ```
84
+
85
+ 4. **Use add_all method**
86
+ ```ruby
87
+ chain.add_all(:user, :name, :upcase).call
88
+ ```
89
+
90
+ #### Can exist nil value on the way, like a following case
91
+ ```ruby
92
+ user.name = nil
93
+ chain.call # => nil
94
+ ```
95
+
96
+ #### Insert, Delete, Clear
97
+ insert, insert_all method is insert_all method to chain.
98
+ delete_at method is delete method from chain.
99
+ clear method is delete all method from chain.
100
+
101
+ ### Require arguments on method
102
+ Following example's method is require two arguments.
103
+ What should do in this case?
104
+ ```ruby
105
+ class Foo
106
+ def say(speaker, message)
107
+ puts "#{speaker} said '#{message}'"
108
+ end
109
+ end
110
+ ```
111
+ ###### Solution
112
+ 1. **Array, format is [Symbol, [\*Args]]**
113
+ ```ruby
114
+ chain = PullChain.new(Foo.new) << [:say, ["Andres", "Hello"]]
115
+ chain.call # => Andres said 'Hello'
116
+ ```
117
+
118
+ 2. **String**
119
+ ```ruby
120
+ chain = PullChain.new(foo) << "say('John', 'Goodbye')"
121
+ chain.call # => John said 'Goodbye'
122
+ ```
123
+
124
+ ### Require block on method
125
+ Following example's method is require Block.
126
+ What should do in this case?
127
+ ```ruby
128
+ [1,2,3,4,5].inject(3) { |sum, n| sum + n } # => 18
129
+ ```
130
+
131
+ ###### Solution
132
+
133
+ 1. **Array, format is [Symbol, [\*Args, Proc]].**
134
+ ```ruby
135
+ chain = PullChain.new([1,2,3,4,5])
136
+ chain << [:inject, [3, lambda { |sum, n| sum + n }]]
137
+ chain.call # => 18
138
+ ```
139
+
140
+ 2. **String**
141
+ ```ruby
142
+ chain = PullChain.new([1,2,3,4,5])
143
+ chain << "inject(3) { |sum, n| sum + n }"
144
+ chain.call # => 18
145
+ ```
146
+
147
+ ### Use result on chain
148
+ Like a following example, can use result on chain.
149
+ ```ruby
150
+ Foo = Struct.new(:bar)
151
+ Bar = Struct.new(:baz) {
152
+ def speaker
153
+ "Julian"
154
+ end
155
+ }
156
+ class Baz
157
+ def say(speaker, message)
158
+ puts "#{speaker} said '#{message}'"
159
+ end
160
+ end
161
+ foo = Foo.new(Bar.new(Baz.new))
162
+ ```
163
+ ###### Example: use result on chain
164
+
165
+ 1. **String**
166
+ Can use bar instance in backward!
167
+ ```ruby
168
+ chain = PullChain.new(foo) << "bar/baz/say(bar.speaker, 'Good!')"
169
+ chain.call # => Julian said 'Good!'
170
+ ```
171
+ Furthermore, can use variable name assigned.
172
+ @b is bar instance alias.
173
+ ```ruby
174
+ chain = PullChain.new(foo) << "@b = bar/baz/say(b.speaker, 'Cool')"
175
+ chain.call # => Julian said 'Cool'
176
+ ```
177
+
178
+ 2. **Array**
179
+ Can access result by Proc.
180
+ ```ruby
181
+ chain = PullChain.new(foo) << :bar << :baz
182
+ chain << [:say, Proc.new { next bar.speaker, "Oh" }]
183
+ chain.call # => Julian said 'Oh'
184
+ ```
185
+ Case of use a lambda, can use result access object explicit.
186
+ ```ruby
187
+ chain = PullChain.new(foo) << :bar << :baz
188
+ arg_reader = lambda { |accessor| next accessor.bar.speaker, "Oh" }
189
+ chain << [:say, arg_reader]
190
+ chain.call # => Julian said 'Oh'
191
+ ```
192
+
193
+ #### etc
194
+ 1. **How to use slash in strings separated by a slash**
195
+ Like following, please escaped by backslash.
196
+ ```ruby
197
+ chain = PullChain.new("AC") << "concat '\\/DC'"
198
+ chain.call # => AC/DC
199
+ ```
200
+
201
+ 2. **Use return_nil_at_error= method, then can ignore error**
202
+ ```ruby
203
+ chain = PullChain.new("Test") << :xxx
204
+ begin
205
+ chain.call # => undefined method `xxx'
206
+ rescue
207
+ end
208
+ chain.return_nil_at_error = true
209
+ chain.call # => nil
210
+ ```
211
+
212
+ 3. **Note:use operator in chain**
213
+ * **String type chain**
214
+ ```ruby
215
+ table = {name: %w(Bill Scott Paul)}
216
+ PullChain.new(table, "[:name]").call # => [:name] NG
217
+ PullChain.new(table, "self[:name]").call # => ["Bill", "Scott", "Paul"] OK
218
+ ```
219
+
220
+ * **Array type chain**
221
+ ```ruby
222
+ PullChain.new(table, [:[], [:name]]).call # OK
223
+ ```
224
+
225
+ Following is also the same.
226
+
227
+ * **<< operator of String**
228
+ ```ruby
229
+ PullChain.new("Led", "<< ' Zeppelin'").call # NG syntax error
230
+ PullChain.new("Led", "self << ' Zeppelin'").call # => "Led Zeppelin"
231
+ ```
232
+
233
+ * **[] operator of Array**
234
+ ```ruby
235
+ PullChain.new(%w(Donald Walter), "[1]").call # NG => [1]
236
+ PullChain.new(%w(Donald Walter), "self[1]").call # OK => Walter
237
+ ```
238
+
239
+ 4. **Some classes, such Fixnum and Bignum not supported**
240
+ ```ruby
241
+ PullChain.new(999999999999999, "self % 2").call # NG
242
+ ```
243
+
244
+ ---
245
+ ## RelayChain
246
+ RelayChain is object like a connect to function's input from function's output.
247
+ (methods well as can connect Proc.)
248
+
249
+ ### Example
250
+ ```ruby
251
+ class Decorator
252
+ def decorate1(value)
253
+ "( #{value} )"
254
+ end
255
+ def decorate2(value)
256
+ "{ #{value} }"
257
+ end
258
+ end
259
+
260
+ chain = RelayChain.new(Decorator.new, :decorate1, :decorate2)
261
+ chain.call("Hello") # => { ( Hello ) }
262
+ ```
263
+ #### Similar
264
+ 1. **Strings separated by a slash**
265
+ ```ruby
266
+ chain = RelayChain.new(Decorator.new, "decorate1/decorate2")
267
+ chain.call("Hello")
268
+ ```
269
+
270
+ 2. **Use >> operator**
271
+ ```ruby
272
+ chain = RelayChain.new(Decorator.new)
273
+ chain >> :decorate1 >> :decorate2
274
+ chain.call("Hello")
275
+ ```
276
+
277
+ 3. **Use Method object**
278
+ ```ruby
279
+ chain = RelayChain.new
280
+ chain >> decorator.method(:decorate1) >> decorator.method(:decorate2)
281
+ chain.call("Hello")
282
+ ```
283
+
284
+ 4. **Use add method**
285
+ ```ruby
286
+ chain.add(:decorate1).add(:decorate2).call("Hello")
287
+ ```
288
+
289
+ 5. **Use add_all method**
290
+ ```ruby
291
+ chain.add_all(:decorate1, :decorate2).call("Hello")
292
+ ```
293
+
294
+ #### Insert, Delete, Clear
295
+ insert, insert_all method is insert function to chain.
296
+ delete_at method is delete function from chain.
297
+ clear method is delete all function from chain.
298
+
299
+ ### How to connect method of differed instance
300
+ Example, following two class.
301
+ How to connect method of these class?
302
+ ```ruby
303
+ class Decorator
304
+ def decorate1(value)
305
+ "( #{value} )"
306
+ end
307
+ def decorate2(value)
308
+ "{ #{value} }"
309
+ end
310
+ end
311
+
312
+ class Decorator2
313
+ def decorate(value)
314
+ "[ #{value} ]"
315
+ end
316
+ end
317
+ ```
318
+ ###### Solution
319
+ 1. **Array, format is [instance, Symbol or String of method]**
320
+ ```ruby
321
+ # Symbol ver.
322
+ chain = RelayChain.new(Decorator.new)
323
+ chain >> :decorate1 >> :decorate2 >> [Decorator2.new, :decorate]
324
+ chain.call("Hello") # => [ { ( Hello ) } ]
325
+
326
+ # String ver.
327
+ chain = RelayChain.new(Decorator.new)
328
+ chain >> :decorate1 >> :decorate2 >> [Decorator2.new, "decorate"]
329
+ chain.call("Hello") # => [ { ( Hello ) } ]
330
+ ```
331
+
332
+ 2. **String, use registered instance**
333
+ ```ruby
334
+ chain = RelayChain.new(Decorator.new)
335
+
336
+ # register name and instance
337
+ chain.add_receiver("d2", Decorator2.new)
338
+
339
+ # use registered instance
340
+ chain >> "/decorate1/decorate2/d2.decorate"
341
+ chain.call("Hello") # => [ { ( Hello ) } ]
342
+
343
+ # add_receiver_table method is register name and instance at once.
344
+ chain.add_receiver_table({"x" => X.new, "y" => Y.new})
345
+ ```
346
+
347
+ ### Case of method's output and method's input mismatch
348
+ Following example, decorate output is 1, and union input is 2.
349
+ How to do connect these methods?
350
+ ```ruby
351
+ class Decorator
352
+ def decorate(value)
353
+ "#{value} And"
354
+ end
355
+ def union(value1, value2)
356
+ "#{value1} #{value2}"
357
+ end
358
+ end
359
+ ```
360
+ ###### Solution
361
+ 1. **Define connect method.**
362
+ ```ruby
363
+ class Decorator
364
+ def connect(value)
365
+ return value, "Palmer"
366
+ end
367
+ end
368
+ chain = RelayChain.new(Decorator.new)
369
+ chain >> :decorate >> :connect >> :union
370
+ chain.call("Emerson, Lake") # => Emerson, Lake And Palmer
371
+ ```
372
+
373
+ 2. **Add lambda or Proc to between these methods.**
374
+ lambda's format is following.
375
+ ```ruby
376
+ # parameter: chain is chain object.
377
+ # parameter: \*args is previous functions output.
378
+ lambda {|chain, *args| chain.call(next functions arguments) }.
379
+ ```
380
+ can call next function by chain object.
381
+ ```ruby
382
+ chain = RelayChain.new(Decorator.new)
383
+ arg_adder = lambda { |chain, value| chain.call(value, "Jerry") }
384
+ chain >> :decorate >> arg_adder >> :union
385
+ chain.call("Tom") # => Tom And Jerry
386
+ ```
387
+
388
+ ### Appendix
389
+ **Chain stop by means of lambda.**
390
+ ```ruby
391
+ class Decorator
392
+ def decorate1(value)
393
+ "( #{value} )"
394
+ end
395
+
396
+ def decorate2(value)
397
+ "{ #{value} }"
398
+ end
399
+ end
400
+
401
+ def create_stopper(&stop_condition)
402
+ lambda do |chain, value|
403
+ # if stop conditions are met then return value
404
+ if stop_condition.call(value)
405
+ value
406
+ else
407
+ chain.call(value)
408
+ end
409
+ end
410
+ end
411
+
412
+ chain = RelayChain.new(Decorator.new, :decorate1, :decorate2)
413
+
414
+ # insert_all conditional chain stopper
415
+ chain.insert(1, create_stopper { |value| value =~ /\d/ })
416
+ chain.call("Van Halen 1984") # => ( Van Halen 1984 ) not enclosed to {}
417
+ chain.call("Van Halen Jump") # => { ( Van Halen Jump ) } enclosed to {}
418
+ ```
419
+
420
+ ## License
421
+ Released under the MIT License.
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ task default: :spec
4
+
5
+ task quality: [:flog, :flay]
6
+
7
+ Dir.glob("tasks/*.rake").each { |each| import each }
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "function_chain/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "function_chain"
8
+ spec.version = FunctionChain::VERSION
9
+ spec.authors = ["Kenji Suzuki"]
10
+ spec.email = ["pujoheadsoft@gmail.com"]
11
+ spec.summary = "FunctionChain objectifies of the method chain."
12
+ spec.description = <<-EOF.gsub(/^\s+|\n/, "")
13
+ FunctionChain objectifies of the method chain.
14
+ chain objects can call later or add chain or insert chain or delete chain.
15
+ supported chain type is following: foo.bar.baz, baz(bar(foo(value))).
16
+ EOF
17
+ spec.homepage = "https://github.com/pujoheadsoft/function_chain"
18
+ spec.license = "MIT"
19
+
20
+ spec.files = `git ls-files -z`.split("\x0")
21
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
22
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
23
+ spec.require_paths = ["lib"]
24
+
25
+ spec.required_ruby_version = ">= 1.9.3"
26
+ spec.required_rubygems_version = ">= 1.3.5"
27
+ end
@@ -0,0 +1,110 @@
1
+ module FunctionChain
2
+ # Base class of PullChain, RelayChain
3
+ class BaseChain
4
+ # Add functions to chain
5
+ def add_all(*functions)
6
+ insert_all(chain_elements.size, *functions)
7
+ self
8
+ end
9
+
10
+ # Add function to chain
11
+ def add(function)
12
+ insert(chain_elements.size, function)
13
+ end
14
+
15
+ # Insert functions to chain
16
+ def insert_all(index, *functions)
17
+ functions.each_with_index { |f, i| insert(index + i, f) }
18
+ self
19
+ end
20
+
21
+ # Insert function to chain
22
+ def insert(index, function)
23
+ if function.is_a? String
24
+ do_insert_by_string(index, function)
25
+ else
26
+ do_insert(index, function)
27
+ end
28
+ self
29
+ end
30
+
31
+ # Delete from chain
32
+ def delete_at(index)
33
+ chain_elements.delete_at(index)
34
+ self
35
+ end
36
+
37
+ # Clear function chain
38
+ def clear
39
+ chain_elements.clear
40
+ end
41
+
42
+ def to_s
43
+ "#{self.class}#{chain_elements.map(&:to_s)}"
44
+ end
45
+
46
+ protected
47
+
48
+ def do_insert(index, function)
49
+ chain_element = create_chain_element(function)
50
+ chain_elements.insert(index, chain_element)
51
+ def_to_s(chain_element, function)
52
+ end
53
+
54
+ def do_insert_by_string(index, function)
55
+ function.split(%r{(?<!\\)/}).reject(&:empty?).each_with_index do |f, i|
56
+ splitted_function = f.gsub(%r{\\/}, "/")
57
+ chain_element = create_chain_element(splitted_function)
58
+ chain_elements.insert(index + i, chain_element)
59
+ def_to_s(chain_element, splitted_function)
60
+ end
61
+ end
62
+
63
+ def create_chain_element(function)
64
+ case function
65
+ when Symbol then create_chain_element_by_symbol(function)
66
+ when Array then create_chain_element_by_array(function)
67
+ when String then create_chain_element_by_string(function)
68
+ else
69
+ fail ArgumentError, <<-EOF.gsub(/^\s+|\n/, "")
70
+ Not supported type #{function}(#{function.class}),
71
+ supported type is #{supported_types}.
72
+ EOF
73
+ end
74
+ end
75
+
76
+ def def_to_s(target, value)
77
+ target.singleton_class.class_eval do
78
+ define_method :to_s do
79
+ value
80
+ end
81
+ end
82
+ end
83
+
84
+ def validate_array_length(arr, expect_length, expect_format)
85
+ unless expect_length == arr.length
86
+ message = "Format Wrong #{arr}, expected format is [#{expect_format}]"
87
+ fail ArgumentError, message
88
+ end
89
+ end
90
+
91
+ def validate_element_type_of_array(arr, i, expect_types, types_as_string)
92
+ unless target_is_a_one_of_types?(arr[i], expect_types)
93
+ fail ArgumentError, "Format Wrong #{arr}," \
94
+ " second element of array is must be #{types_as_string}"
95
+ end
96
+ end
97
+
98
+ def target_is_a_one_of_types?(target, types)
99
+ types.any? { |type| target.is_a? type }
100
+ end
101
+
102
+ def chain_elements
103
+ @chain_elements ||= []
104
+ end
105
+
106
+ def supported_types
107
+ [Symbol, Array, String]
108
+ end
109
+ end
110
+ end