function_chain 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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