core-pipeline 0.1.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 12857259602df10fd3cb27322098ba04c9f3b7706fbd982939ba162e97f4dbcb
4
- data.tar.gz: fbb77341b33a2cb8195dd6431fd23efeb99499fd6bf3b175a1cadc831feae135
3
+ metadata.gz: 28a2f0e27827605918442c956cb6e4236cb146ba16c180f9418569dd09711da9
4
+ data.tar.gz: f7927e0c5657dfaa13e1bc03a48bfe0fb75ff5cb2b47d5417545c89a6cf41f78
5
5
  SHA512:
6
- metadata.gz: 8383cd41dc3db75a6b8329baff6f7af529b4fcb2f82464fa3be3c5afbb3fdfe44a8666aa2815ef115a191316066cb1a49c11a48747dd1b8755d9b89233329762
7
- data.tar.gz: 254a3bc8e99465394dd6f7b2bbe3dc8e90a73d655d037e3c1b44580c0de172f19360fe696683940aaf7d22c72950b91ef59ab7bd209bd30e09afdbc3929aaeb6
6
+ metadata.gz: 379641bc184684af5be9e35b02a926b5f85a52f63c83723afa95722136184a05c2474f64a8c8f67b5261989b098051eec20d5920901356dbaadc4063ee276dfa
7
+ data.tar.gz: 5bf61a391a6aac27d282eb7cb7fa8d1d973e50496316dc405760e9ef9510c7299cb46920993db62ed80b190a677342c80f4afcfd707526e14132e90621fbacc2
data/CHANGELOG.md CHANGED
@@ -1,7 +1,28 @@
1
+ ## [v0.4.0](https://github.com/metabahn/corerb/releases/tag/2021-11-02.1)
2
+
3
+ *released on 2021-11-02*
4
+
5
+ * `add` [#98](https://github.com/metabahn/corerb/pull/98) Add a finalizer to pipelines ([bryanp](https://github.com/bryanp))
6
+
7
+ ## [v0.3.0](https://github.com/metabahn/corerb/releases/tag/2021-11-02)
8
+
9
+ *released on 2021-11-02*
10
+
11
+ * `chg` [#97](https://github.com/metabahn/corerb/pull/97) Designate internal state with leading and trailing double underscores ([bryanp](https://github.com/bryanp))
12
+ * `chg` [#89](https://github.com/metabahn/corerb/pull/89) Allow the pipeline compiler to be extended ([bryanp](https://github.com/bryanp))
13
+
14
+ ## [v0.2.0](https://github.com/metabahn/corerb/releases/tag/2021-10-24)
15
+
16
+ *released on 2021-10-24*
17
+
18
+ * `chg` [#77](https://github.com/metabahn/corerb/pull/77) Add recompile support to pipelines ([bryanp](https://github.com/bryanp))
19
+
1
20
  ## [v0.1.0](https://github.com/metabahn/corerb/releases/tag/2021-07-15)
2
21
 
3
22
  *released on 2021-07-15*
4
23
 
24
+ * `fix` [#81](https://github.com/metabahn/corerb/pull/81) Tie up loose ends around curried pipeline actions ([bryanp](https://github.com/bryanp))
25
+ * `add` [#80](https://github.com/metabahn/corerb/pull/80) Define curried pipeline actions ([bryanp](https://github.com/bryanp))
5
26
  * `fix` [#69](https://github.com/metabahn/corerb/pull/69) Allow pipelines to be called at the class level ([bryanp](https://github.com/bryanp))
6
27
  * `add` [#64](https://github.com/metabahn/corerb/pull/64) Add a method for checking if a callable pipeline will call any actions ([bryanp](https://github.com/bryanp))
7
28
  * `chg` [#63](https://github.com/metabahn/corerb/pull/63) Improve inspect output for callable pipelines ([bryanp](https://github.com/bryanp))
@@ -10,26 +10,26 @@ module Core
10
10
  #
11
11
  class Action
12
12
  include Is::Stateful
13
- state :__used_random_suffixes, default: []
13
+ state :__used_random_suffixes__, default: []
14
14
 
15
15
  class << self
16
16
  # [public] Builds an action for a given target.
17
17
  #
18
- def build(target = nil, *args, before: nil, after: nil, context: nil, &block)
18
+ def build(target = nil, *args, before: nil, after: nil, context: nil, curry: false, &block)
19
19
  if block
20
- Actions::Block.new(target, before: before, after: after, context: context, &block)
20
+ Actions::Block.new(target, before: before, after: after, context: context, curry: curry, &block)
21
21
  else
22
- build_target(target, *args, before: before, after: after, context: context)
22
+ build_target(target, *args, before: before, after: after, context: context, curry: curry)
23
23
  end
24
24
  end
25
25
 
26
- private def build_target(first, *args, before:, after:, context:)
26
+ private def build_target(first, *args, before:, after:, context:, curry:)
27
27
  case first
28
28
  when String, Symbol
29
- if (target = build_target(args[0], *args[1..], before: before, after: after, context: context))
29
+ if (target = build_target(args[0], *args[1..], before: before, after: after, context: context, curry: curry))
30
30
  target
31
31
  else
32
- Actions::Method.new(first, before: before, after: after, context: context)
32
+ Actions::Method.new(first, before: before, after: after, context: context, curry: curry)
33
33
  end
34
34
  when NilClass
35
35
  nil
@@ -40,10 +40,10 @@ module Core
40
40
 
41
41
  def build_name
42
42
  suffix = generate_random_suffix
43
- if __used_random_suffixes.include?(suffix)
43
+ if __used_random_suffixes__.include?(suffix)
44
44
  build_name
45
45
  else
46
- __used_random_suffixes << suffix
46
+ __used_random_suffixes__ << suffix
47
47
  "action_#{suffix}"
48
48
  end
49
49
  end
@@ -55,11 +55,12 @@ module Core
55
55
 
56
56
  include Is::Inspectable
57
57
 
58
- def initialize(name, before: nil, after: nil, context: nil)
58
+ def initialize(name, before: nil, after: nil, context: nil, curry: false)
59
59
  @name = (name || self.class.build_name).to_sym
60
60
  @before = before
61
61
  @after = after
62
62
  @context = context
63
+ @curry = curry
63
64
  end
64
65
 
65
66
  # [public] The action name.
@@ -74,6 +75,16 @@ module Core
74
75
  #
75
76
  attr_reader :after
76
77
 
78
+ # [public] The context this action should be called in.
79
+ #
80
+ attr_reader :context
81
+
82
+ # [public] Returns `true` if the action should be curried.
83
+ #
84
+ def curried?
85
+ @curry == true
86
+ end
87
+
77
88
  # [public] Finalizes the action for the given context.
78
89
  #
79
90
  def finalize(context)
@@ -10,10 +10,10 @@ module Core
10
10
  class Block < Action
11
11
  include Is::Inspectable
12
12
 
13
- def initialize(name = nil, before: nil, after: nil, context: nil, &block)
13
+ def initialize(name = nil, before: nil, after: nil, context: nil, curry: false, &block)
14
14
  @block = block
15
15
 
16
- super(name, before: before, after: after, context: context)
16
+ super(name, before: before, after: after, context: context, curry: curry)
17
17
  end
18
18
 
19
19
  # [public]
@@ -21,13 +21,19 @@ module Core
21
21
  def finalize(context)
22
22
  case @context
23
23
  when NilClass
24
- context.define_method(@name, &@block)
24
+ unless context.method_defined?(@name)
25
+ context.define_method(@name, &@block)
26
+ end
27
+
25
28
  @name
26
29
  else
27
30
  if @block.binding.receiver.equal?(@context)
28
31
  @block
29
32
  else
30
- @context.define_singleton_method(@name, &@block)
33
+ unless context.singleton_class.method_defined?(@name)
34
+ @context.define_singleton_method(@name, &@block)
35
+ end
36
+
31
37
  @context.method(@name).to_proc
32
38
  end
33
39
  end
@@ -10,10 +10,10 @@ module Core
10
10
  class Method < Action
11
11
  include Is::Inspectable
12
12
 
13
- def initialize(name = nil, before: nil, after: nil, context: nil)
13
+ def initialize(name = nil, before: nil, after: nil, context: nil, curry: false)
14
14
  @method = nil
15
15
 
16
- super(name, before: before, after: after, context: context)
16
+ super(name, before: before, after: after, context: context, curry: curry)
17
17
  end
18
18
 
19
19
  # [public]
@@ -18,11 +18,29 @@ module Core
18
18
  @mutex = Mutex.new
19
19
  @actions = []
20
20
  @skipped = []
21
+ @compiled = false
22
+ @compiler = Compiler
23
+ end
24
+
25
+ def initialize_copy(...)
26
+ @actions = @actions.clone
27
+ @skipped = @skipped.clone
28
+ super
21
29
  end
22
30
 
23
31
  attr_reader :actions
24
32
  attr_reader :skipped
25
33
 
34
+ # [public]
35
+ #
36
+ attr_writer :compiler
37
+
38
+ # [public] Relocates to another object context.
39
+ #
40
+ def relocate(object)
41
+ @object = object
42
+ end
43
+
26
44
  # [public] Returns true if the pipeline will call any actions.
27
45
  #
28
46
  def any?
@@ -31,14 +49,16 @@ module Core
31
49
 
32
50
  # [public] Defines a pipeline action.
33
51
  #
34
- def action(*args, before: nil, after: nil, context: nil, &block)
35
- @actions << Action.build(*args, before: before, after: after, context: context, &block)
52
+ def action(*args, before: nil, after: nil, context: nil, curry: false, &block)
53
+ @actions << Action.build(*args, before: before, after: after, context: context, curry: curry, &block)
54
+ recompile if compiled?
36
55
  end
37
56
 
38
57
  # [public] Skips the given action.
39
58
  #
40
59
  def skip(name)
41
60
  @skipped << name.to_sym
61
+ recompile if compiled?
42
62
  end
43
63
 
44
64
  # [public] Replaces existing actions with actions from the given pipeline.
@@ -48,6 +68,7 @@ module Core
48
68
  @mutex.synchronize do
49
69
  @actions.clear
50
70
  @actions.concat(pipeline.pipeline.actions)
71
+ recompile if compiled?
51
72
  end
52
73
  else
53
74
  raise ArgumentError, "expected a pipeline"
@@ -59,6 +80,7 @@ module Core
59
80
  def include(pipeline)
60
81
  if (pipeline.is_a?(Class) || pipeline.is_a?(Module)) && pipeline.ancestors.include?(Is::Pipeline)
61
82
  @actions.concat(pipeline.pipeline.actions)
83
+ recompile if compiled?
62
84
  else
63
85
  raise ArgumentError, "expected a pipeline"
64
86
  end
@@ -70,6 +92,7 @@ module Core
70
92
  if (pipeline.is_a?(Class) || pipeline.is_a?(Module)) && pipeline.ancestors.include?(Is::Pipeline)
71
93
  pipeline.pipeline.actions.each do |action|
72
94
  @actions.delete(action)
95
+ recompile if compiled?
73
96
  end
74
97
  else
75
98
  raise ArgumentError, "expected a pipeline"
@@ -79,14 +102,30 @@ module Core
79
102
  # [public] Calls the pipeline in context of an object with the given arguments.
80
103
  #
81
104
  def call(object, ...)
82
- compile.call(object, ...)
105
+ finalize.call(object, ...)
83
106
  end
84
107
 
85
- private def compile
86
- instance_eval(Compiler.compile(self, @object), __FILE__, __LINE__ - 1)
108
+ # [public] Finalizes the pipeline.
109
+ #
110
+ def finalize
111
+ compile
87
112
 
88
113
  self
89
114
  end
115
+
116
+ private def compile
117
+ instance_eval(@compiler.compile(self, @object), __FILE__, __LINE__ - 1)
118
+ @compiled = true
119
+ end
120
+
121
+ private def recompile
122
+ singleton_class.remove_method(:call)
123
+ compile
124
+ end
125
+
126
+ private def compiled?
127
+ @compiled == true
128
+ end
90
129
  end
91
130
  end
92
131
  end
@@ -21,28 +21,39 @@ module Core
21
21
  CODE
22
22
  end
23
23
 
24
+ # [public]
25
+ #
24
26
  private def compile_call(callable, object)
25
27
  compiled = +""
26
- finalized_actions(callable, object).each_pair do |object_id, action|
27
- compiled << "begin; "
28
+ finalized_actions(callable, object).each_value do |action|
29
+ compiled << "begin\n"
30
+ compiled << compile_action(action, object)
31
+ compiled << "rescue Core::Pipeline::Signals::Rejected\n"
32
+ compiled << "end\n"
33
+ end
34
+
35
+ compiled
36
+ end
28
37
 
29
- compiled << case action
30
- when Symbol
31
- "object.#{action}(...); "
38
+ # [public]
39
+ #
40
+ private def compile_action(action, object)
41
+ case action[:finalized]
42
+ when Symbol
43
+ if object.private_method_defined?(action[:finalized])
44
+ "object.send(#{action[:finalized].inspect}, ...)\n"
32
45
  else
33
- "@__finalized_actions[#{object_id}].call(...); "
46
+ "object.#{action[:finalized]}(...)\n"
34
47
  end
35
-
36
- compiled << "rescue Core::Pipeline::Signals::Rejected; end\n"
48
+ else
49
+ "@__finalized_actions__[#{action[:object_id]}][:finalized].call(...)\n"
37
50
  end
38
-
39
- compiled
40
51
  end
41
52
 
42
53
  private def finalized_actions(callable, object)
43
54
  validate_skipped_actions(callable)
44
55
  finalized_actions = build_finalized_actions(callable, object)
45
- callable.instance_variable_set(:@__finalized_actions, finalized_actions)
56
+ callable.instance_variable_set(:@__finalized_actions__, finalized_actions)
46
57
  end
47
58
 
48
59
  private def validate_skipped_actions(callable)
@@ -57,9 +68,17 @@ module Core
57
68
  ordered_actions(callable).reject { |action|
58
69
  callable.skipped.include?(action.name)
59
70
  }.map { |action|
60
- action.finalize(object)
71
+ finalized = action.finalize(object)
72
+
73
+ finalized = if action.curried?
74
+ wrap_finalized_action_for_context(finalized, action.context || object)
75
+ else
76
+ finalized
77
+ end
78
+
79
+ {object: action, finalized: finalized, object_id: finalized.object_id}
61
80
  }.each_with_object({}) { |action, lookup|
62
- lookup[action.object_id] = action
81
+ lookup[action[:object_id]] = action
63
82
  }
64
83
  end
65
84
 
@@ -113,6 +132,205 @@ module Core
113
132
 
114
133
  ordered
115
134
  end
135
+
136
+ private def wrap_finalized_action_for_context(finalized, context)
137
+ case finalized
138
+ when Symbol
139
+ wrapped_name = :"curried_#{finalized}"
140
+ method = context.instance_method(finalized)
141
+ signature = [
142
+ build_method_arguments_signature(method),
143
+ build_method_keywords_signature(method),
144
+ "&block"
145
+ ].compact.join(", ")
146
+
147
+ code = <<~CODE
148
+ def #{wrapped_name}(*args, **kwargs, &block)
149
+ self.#{finalized}(#{signature})
150
+ end
151
+ CODE
152
+
153
+ context.class_eval(code, __FILE__, __LINE__ - 1)
154
+
155
+ wrapped_name
156
+ else
157
+ if callable_accepts_keyword_arguments?(finalized)
158
+ finalized_keywords = callable_keywords(finalized)
159
+
160
+ if callable_accepts_arguments?(finalized)
161
+ argument_count = callable_arguments(finalized).count
162
+
163
+ if callable_accepts_keyword_arguments_splat?(finalized)
164
+ if callable_accepts_arguments_splat?(finalized)
165
+ if RbConfig::CONFIG["RUBY_PROGRAM_VERSION"] < "3"
166
+ proc { |*args, **kwargs, &block|
167
+ finalized.call(*args.take(argument_count), *args[argument_count..], **kwargs.slice(*finalized_keywords), **kwargs.reject { |kwarg, _| finalized_keywords.include?(kwarg) }, &block)
168
+ }
169
+ else
170
+ proc { |*args, **kwargs, &block|
171
+ finalized.call(*args.take(argument_count), *args[argument_count..], **kwargs.slice(*finalized_keywords), **kwargs.except(*finalized_keywords), &block)
172
+ }
173
+ end
174
+ elsif RbConfig::CONFIG["RUBY_PROGRAM_VERSION"] < "3"
175
+ proc { |*args, **kwargs, &block|
176
+ finalized.call(*args.take(argument_count), **kwargs.slice(*finalized_keywords), **kwargs.reject { |kwarg, _| finalized_keywords.include?(kwarg) }, &block)
177
+ }
178
+ else
179
+ proc { |*args, **kwargs, &block|
180
+ finalized.call(*args.take(argument_count), **kwargs.slice(*finalized_keywords), **kwargs.except(*finalized_keywords), &block)
181
+ }
182
+ end
183
+ elsif callable_accepts_arguments_splat?(finalized)
184
+ proc { |*args, **kwargs, &block|
185
+ finalized.call(*args.take(argument_count), *args[argument_count..], **kwargs.slice(*finalized_keywords), &block)
186
+ }
187
+ else
188
+ proc { |*args, **kwargs, &block|
189
+ finalized.call(*args.take(argument_count), **kwargs.slice(*finalized_keywords), &block)
190
+ }
191
+ end
192
+ elsif callable_accepts_keyword_arguments_splat?(finalized)
193
+ if callable_accepts_arguments_splat?(finalized)
194
+ if RbConfig::CONFIG["RUBY_PROGRAM_VERSION"] < "3"
195
+ proc { |*args, **kwargs, &block|
196
+ finalized.call(*args, **kwargs.slice(*finalized_keywords), **kwargs.reject { |kwarg, _| finalized_keywords.include?(kwarg) }, &block)
197
+ }
198
+ else
199
+ proc { |*args, **kwargs, &block|
200
+ finalized.call(*args, **kwargs.slice(*finalized_keywords), **kwargs.except(*finalized_keywords), &block)
201
+ }
202
+ end
203
+ elsif RbConfig::CONFIG["RUBY_PROGRAM_VERSION"] < "3"
204
+ proc { |*, **kwargs, &block|
205
+ finalized.call(**kwargs.slice(*finalized_keywords), **kwargs.reject { |kwarg, _| finalized_keywords.include?(kwarg) }, &block)
206
+ }
207
+ else
208
+ proc { |*, **kwargs, &block|
209
+ finalized.call(**kwargs.slice(*finalized_keywords), **kwargs.except(*finalized_keywords), &block)
210
+ }
211
+ end
212
+ elsif callable_accepts_arguments_splat?(finalized)
213
+ proc { |*args, **kwargs, &block|
214
+ finalized.call(*args, **kwargs.slice(*finalized_keywords), &block)
215
+ }
216
+ else
217
+ proc { |*, **kwargs, &block|
218
+ finalized.call(**kwargs.slice(*finalized_keywords), &block)
219
+ }
220
+ end
221
+ elsif callable_accepts_arguments?(finalized)
222
+ argument_count = callable_arguments(finalized).count
223
+
224
+ if callable_accepts_keyword_arguments_splat?(finalized)
225
+ if callable_accepts_arguments_splat?(finalized)
226
+ proc { |*args, **kwargs, &block|
227
+ finalized.call(*args.take(argument_count), *args[argument_count..], **kwargs, &block)
228
+ }
229
+ else
230
+ proc { |*args, **kwargs, &block|
231
+ finalized.call(*args.take(argument_count), **kwargs, &block)
232
+ }
233
+ end
234
+ elsif callable_accepts_arguments_splat?(finalized)
235
+ proc { |*args, **, &block|
236
+ finalized.call(*args.take(argument_count), *args[argument_count..], &block)
237
+ }
238
+ else
239
+ proc { |*args, **, &block|
240
+ finalized.call(*args.take(argument_count), &block)
241
+ }
242
+ end
243
+ elsif callable_accepts_keyword_arguments_splat?(finalized)
244
+ if callable_accepts_arguments_splat?(finalized)
245
+ proc { |*args, **kwargs, &block|
246
+ finalized.call(*args, **kwargs, &block)
247
+ }
248
+ else
249
+ proc { |*, **kwargs, &block|
250
+ finalized.call(**kwargs, &block)
251
+ }
252
+ end
253
+ elsif callable_accepts_arguments_splat?(finalized)
254
+ proc { |*args, **, &block|
255
+ finalized.call(*args, &block)
256
+ }
257
+ else
258
+ proc { |*, **, &block|
259
+ finalized.call(&block)
260
+ }
261
+ end
262
+ end
263
+ end
264
+
265
+ private def build_method_arguments_signature(method)
266
+ return if method.arity == 0
267
+
268
+ arguments = callable_arguments(method)
269
+
270
+ if arguments.any?
271
+ if callable_accepts_arguments_splat?(method)
272
+ "*args.take(#{arguments.count}), *args[#{arguments.count}..]"
273
+ else
274
+ "*args.take(#{arguments.count})"
275
+ end
276
+ elsif callable_accepts_arguments_splat?(method)
277
+ "*args"
278
+ end
279
+ end
280
+
281
+ private def build_method_keywords_signature(method)
282
+ return if method.arity == 0
283
+
284
+ keywords = callable_keywords(method)
285
+
286
+ if keywords.any?
287
+ keywords_string = keywords.map { |keyword| ":#{keyword}" }.join(", ")
288
+
289
+ if callable_accepts_keyword_arguments_splat?(method)
290
+ if RbConfig::CONFIG["RUBY_PROGRAM_VERSION"] < "3"
291
+ "**kwargs.slice(#{keywords_string}), **kwargs.reject { |kwarg, _| [#{keywords_string}].include?(kwarg) }"
292
+ else
293
+ "**kwargs.slice(#{keywords_string}), **kwargs.except(*#{keywords_string})"
294
+ end
295
+ else
296
+ "**kwargs.slice(#{keywords_string})"
297
+ end
298
+ elsif callable_accepts_keyword_arguments_splat?(method)
299
+ "**kwargs"
300
+ end
301
+ end
302
+
303
+ private def callable_accepts_arguments_splat?(callable)
304
+ callable.parameters.any? { |type, _| type == :rest }
305
+ end
306
+
307
+ private def callable_accepts_keyword_arguments_splat?(callable)
308
+ callable.parameters.any? { |type, _| type == :keyrest }
309
+ end
310
+
311
+ private def callable_accepts_arguments?(callable)
312
+ callable.parameters.any? { |type, _| type == :req || type == :opt }
313
+ end
314
+
315
+ private def callable_accepts_keyword_arguments?(callable)
316
+ callable.parameters.any? { |type, _| type == :keyreq || type == :key }
317
+ end
318
+
319
+ private def callable_arguments(callable)
320
+ callable.parameters.select { |type, _|
321
+ type == :req || type == :opt
322
+ }.map { |_, name|
323
+ name
324
+ }
325
+ end
326
+
327
+ private def callable_keywords(callable)
328
+ callable.parameters.select { |type, _|
329
+ type == :keyreq || type == :key
330
+ }.map { |_, name|
331
+ name
332
+ }
333
+ end
116
334
  end
117
335
  end
118
336
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Core
4
4
  module Pipeline
5
- VERSION = "0.1.0"
5
+ VERSION = "0.4.0"
6
6
 
7
7
  def self.version
8
8
  VERSION
data/lib/is/pipeline.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "is/async"
4
3
  require "is/extension"
5
4
  require "is/stateful"
6
5
 
@@ -28,8 +27,8 @@ module Is
28
27
  extends :definition do
29
28
  # [public] Defines a pipeline action.
30
29
  #
31
- def action(*args, before: nil, after: nil, context: nil, &block)
32
- pipeline.action(*args, before: before, after: after, context: context, &block)
30
+ def action(*args, before: nil, after: nil, context: nil, curry: false, &block)
31
+ pipeline.action(*args, before: before, after: after, context: context, curry: curry, &block)
33
32
  end
34
33
 
35
34
  # [public] Skips the given action.
@@ -63,9 +62,50 @@ module Is
63
62
  def call(...)
64
63
  @pipeline.call(self, ...)
65
64
  end
65
+
66
+ # [public] Defines a pipeline action, isolated to the instance.
67
+ #
68
+ def action(*args, before: nil, after: nil, context: nil, curry: false, &block)
69
+ pipeline.relocate(singleton_class)
70
+ pipeline.action(*args, before: before, after: after, context: context, curry: curry, &block)
71
+ end
72
+
73
+ # [public] Skips the given action, isolated to the instance.
74
+ #
75
+ def skip_action(name)
76
+ pipeline.relocate(singleton_class)
77
+ pipeline.skip(name)
78
+ end
79
+
80
+ # [public] Replaces existing actions with actions from the given pipeline, isolated to the instance.
81
+ #
82
+ def use_pipeline(other_pipeline)
83
+ pipeline.relocate(singleton_class)
84
+ pipeline.use(other_pipeline)
85
+ end
86
+
87
+ # [public] Includes actions from the given pipeline, isolated to the instance.
88
+ #
89
+ def include_pipeline(other_pipeline)
90
+ pipeline.relocate(singleton_class)
91
+ pipeline.include(other_pipeline)
92
+ end
93
+
94
+ # [public] Excludes actions from the given pipeline, isolated to the instance.
95
+ #
96
+ def exclude_pipeline(other_pipeline)
97
+ pipeline.relocate(singleton_class)
98
+ pipeline.exclude(other_pipeline)
99
+ end
66
100
  end
67
101
 
68
102
  extends :implementation, prepend: true do
103
+ def finalize
104
+ super if defined?(super)
105
+ pipeline.finalize
106
+ self
107
+ end
108
+
69
109
  # [public] Halts the execution of the pipeline, setting the pipeline's current value to the given object.
70
110
  #
71
111
  private def halt(value = nil)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: core-pipeline
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bryan Powell
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-07-15 00:00:00.000000000 Z
11
+ date: 2021-11-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: core-extension
@@ -89,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
89
89
  - !ruby/object:Gem::Version
90
90
  version: '0'
91
91
  requirements: []
92
- rubygems_version: 3.2.15
92
+ rubygems_version: 3.2.22
93
93
  signing_key:
94
94
  specification_version: 4
95
95
  summary: Turns Ruby objects into pipelines.