cuprum 0.10.0.rc.0 → 1.0.0.rc.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +52 -2
- data/CODE_OF_CONDUCT.md +132 -0
- data/DEVELOPMENT.md +4 -21
- data/README.md +776 -89
- data/lib/cuprum/built_in/identity_command.rb +6 -4
- data/lib/cuprum/built_in/identity_operation.rb +4 -2
- data/lib/cuprum/built_in/null_command.rb +5 -3
- data/lib/cuprum/built_in/null_operation.rb +4 -2
- data/lib/cuprum/built_in.rb +3 -1
- data/lib/cuprum/command.rb +29 -58
- data/lib/cuprum/command_factory.rb +7 -5
- data/lib/cuprum/currying/curried_command.rb +11 -4
- data/lib/cuprum/currying.rb +3 -2
- data/lib/cuprum/error.rb +44 -10
- data/lib/cuprum/errors/command_not_implemented.rb +6 -3
- data/lib/cuprum/errors/operation_not_called.rb +6 -6
- data/lib/cuprum/errors/uncaught_exception.rb +55 -0
- data/lib/cuprum/errors.rb +2 -0
- data/lib/cuprum/exception_handling.rb +50 -0
- data/lib/cuprum/matcher.rb +90 -0
- data/lib/cuprum/matcher_list.rb +150 -0
- data/lib/cuprum/matching/match_clause.rb +65 -0
- data/lib/cuprum/matching.rb +232 -0
- data/lib/cuprum/middleware.rb +210 -0
- data/lib/cuprum/operation.rb +17 -15
- data/lib/cuprum/result.rb +1 -3
- data/lib/cuprum/rspec/be_a_result.rb +10 -1
- data/lib/cuprum/rspec/be_a_result_matcher.rb +2 -4
- data/lib/cuprum/rspec/be_callable.rb +14 -0
- data/lib/cuprum/steps.rb +47 -89
- data/lib/cuprum/utils/instance_spy.rb +28 -28
- data/lib/cuprum/utils.rb +3 -1
- data/lib/cuprum/version.rb +13 -10
- data/lib/cuprum.rb +12 -7
- metadata +31 -19
- data/lib/cuprum/chaining.rb +0 -441
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cuprum
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0.rc.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rob "Merlin" Smith
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-09-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sleeping_king_studios-tools
|
@@ -16,70 +16,70 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0
|
19
|
+
version: '1.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0
|
26
|
+
version: '1.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rspec
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '3.
|
33
|
+
version: '3.10'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '3.
|
40
|
+
version: '3.10'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec-sleeping_king_studios
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '2.
|
47
|
+
version: '2.5'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '2.
|
54
|
+
version: '2.5'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rubocop
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: 1.10.0
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: 1.10.0
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rubocop-rspec
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '1
|
75
|
+
version: '2.1'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '1
|
82
|
+
version: '2.1'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: simplecov
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,9 +94,11 @@ dependencies:
|
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0.15'
|
97
|
-
description:
|
98
|
-
|
99
|
-
|
97
|
+
description: |-
|
98
|
+
An opinionated implementation of the Command pattern for Ruby applications.
|
99
|
+
Cuprum wraps your business logic in a consistent, object-oriented interface
|
100
|
+
and features status and error management, composability and control flow
|
101
|
+
management.
|
100
102
|
email:
|
101
103
|
- merlin@sleepingkingstudios.com
|
102
104
|
executables: []
|
@@ -104,6 +106,7 @@ extensions: []
|
|
104
106
|
extra_rdoc_files: []
|
105
107
|
files:
|
106
108
|
- CHANGELOG.md
|
109
|
+
- CODE_OF_CONDUCT.md
|
107
110
|
- DEVELOPMENT.md
|
108
111
|
- LICENSE
|
109
112
|
- README.md
|
@@ -113,7 +116,6 @@ files:
|
|
113
116
|
- lib/cuprum/built_in/identity_operation.rb
|
114
117
|
- lib/cuprum/built_in/null_command.rb
|
115
118
|
- lib/cuprum/built_in/null_operation.rb
|
116
|
-
- lib/cuprum/chaining.rb
|
117
119
|
- lib/cuprum/command.rb
|
118
120
|
- lib/cuprum/command_factory.rb
|
119
121
|
- lib/cuprum/currying.rb
|
@@ -122,6 +124,13 @@ files:
|
|
122
124
|
- lib/cuprum/errors.rb
|
123
125
|
- lib/cuprum/errors/command_not_implemented.rb
|
124
126
|
- lib/cuprum/errors/operation_not_called.rb
|
127
|
+
- lib/cuprum/errors/uncaught_exception.rb
|
128
|
+
- lib/cuprum/exception_handling.rb
|
129
|
+
- lib/cuprum/matcher.rb
|
130
|
+
- lib/cuprum/matcher_list.rb
|
131
|
+
- lib/cuprum/matching.rb
|
132
|
+
- lib/cuprum/matching/match_clause.rb
|
133
|
+
- lib/cuprum/middleware.rb
|
125
134
|
- lib/cuprum/operation.rb
|
126
135
|
- lib/cuprum/processing.rb
|
127
136
|
- lib/cuprum/result.rb
|
@@ -129,6 +138,7 @@ files:
|
|
129
138
|
- lib/cuprum/rspec.rb
|
130
139
|
- lib/cuprum/rspec/be_a_result.rb
|
131
140
|
- lib/cuprum/rspec/be_a_result_matcher.rb
|
141
|
+
- lib/cuprum/rspec/be_callable.rb
|
132
142
|
- lib/cuprum/steps.rb
|
133
143
|
- lib/cuprum/utils.rb
|
134
144
|
- lib/cuprum/utils/instance_spy.rb
|
@@ -136,7 +146,9 @@ files:
|
|
136
146
|
homepage: http://sleepingkingstudios.com
|
137
147
|
licenses:
|
138
148
|
- MIT
|
139
|
-
metadata:
|
149
|
+
metadata:
|
150
|
+
bug_tracker_uri: https://github.com/sleepingkingstudios/cuprum/issues
|
151
|
+
source_code_uri: https://github.com/sleepingkingstudios/cuprum
|
140
152
|
post_install_message:
|
141
153
|
rdoc_options: []
|
142
154
|
require_paths:
|
@@ -145,14 +157,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
145
157
|
requirements:
|
146
158
|
- - ">="
|
147
159
|
- !ruby/object:Gem::Version
|
148
|
-
version:
|
160
|
+
version: 2.5.0
|
149
161
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
150
162
|
requirements:
|
151
163
|
- - ">"
|
152
164
|
- !ruby/object:Gem::Version
|
153
165
|
version: 1.3.1
|
154
166
|
requirements: []
|
155
|
-
rubygems_version: 3.1.
|
167
|
+
rubygems_version: 3.1.4
|
156
168
|
signing_key:
|
157
169
|
specification_version: 4
|
158
170
|
summary: An opinionated implementation of the Command pattern.
|
data/lib/cuprum/chaining.rb
DELETED
@@ -1,441 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'cuprum'
|
4
|
-
|
5
|
-
module Cuprum
|
6
|
-
# Mixin to implement command chaining functionality for a command class.
|
7
|
-
# Chaining commands allows you to define complex logic by composing it from
|
8
|
-
# simpler commands, including branching logic and error handling.
|
9
|
-
#
|
10
|
-
# @example Chaining Commands
|
11
|
-
# # By chaining commands together with the #chain instance method, we set up
|
12
|
-
# # a series of commands to run in sequence. Each chained command is passed
|
13
|
-
# # the value of the previous command.
|
14
|
-
#
|
15
|
-
# class GenerateUrlCommand
|
16
|
-
# include Cuprum::Chaining
|
17
|
-
# include Cuprum::Processing
|
18
|
-
#
|
19
|
-
# private
|
20
|
-
#
|
21
|
-
# # Acts as a pipeline, taking a value (the title of the given post) and
|
22
|
-
# # calling the underscore, URL safe, and prepend date commands. By
|
23
|
-
# # passing parameters to PrependDateCommand, we can customize the command
|
24
|
-
# # in the pipeline to the current context (in this case, the Post).
|
25
|
-
# def process post
|
26
|
-
# UnderscoreCommand.new.
|
27
|
-
# chain(UrlSafeCommand.new).
|
28
|
-
# chain(PrependDateCommand.new(post.created_at)).
|
29
|
-
# call(post.title)
|
30
|
-
# end
|
31
|
-
# end
|
32
|
-
#
|
33
|
-
# title = 'Greetings, programs!'
|
34
|
-
# date = '1982-07-09'
|
35
|
-
# post = Post.new(:title => title, :created_at => date)
|
36
|
-
# url = GenerateUrlCommand.new.call(post).value
|
37
|
-
# #=> '1982_07_09_greetings_programs'
|
38
|
-
#
|
39
|
-
# title = 'Plasma-based Einhanders in Popular Media'
|
40
|
-
# date = '1977-05-25'
|
41
|
-
# post = Post.new(:title => title, :created_at => date)
|
42
|
-
# url = GenerateUrlCommand.new.call(post).value
|
43
|
-
# #=> '1977_05_25_plasma_based_einhanders_in_popular_media'
|
44
|
-
#
|
45
|
-
# @example Conditional Chaining
|
46
|
-
# # Commands can be conditionally chained based on the success or failure of
|
47
|
-
# # the previous command using the on: keyword. If the command is chained
|
48
|
-
# # using on: :success, it will only be called if the result is passing.
|
49
|
-
# # If the command is chained using on: :failure, it will only be called if
|
50
|
-
# # the command is failing. This can be used to perform error handling.
|
51
|
-
#
|
52
|
-
# class CreateTaggingCommand
|
53
|
-
# include Cuprum::Chaining
|
54
|
-
# include Cuprum::Processing
|
55
|
-
#
|
56
|
-
# private
|
57
|
-
#
|
58
|
-
# def create_tag
|
59
|
-
# Command.new do |tag_name|
|
60
|
-
# tag = Tag.new(name: tag_name)
|
61
|
-
#
|
62
|
-
# return tag if tag.save
|
63
|
-
#
|
64
|
-
# Cuprum::Result.new(error: tag.errors)
|
65
|
-
# end
|
66
|
-
# end
|
67
|
-
#
|
68
|
-
# def create_tagging(taggable)
|
69
|
-
# Command.new do |tag|
|
70
|
-
# tagging = tag.build_tagging(taggable)
|
71
|
-
#
|
72
|
-
# return tagging if tagging.save
|
73
|
-
#
|
74
|
-
# Cuprum::Result.new(error: tagging.errors)
|
75
|
-
# end
|
76
|
-
# end
|
77
|
-
#
|
78
|
-
# def find_tag
|
79
|
-
# Command.new do |tag_name|
|
80
|
-
# tag = Tag.where(name: tag_name).first
|
81
|
-
#
|
82
|
-
# tag || Cuprum::Result.new(error: 'tag not found')
|
83
|
-
# end
|
84
|
-
# end
|
85
|
-
#
|
86
|
-
# # Tries to find the tag with the given name. If that fails, creates a
|
87
|
-
# # new tag with the given name. If the tag is found, or if the new tag is
|
88
|
-
# # successfully created, then creates a tagging using the tag. If the tag
|
89
|
-
# # is not found and cannot be created, then the tagging is not created
|
90
|
-
# # and the result of the CreateTaggingCommand is a failure with the
|
91
|
-
# # appropriate error messages.
|
92
|
-
# def process(taggable, tag_name)
|
93
|
-
# find_tag
|
94
|
-
# .chain(on: :failure) do
|
95
|
-
# # If the finding the tag fails, this step is called, returning a
|
96
|
-
# # result with a newly created tag.
|
97
|
-
# create_tag.call(tag_name)
|
98
|
-
# end
|
99
|
-
# .chain(:on => :success) do |tag|
|
100
|
-
# # Finally, the tag has been either found or created, so we can
|
101
|
-
# # create the tagging relation.
|
102
|
-
# tag.create_tagging(taggable)
|
103
|
-
# end
|
104
|
-
# .call(tag_name)
|
105
|
-
# end
|
106
|
-
# end
|
107
|
-
#
|
108
|
-
# post = Post.create(:title => 'Tagging Example')
|
109
|
-
# example_tag = Tag.create(:name => 'Example Tag')
|
110
|
-
#
|
111
|
-
# result = CreateTaggingCommand.new.call(post, 'Example Tag')
|
112
|
-
# result.success? #=> true
|
113
|
-
# result.error #=> nil
|
114
|
-
# result.value #=> an instance of Tagging
|
115
|
-
# post.tags.map(&:name)
|
116
|
-
# #=> ['Example Tag']
|
117
|
-
#
|
118
|
-
# result = CreateTaggingCommand.new.call(post, 'Another Tag')
|
119
|
-
# result.success? #=> true
|
120
|
-
# result.error #=> nil
|
121
|
-
# result.value #=> an instance of Tagging
|
122
|
-
# post.tags.map(&:name)
|
123
|
-
# #=> ['Example Tag', 'Another Tag']
|
124
|
-
#
|
125
|
-
# result = CreateTaggingCommand.new.call(post, 'An Invalid Tag Name')
|
126
|
-
# result.success? #=> false
|
127
|
-
# result.error #=> [{ tag: { name: ['is invalid'] }}]
|
128
|
-
# post.tags.map(&:name)
|
129
|
-
# #=> ['Example Tag', 'Another Tag']
|
130
|
-
#
|
131
|
-
# @example Yield Result and Tap Result
|
132
|
-
# # The #yield_result method allows for advanced control over a step in the
|
133
|
-
# # command chain. The block will be yielded the result at that point in the
|
134
|
-
# # chain, and will wrap the returned value in a result to the next chained
|
135
|
-
# # command (or return it directly if the returned value is a result).
|
136
|
-
# #
|
137
|
-
# # The #tap_result method inserts arbitrary code into the command chain
|
138
|
-
# # without interrupting it. The block will be yielded the result at that
|
139
|
-
# # point in the chain and will pass that same result to the next chained
|
140
|
-
# # command after executing the block. The return value of the block is
|
141
|
-
# # ignored.
|
142
|
-
#
|
143
|
-
# class UpdatePostCommand
|
144
|
-
# include Cuprum::Chaining
|
145
|
-
# include Cuprum::Processing
|
146
|
-
#
|
147
|
-
# private
|
148
|
-
#
|
149
|
-
# def process id, attributes
|
150
|
-
# # First, find the referenced post.
|
151
|
-
# Find.new(Post).call(id).
|
152
|
-
# yield_result(:on => :failure) do |result|
|
153
|
-
# redirect_to posts_path
|
154
|
-
# end.
|
155
|
-
# yield_result(on: :success) do |result|
|
156
|
-
# # Assign our attributes and save the post.
|
157
|
-
# UpdateAttributes.new.call(result.value, attributes)
|
158
|
-
# end.
|
159
|
-
# tap_result(:on => :success) do |result|
|
160
|
-
# # Create our tags, but still return the result of our update.
|
161
|
-
# attributes[:tags].each do |tag_name|
|
162
|
-
# CreateTaggingCommand.new.call(result.value, tag_name)
|
163
|
-
# end
|
164
|
-
# end.
|
165
|
-
# tap_result(:on => :always) do |result|
|
166
|
-
# # Chaining :on => :always ensures that the command will be run,
|
167
|
-
# # even if the previous result is failing.
|
168
|
-
# if result.failure?
|
169
|
-
# log_errors(
|
170
|
-
# :command => UpdatePostCommand,
|
171
|
-
# :error => result.error
|
172
|
-
# )
|
173
|
-
# end
|
174
|
-
# end
|
175
|
-
# end
|
176
|
-
# end
|
177
|
-
#
|
178
|
-
# @example Protected Chaining Methods
|
179
|
-
# # Using the protected chaining methods #chain!, #tap_result!, and
|
180
|
-
# # #yield_result!, you can create a command class that composes other
|
181
|
-
# # commands.
|
182
|
-
#
|
183
|
-
# # We subclass the build command, which will be executed first.
|
184
|
-
# class CreateCommentCommand < BuildCommentCommand
|
185
|
-
# include Cuprum::Chaining
|
186
|
-
# include Cuprum::Processing
|
187
|
-
#
|
188
|
-
# def initialize
|
189
|
-
# # After the build step is run, we validate the comment.
|
190
|
-
# chain!(ValidateCommentCommand.new)
|
191
|
-
#
|
192
|
-
# # If the validation passes, we then save the comment.
|
193
|
-
# chain!(SaveCommentCommand.new, on: :success)
|
194
|
-
# end
|
195
|
-
# end
|
196
|
-
#
|
197
|
-
# @see Cuprum::Command
|
198
|
-
module Chaining
|
199
|
-
# (see Cuprum::Processing#call)
|
200
|
-
def call(*args, **kwargs, &block)
|
201
|
-
yield_chain(super)
|
202
|
-
end
|
203
|
-
|
204
|
-
# Creates a copy of the first command, and then chains the given command or
|
205
|
-
# block to execute after the first command's implementation. When #call is
|
206
|
-
# executed, each chained command will be called with the previous result
|
207
|
-
# value, and its result property will be set to the previous result. The
|
208
|
-
# return value will be wrapped in a result and returned or yielded to the
|
209
|
-
# next block.
|
210
|
-
#
|
211
|
-
# @return [Cuprum::Chaining] A copy of the command, with the chained
|
212
|
-
# command.
|
213
|
-
#
|
214
|
-
# @see #yield_result
|
215
|
-
#
|
216
|
-
# @overload chain(command, on: nil)
|
217
|
-
# @param command [Cuprum::Command] The command to chain.
|
218
|
-
#
|
219
|
-
# @param on [Symbol] Sets a condition on when the chained block can run,
|
220
|
-
# based on the previous result. Valid values are :success, :failure, and
|
221
|
-
# :always. If the value is :success, the block will be called only if
|
222
|
-
# the previous result succeeded. If the value is :failure, the block
|
223
|
-
# will be called only if the previous result failed. If the value is
|
224
|
-
# :always, the block will be called regardless of the previous result
|
225
|
-
# status. If no value is given, the command will run whether the
|
226
|
-
# previous command was a success or a failure.
|
227
|
-
#
|
228
|
-
# @overload chain(on: nil) { |value| }
|
229
|
-
# Creates an anonymous command from the given block. The command will be
|
230
|
-
# passed the value of the previous result.
|
231
|
-
#
|
232
|
-
# @param on [Symbol] Sets a condition on when the chained block can run,
|
233
|
-
# based on the previous result. Valid values are :success, :failure, and
|
234
|
-
# :always. If the value is :success, the block will be called only if
|
235
|
-
# the previous result succeeded. If the value is :failure, the block
|
236
|
-
# will be called only if the previous result failed. If the value is
|
237
|
-
# :always, the block will be called regardless of the previous result
|
238
|
-
# status. If no value is given, the command will run whether the
|
239
|
-
# previous command was a success or a failure.
|
240
|
-
#
|
241
|
-
# @yieldparam value [Object] The value of the previous result.
|
242
|
-
def chain(command = nil, on: nil, &block)
|
243
|
-
clone.chain!(command, on: on, &block)
|
244
|
-
end
|
245
|
-
|
246
|
-
# As #yield_result, but always returns the previous result when the block is
|
247
|
-
# called. The return value of the block is discarded.
|
248
|
-
#
|
249
|
-
# @param (see #yield_result)
|
250
|
-
#
|
251
|
-
# @yieldparam result [Cuprum::Result] The #result of the previous command.
|
252
|
-
#
|
253
|
-
# @return (see #yield_result)
|
254
|
-
#
|
255
|
-
# @see #yield_result
|
256
|
-
def tap_result(on: nil, &block)
|
257
|
-
clone.tap_result!(on: on, &block)
|
258
|
-
end
|
259
|
-
|
260
|
-
# Creates a copy of the command, and then chains the block to execute after
|
261
|
-
# the command implementation. When #call is executed, each chained block
|
262
|
-
# will be yielded the previous result, and the return value wrapped in a
|
263
|
-
# result and returned or yielded to the next block.
|
264
|
-
#
|
265
|
-
# @param on [Symbol] Sets a condition on when the chained block can run,
|
266
|
-
# based on the previous result. Valid values are :success, :failure, and
|
267
|
-
# :always. If the value is :success, the block will be called only if the
|
268
|
-
# previous result succeeded. If the value is :failure, the block will be
|
269
|
-
# called only if the previous result failed. If the value is :always, the
|
270
|
-
# block will be called regardless of the previous result status. If no
|
271
|
-
# value is given, the command will run whether the previous command was a
|
272
|
-
# success or a failure.
|
273
|
-
#
|
274
|
-
# @yieldparam result [Cuprum::Result] The #result of the previous command.
|
275
|
-
#
|
276
|
-
# @return [Cuprum::Chaining] A copy of the command, with the chained block.
|
277
|
-
#
|
278
|
-
# @see #tap_result
|
279
|
-
def yield_result(on: nil, &block)
|
280
|
-
clone.yield_result!(on: on, &block)
|
281
|
-
end
|
282
|
-
|
283
|
-
protected
|
284
|
-
|
285
|
-
# rubocop:disable Metrics/MethodLength
|
286
|
-
|
287
|
-
# @!visibility public
|
288
|
-
#
|
289
|
-
# As #chain, but modifies the current command instead of creating a clone.
|
290
|
-
# This is a protected method, and is meant to be called by the command to be
|
291
|
-
# chained, such as during #initialize.
|
292
|
-
#
|
293
|
-
# @return [Cuprum::Chaining] The current command.
|
294
|
-
#
|
295
|
-
# @see #chain
|
296
|
-
#
|
297
|
-
# @overload chain!(command, on: nil)
|
298
|
-
# @param command [Cuprum::Command] The command to chain.
|
299
|
-
#
|
300
|
-
# @param on [Symbol] Sets a condition on when the chained block can run,
|
301
|
-
# based on the previous result. Valid values are :success, :failure, and
|
302
|
-
# :always. If the value is :success, the block will be called only if
|
303
|
-
# the previous result succeeded. If the value is :failure, the block
|
304
|
-
# will be called only if the previous result failed. If the value is
|
305
|
-
# :always, the block will be called regardless of the previous result
|
306
|
-
# status. If no value is given, the command will run whether the
|
307
|
-
# previous command was a success or a failure.
|
308
|
-
#
|
309
|
-
# @overload chain!(on: nil) { |value| }
|
310
|
-
# Creates an anonymous command from the given block. The command will be
|
311
|
-
# passed the value of the previous result.
|
312
|
-
#
|
313
|
-
# @param on [Symbol] Sets a condition on when the chained block can run,
|
314
|
-
# based on the previous result. Valid values are :success, :failure, and
|
315
|
-
# :always. If the value is :success, the block will be called only if
|
316
|
-
# the previous result succeeded. If the value is :failure, the block
|
317
|
-
# will be called only if the previous result failed. If the value is
|
318
|
-
# :always, the block will be called regardless of the previous result
|
319
|
-
# status. If no value is given, the command will run whether the
|
320
|
-
# previous command was a success or a failure.
|
321
|
-
#
|
322
|
-
# @yieldparam value [Object] The value of the previous result.
|
323
|
-
def chain!(command = nil, on: nil, &block)
|
324
|
-
SleepingKingStudios::Tools::CoreTools.deprecate(
|
325
|
-
"#{self.class}#chain",
|
326
|
-
message: 'Use the #step method to compose commands.'
|
327
|
-
)
|
328
|
-
|
329
|
-
command ||= Cuprum::Command.new(&block)
|
330
|
-
|
331
|
-
chained_procs <<
|
332
|
-
{
|
333
|
-
proc: chain_command(command),
|
334
|
-
on: on
|
335
|
-
} # end hash
|
336
|
-
|
337
|
-
self
|
338
|
-
end
|
339
|
-
# rubocop:enable Metrics/MethodLength
|
340
|
-
|
341
|
-
def chained_procs
|
342
|
-
@chained_procs ||= []
|
343
|
-
end
|
344
|
-
|
345
|
-
# rubocop:disable Metrics/MethodLength
|
346
|
-
|
347
|
-
# @!visibility public
|
348
|
-
#
|
349
|
-
# As #tap_result, but modifies the current command instead of creating a
|
350
|
-
# clone. This is a protected method, and is meant to be called by the
|
351
|
-
# command to be chained, such as during #initialize.
|
352
|
-
#
|
353
|
-
# @param (see #tap_result)
|
354
|
-
#
|
355
|
-
# @yieldparam result [Cuprum::Result] The #result of the previous command.
|
356
|
-
#
|
357
|
-
# @return (see #tap_result)
|
358
|
-
#
|
359
|
-
# @see #tap_result
|
360
|
-
def tap_result!(on: nil, &block)
|
361
|
-
SleepingKingStudios::Tools::CoreTools.deprecate(
|
362
|
-
"#{self.class}#tap_result",
|
363
|
-
message: 'Use the #step method to compose commands.'
|
364
|
-
)
|
365
|
-
|
366
|
-
tapped = ->(result) { result.tap { block.call(result) } }
|
367
|
-
|
368
|
-
chained_procs <<
|
369
|
-
{
|
370
|
-
proc: tapped,
|
371
|
-
on: on
|
372
|
-
} # end hash
|
373
|
-
|
374
|
-
self
|
375
|
-
end
|
376
|
-
# rubocop:enable Metrics/MethodLength
|
377
|
-
|
378
|
-
# @!visibility public
|
379
|
-
#
|
380
|
-
# As #yield_result, but modifies the current command instead of creating a
|
381
|
-
# clone. This is a protected method, and is meant to be called by the
|
382
|
-
# command to be chained, such as during #initialize.
|
383
|
-
#
|
384
|
-
# @param (see #yield_result)
|
385
|
-
#
|
386
|
-
# @yieldparam result [Cuprum::Result] The #result of the previous command.
|
387
|
-
#
|
388
|
-
# @return (see #yield_result)
|
389
|
-
#
|
390
|
-
# @see #yield_result
|
391
|
-
def yield_result!(on: nil, &block)
|
392
|
-
SleepingKingStudios::Tools::CoreTools.deprecate(
|
393
|
-
"#{self.class}#yield_result",
|
394
|
-
message: 'Use the #step method to compose commands.'
|
395
|
-
)
|
396
|
-
|
397
|
-
chained_procs <<
|
398
|
-
{
|
399
|
-
proc: block,
|
400
|
-
on: on
|
401
|
-
} # end hash
|
402
|
-
|
403
|
-
self
|
404
|
-
end
|
405
|
-
|
406
|
-
private
|
407
|
-
|
408
|
-
def chain_command(command)
|
409
|
-
if command.arity.zero?
|
410
|
-
->(_result) { command.call }
|
411
|
-
else
|
412
|
-
->(result) { command.call(result.value) }
|
413
|
-
end
|
414
|
-
end
|
415
|
-
|
416
|
-
def skip_chained_proc?(last_result, on:)
|
417
|
-
return false if on == :always
|
418
|
-
|
419
|
-
case on
|
420
|
-
when :success
|
421
|
-
!last_result.success?
|
422
|
-
when :failure
|
423
|
-
!last_result.failure?
|
424
|
-
end
|
425
|
-
end
|
426
|
-
|
427
|
-
def yield_chain(first_result)
|
428
|
-
chained_procs.reduce(first_result) do |result, hsh|
|
429
|
-
next result if skip_chained_proc?(result, on: hsh[:on])
|
430
|
-
|
431
|
-
value = hsh.fetch(:proc).call(result)
|
432
|
-
|
433
|
-
if value_is_result?(value)
|
434
|
-
value.to_cuprum_result
|
435
|
-
else
|
436
|
-
build_result(value: value)
|
437
|
-
end
|
438
|
-
end
|
439
|
-
end
|
440
|
-
end
|
441
|
-
end
|