cuprum 0.8.0 → 0.9.0.beta.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +41 -0
- data/DEVELOPMENT.md +14 -10
- data/README.md +197 -337
- data/lib/cuprum.rb +0 -25
- data/lib/cuprum/built_in/identity_command.rb +4 -4
- data/lib/cuprum/chaining.rb +119 -149
- data/lib/cuprum/command.rb +16 -14
- data/lib/cuprum/error.rb +37 -0
- data/lib/cuprum/errors/command_not_implemented.rb +35 -0
- data/lib/cuprum/errors/operation_not_called.rb +35 -0
- data/lib/cuprum/operation.rb +30 -27
- data/lib/cuprum/processing.rb +47 -80
- data/lib/cuprum/result.rb +52 -127
- data/lib/cuprum/rspec.rb +8 -0
- data/lib/cuprum/rspec/be_a_result.rb +19 -0
- data/lib/cuprum/rspec/be_a_result_matcher.rb +271 -0
- data/lib/cuprum/version.rb +3 -3
- metadata +11 -9
- data/lib/cuprum/errors/process_not_implemented_error.rb +0 -14
- data/lib/cuprum/result_helpers.rb +0 -113
- data/lib/cuprum/utils/result_not_empty_warning.rb +0 -72
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 92d562710780dafcd20a5114fea623303dde6c22f7fbb2588eae26fd10adb419
|
4
|
+
data.tar.gz: 5a0c7d60b320673d3816b63b7480d84f4fa062bd52efb3b6ccca6de5237778a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 147d1581adb612e620a629429a7207f84a7e15a6224da5045ef30a9f270aa72ae2b9a3332221054ee902a205c1d60224d31eec998450d45bb68b335b10d5c255
|
7
|
+
data.tar.gz: 2db46aea35210874659ae9e69df64574d1f0e89e600937f6b20d45c56222c656477e663b722069b89fbe3d97d663189e7edb79776d72a67dcca3e8bdb6bd7607
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,46 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 0.9.0
|
4
|
+
|
5
|
+
The "'Tis Not Too Late To Seek A Newer World" Update
|
6
|
+
|
7
|
+
Major refactoring of Command processing and the Result object. This update is **not** backwards compatible.
|
8
|
+
|
9
|
+
### Commands
|
10
|
+
|
11
|
+
Removed the `#success` and `#failure` chaining helpers.
|
12
|
+
|
13
|
+
Permanently removed the deprecated ResultHelpers mixin.
|
14
|
+
|
15
|
+
### Errors
|
16
|
+
|
17
|
+
Added `Cuprum::Error`, which encapsulates the failure state of a result. It is *recommended*, but not required, that when creating a failing Result, the `:error` property be set to an instance of `Cuprum::Error`.
|
18
|
+
|
19
|
+
### Results
|
20
|
+
|
21
|
+
Results are now nominally immutable objects. All mutator methods have been removed, including `#failure!`, `#success!`, and `#update`. The `#empty?` predicate has also been removed.
|
22
|
+
|
23
|
+
Updated the constructor to take the following keyword arguments: `:value`, `:error`, and `:status`.
|
24
|
+
|
25
|
+
- The status can now be overridden on a new Result by passing in the `:status`.
|
26
|
+
- Resolves an issue when attempting to instantiate a result with a Hash value.
|
27
|
+
- *Note:* The value must now be passed in as a keyword.
|
28
|
+
- *Note:* The `:errors` keyword has been renamed to `:error`.
|
29
|
+
|
30
|
+
Removed the `:halted` status.
|
31
|
+
|
32
|
+
### Other Changes
|
33
|
+
|
34
|
+
Removed the `Cuprum#warn` functionality.
|
35
|
+
|
36
|
+
### Upgrade Notes
|
37
|
+
|
38
|
+
Anywhere a new `Cuprum::Result` is created directly, update the arguments to match the new `value:` and `error:` keywords.
|
39
|
+
|
40
|
+
Anywhere the `#result` is referenced inside a command, instead return the desired value directly, or return a result with the desired error.
|
41
|
+
|
42
|
+
Anywhere a command is chained with the `#success` or `#failure` shorthand, use the full `chain(on: :success)` or `chain(on: :failure)` format.
|
43
|
+
|
3
44
|
## 0.8.0
|
4
45
|
|
5
46
|
The "We Have The Technology" Update.
|
data/DEVELOPMENT.md
CHANGED
@@ -2,22 +2,26 @@
|
|
2
2
|
|
3
3
|
## Version 0.9.0
|
4
4
|
|
5
|
-
The "
|
6
|
-
|
7
|
-
### Actions
|
8
|
-
|
9
|
-
#### LifecycleHooks
|
10
|
-
|
11
|
-
- :before, :after hooks
|
12
|
-
- NOT included in Command by default
|
5
|
+
The "'Tis Not Too Late To Seek A Newer World" Update
|
13
6
|
|
14
7
|
## Version 0.10.0
|
15
8
|
|
16
|
-
|
9
|
+
The "One Small Step" Update
|
17
10
|
|
18
11
|
### Commands
|
19
12
|
|
20
|
-
-
|
13
|
+
- Implement #<<, #>> composition methods.
|
14
|
+
- Calls commands in order passing values.
|
15
|
+
- Return Result early on Failure (or not Success), otherwise final Result.
|
16
|
+
- Implement #step method (used in #process).
|
17
|
+
- Called with command (block? method?) that returns a Result.
|
18
|
+
- Raise (and catch) exception on non-success Result (test custom status?)
|
19
|
+
- Otherwise return Result#value.
|
20
|
+
|
21
|
+
### Matcher
|
22
|
+
|
23
|
+
- Handle success(), failure(), failure(SomeError) cases.
|
24
|
+
- Custom matcher to handle additional cases - halted, pending, etc?
|
21
25
|
|
22
26
|
## Version 1.0.0
|
23
27
|
|
data/README.md
CHANGED
@@ -6,7 +6,8 @@ It defines the following concepts:
|
|
6
6
|
|
7
7
|
- [Commands](#label-Commands) - A function-like object that responds to `#call` and returns a `Result`.
|
8
8
|
- [Operations](#label-Operations) - A stateful `Command` that wraps and delegates to its most recent `Result`.
|
9
|
-
- [Results](#label-Results) -
|
9
|
+
- [Results](#label-Results) - An immutable data object with a status (either `:success` or `:failure`), and either a `#value` or an `#error` object.
|
10
|
+
- [Errors](#label-Errors) - Encapsulates a failure state of a command.
|
10
11
|
|
11
12
|
## About
|
12
13
|
|
@@ -41,7 +42,7 @@ Documentation is generated using [YARD](https://yardoc.org/), and can be generat
|
|
41
42
|
|
42
43
|
### License
|
43
44
|
|
44
|
-
Copyright (c)
|
45
|
+
Copyright (c) 2019 Rob Smith
|
45
46
|
|
46
47
|
Cuprum is released under the [MIT License](https://opensource.org/licenses/MIT).
|
47
48
|
|
@@ -63,9 +64,9 @@ Hi, I'm Rob Smith, a Ruby Engineer and the developer of this library. I use thes
|
|
63
64
|
|
64
65
|
require 'cuprum'
|
65
66
|
|
66
|
-
Commands are the core feature of Cuprum. In a nutshell, each Cuprum::Command is a functional object that encapsulates a business logic operation. A Command provides a consistent interface and tracking of result value and status. This minimizes boilerplate and allows for interchangeability between different implementations or strategies for managing your data and processes.
|
67
|
+
Commands are the core feature of Cuprum. In a nutshell, each `Cuprum::Command` is a functional object that encapsulates a business logic operation. A Command provides a consistent interface and tracking of result value and status. This minimizes boilerplate and allows for interchangeability between different implementations or strategies for managing your data and processes.
|
67
68
|
|
68
|
-
Each Command implements a `#call` method that wraps your defined business logic and returns an instance of Cuprum::Result
|
69
|
+
Each Command implements a `#call` method that wraps your defined business logic and returns an instance of `Cuprum::Result`. The result has a status (either `:success` or `:failure`), and may have a `#value` and/or an `#error` object. For more details about Cuprum::Result, [see below](#label-Results).
|
69
70
|
|
70
71
|
[Class Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum%2FCommand)
|
71
72
|
|
@@ -77,12 +78,13 @@ The recommended way to define commands is to create a subclass of `Cuprum::Comma
|
|
77
78
|
class BuildBookCommand < Cuprum::Command
|
78
79
|
def process attributes
|
79
80
|
Book.new(attributes)
|
80
|
-
end
|
81
|
-
end
|
81
|
+
end
|
82
|
+
end
|
82
83
|
|
83
84
|
command = BuildPostCommand.new
|
84
|
-
result = command.call(:
|
85
|
-
result.class
|
85
|
+
result = command.call(title: 'The Hobbit')
|
86
|
+
result.class #=> Cuprum::Result
|
87
|
+
result.success? #=> true
|
86
88
|
|
87
89
|
book = result.value
|
88
90
|
book.class #=> Book
|
@@ -97,23 +99,30 @@ Because a command is just a Ruby object, we can also pass values to the construc
|
|
97
99
|
class SaveBookCommand < Cuprum::Command
|
98
100
|
def initialize repository
|
99
101
|
@repository = repository
|
100
|
-
end
|
102
|
+
end
|
101
103
|
|
102
104
|
def process book
|
103
|
-
@repository.persist(book)
|
104
|
-
|
105
|
-
|
105
|
+
if @repository.persist(book)
|
106
|
+
success(book)
|
107
|
+
else
|
108
|
+
failure('unable to save book')
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
106
112
|
|
107
113
|
books = [
|
108
|
-
Book.new(:
|
109
|
-
Book.new(:
|
110
|
-
Book.new(:
|
114
|
+
Book.new(title: 'The Fellowship of the Ring'),
|
115
|
+
Book.new(title: 'The Two Towers'),
|
116
|
+
Book.new(title: 'The Return of the King')
|
111
117
|
]
|
112
118
|
command = SaveBookCommand.new(books_repository)
|
113
119
|
books.each { |book| command.call(book) }
|
114
120
|
```
|
115
121
|
|
116
|
-
Here, we are
|
122
|
+
Here, we are defining a command that might fail - maybe the database is unavailable, or there's a constraint that is violated by the inserted attributes. If the call to `#persist` succeeds, we're returning a Result with a status of `:success` and the value set to the persisted book.
|
123
|
+
Conversely, if the call to `#persist` fails, we're returning a Result with a status of `:failure` and a custom error message. Since the `#process` method returns a Result, it is returned directly by `#call`.
|
124
|
+
|
125
|
+
Note also that we are reusing the same command three times, rather than creating a new save command for each book. Each book is persisted to the `books_repository`. This is also an example of how using commands can simplify code - notice that nothing about the `SaveBookCommand` is specific to the `Book` model. Thus, we could refactor this into a generic `SaveModelCommand`.
|
117
126
|
|
118
127
|
A command can also be defined by passing block to `Cuprum::Command.new`.
|
119
128
|
|
@@ -136,9 +145,9 @@ Commands defined using `Cuprum::Command.new` are quick to use, but more difficul
|
|
136
145
|
|
137
146
|
Calling the `#call` method on a `Cuprum::Command` instance will always return an instance of `Cuprum::Result`. The result's `#value` property is determined by the object returned by the `#process` method (if the command is defined as a class) or the block (if the command is defined by passing a block to `Cuprum::Command.new`).
|
138
147
|
|
139
|
-
The `#value` depends on whether or not the returned object is a result or is compatible with the result interface. Specifically, any object that responds to the
|
148
|
+
The `#value` depends on whether or not the returned object is a result or is compatible with the result interface. Specifically, any object that responds to the method `#to_cuprum_result` is considered to be a result.
|
140
149
|
|
141
|
-
If the object returned is **not** a result, then the `#value` of the returned result is set to the object.
|
150
|
+
If the object returned by `#process` is **not** a result, then the `#value` of the returned result is set to the object.
|
142
151
|
|
143
152
|
```ruby
|
144
153
|
command = Cuprum::Command.new { 'Greetings, programs!' }
|
@@ -147,46 +156,18 @@ result.class #=> Cuprum::Result
|
|
147
156
|
result.value #=> 'Greetings, programs!'
|
148
157
|
```
|
149
158
|
|
150
|
-
If the object returned
|
159
|
+
If the object returned by `#process` is a result object, then result is returned directly.
|
151
160
|
|
152
161
|
```ruby
|
153
|
-
command = Cuprum::Command.new {
|
162
|
+
command = Cuprum::Command.new { Cuprum::Result.new(value: 'Greetings, programs!') }
|
154
163
|
result = command.call
|
155
|
-
result.class #=> Cuprum::Result
|
156
|
-
result.value #=> nil
|
157
|
-
result.success? #=> false
|
158
|
-
```
|
159
|
-
|
160
|
-
If the object returned is another result or compatible object, then `#call` will call the `#to_result` method on the result and return the resulting object.
|
161
|
-
|
162
|
-
```ruby
|
163
|
-
command = Cuprum::Command.new { |value| Cuprum::Result.new(value) }
|
164
|
-
result = command.call('Greetings, starfighter!')
|
165
164
|
result.class #=> Cuprum::Result
|
166
|
-
result.value #=> 'Greetings,
|
167
|
-
```
|
168
|
-
|
169
|
-
In some cases, returning a result directly will discard information on the command's own result object. When this occurs, Cuprum will display a warning.
|
170
|
-
|
171
|
-
```ruby
|
172
|
-
command =
|
173
|
-
Cuprum::Command.new do
|
174
|
-
result.errors << 'Oops! We are throwing away this result.'
|
175
|
-
|
176
|
-
Cuprum::Result.new
|
177
|
-
end
|
178
|
-
|
179
|
-
#=> This calls Kernel#warn with a warning message.
|
180
|
-
result = command.call
|
181
|
-
result.class #=> Cuprum::Result
|
182
|
-
result.value #=> nil
|
183
|
-
result.success? #=> true
|
184
|
-
result.errors #=> []
|
165
|
+
result.value #=> 'Greetings, programs!'
|
185
166
|
```
|
186
167
|
|
187
168
|
#### Success, Failure, and Errors
|
188
169
|
|
189
|
-
|
170
|
+
Each Result has a status, either `:success` or `:failure`. A Result will have a status of `:failure` when it was created with an error object. Otherwise, a Result will have a status of `:success`. Returning a failing Result from a Command indicates that something went wrong while executing the Command.
|
190
171
|
|
191
172
|
```ruby
|
192
173
|
class PublishBookCommand < Cuprum::Command
|
@@ -194,40 +175,38 @@ class PublishBookCommand < Cuprum::Command
|
|
194
175
|
|
195
176
|
def process book
|
196
177
|
if book.cover.nil?
|
197
|
-
|
198
|
-
|
199
|
-
return
|
200
|
-
end # if
|
178
|
+
return Cuprum::Result.new(error: 'This book does not have a cover.')
|
179
|
+
end
|
201
180
|
|
202
181
|
book.published = true
|
203
182
|
|
204
183
|
book
|
205
|
-
end
|
206
|
-
end
|
184
|
+
end
|
185
|
+
end
|
207
186
|
```
|
208
187
|
|
209
|
-
In addition, the result object defines `#success?` and `#failure?` predicates.
|
188
|
+
In addition, the result object defines `#success?` and `#failure?` predicates.
|
210
189
|
|
211
190
|
```ruby
|
212
|
-
book = Book.new(:
|
191
|
+
book = Book.new(title: 'The Silmarillion', cover: Cover.new)
|
213
192
|
book.published? #=> false
|
214
193
|
|
215
194
|
result = PublishBookCommand.new.call(book)
|
216
|
-
result.
|
195
|
+
result.error #=> nil
|
217
196
|
result.success? #=> true
|
218
197
|
result.failure? #=> false
|
219
198
|
result.value #=> book
|
220
199
|
book.published? #=> true
|
221
200
|
```
|
222
201
|
|
223
|
-
If the result does have
|
202
|
+
If the result does have an error, `#success?` will return false and `#failure?` will return true.
|
224
203
|
|
225
204
|
```ruby
|
226
|
-
book = Book.new(:
|
205
|
+
book = Book.new(title: 'The Silmarillion', cover: nil)
|
227
206
|
book.published? #=> false
|
228
207
|
|
229
208
|
result = PublishBookCommand.new.call(book)
|
230
|
-
result.
|
209
|
+
result.error #=> 'This book does not have a cover.'
|
231
210
|
result.success? #=> false
|
232
211
|
result.failure? #=> true
|
233
212
|
result.value #=> book
|
@@ -248,7 +227,7 @@ add_command = Cuprum::Command.new do |addend, i|
|
|
248
227
|
addend.times { i = increment_command(i).value }
|
249
228
|
|
250
229
|
i
|
251
|
-
end
|
230
|
+
end
|
252
231
|
|
253
232
|
add_command.call(1, 1).value #=> 2
|
254
233
|
add_command.call(1, 2).value #=> 3
|
@@ -274,8 +253,12 @@ class AddCommand < Cuprum::Command
|
|
274
253
|
|
275
254
|
private
|
276
255
|
|
256
|
+
def increment_command
|
257
|
+
@increment_command ||= IncrementCommand.new
|
258
|
+
end
|
259
|
+
|
277
260
|
def process i
|
278
|
-
addend.times { i =
|
261
|
+
addend.times { i = increment_command.call(i).value }
|
279
262
|
|
280
263
|
i
|
281
264
|
end
|
@@ -335,9 +318,7 @@ second_command.call #=> Outputs 'First command!' then 'Second command!'.
|
|
335
318
|
first_command.call #=> Outputs 'First command!' to STDOUT.
|
336
319
|
```
|
337
320
|
|
338
|
-
When a chained command is called, the original command is called with whatever parameters are passed in to the `#call` method, and the command executes the `#process` method as normal
|
339
|
-
|
340
|
-
First, the next command is called. If the next command does not take any arguments, it is not passed any arguments. If the next command takes one or more arguments, it is passed the `#value` of that previous result.
|
321
|
+
When a chained command is called, the original command is called with whatever parameters are passed in to the `#call` method, and the command executes the `#process` method as normal. Rather than returning the result, however, the next command in the chain is called. If the next command does not take any arguments, it is not passed any arguments. If the next command takes one or more arguments, it is passed the `#value` of that previous result. When the final command in the chain is called, that result is returned.
|
341
322
|
|
342
323
|
```ruby
|
343
324
|
double_command = Cuprum::Command.new { |i| 2 * i }
|
@@ -360,87 +341,38 @@ result.class #=> Cuprum::Result
|
|
360
341
|
result.value #=> 25
|
361
342
|
```
|
362
343
|
|
363
|
-
Second, the previous result is set as the result of the next command (before it is evaluated). This makes it available to the next command during execution as the `#result` method, and makes available the value, errors, and status of the previous command (and avoids unnecessary object allocation). The value of the result will be updated to reflect the return value of the next command execution.
|
364
|
-
|
365
|
-
```ruby
|
366
|
-
validate_command =
|
367
|
-
Cuprum::Command.new do |object|
|
368
|
-
result.errors << 'Object is invalid!' unless object.valid?
|
369
|
-
|
370
|
-
object
|
371
|
-
end
|
372
|
-
persist_command =
|
373
|
-
Cuprum::Command.new do |object|
|
374
|
-
object.save if result.success?
|
375
|
-
|
376
|
-
object
|
377
|
-
end
|
378
|
-
chained_command = validate_command.chain(persist_command)
|
379
|
-
|
380
|
-
# First, validate_command is called with a valid object. This creates a result
|
381
|
-
# with no errors and whose value is the valid object.
|
382
|
-
#
|
383
|
-
# Then, persist_command is called with the object, and its result is assigned to
|
384
|
-
# the previous result. Since there are no errors on the result, the object is
|
385
|
-
# saved. Finally, the value of the result is set to the object, and the result
|
386
|
-
# is returned.
|
387
|
-
result = chained_command.call(a_valid_object) #=> Saves the object.
|
388
|
-
result.value #=> a_valid_object
|
389
|
-
result.errors #=> []
|
390
|
-
a_valid_object.persisted? #=> true
|
391
|
-
|
392
|
-
# First, validate_command is called with an invalid object. This creates a
|
393
|
-
# result whose value is the invalid object, and with errors 'Object is
|
394
|
-
# invalid!'.
|
395
|
-
#
|
396
|
-
# Then, persist_command is called with the object, and its result is assigned to
|
397
|
-
# the previous result. Since the result has an error, the object is not saved.
|
398
|
-
# Finally, the value of the result is set to the object, and the result
|
399
|
-
# is returned.
|
400
|
-
result = chained_command.call(an_invalid_object) #=> Does not save the object.
|
401
|
-
result.value #=> an_invalid_object
|
402
|
-
result.errors #=> ['Object is invalid!']
|
403
|
-
an_invalid_object.persisted? #=> false
|
404
|
-
```
|
405
|
-
|
406
344
|
#### Conditional Chaining
|
407
345
|
|
408
|
-
The `#chain` method can be passed an optional
|
409
|
-
|
410
|
-
If the `:on` keyword is omitted, the chained command will always be executed after the previous command unless the result is halted (see [Halting A Command Chain](#label-Commands))
|
346
|
+
The `#chain` method can be passed an optional `on: value` keyword. This keyword determines whether or not the chained command will execute, based on the previous result status. Possible values are `:success`, `:failure`, `:always`, or `nil`. The default value is `nil`.
|
411
347
|
|
412
|
-
If the command is chained with
|
348
|
+
If the command is chained with `on: :always`, or if the `:on` keyword is omitted, the chained command will always be executed after the previous command.
|
413
349
|
|
414
|
-
If the command is chained with
|
350
|
+
If the command is chained with `on: :success`, then the chained command will only execute if the previous result is passing, e.g. the `#success?` method returns true. A result is passing if there is no `#error`, or if the status is set to `:success`.
|
415
351
|
|
416
|
-
If the command is chained with
|
352
|
+
If the command is chained with `on: :failure`, then the chained command will only execute if the previous result is failing, e.g. the `#success?` method returns false. A result is failing if there is an `#error`, or if the status is set to `:failure`.
|
417
353
|
|
418
354
|
```ruby
|
419
355
|
find_command =
|
420
356
|
Cuprum::Command.new do |attributes|
|
421
|
-
book = Book.where(:
|
357
|
+
book = Book.where(id: attributes[:id]).first
|
422
358
|
|
423
|
-
|
359
|
+
return book if book
|
424
360
|
|
425
|
-
|
361
|
+
Cuprum::Result.new(error: 'Book not found')
|
426
362
|
end
|
427
363
|
create_command =
|
428
364
|
Cuprum::Command.new do |attributes|
|
429
365
|
book = Book.new(attributes)
|
430
366
|
|
431
|
-
if book.save
|
432
|
-
result.success!
|
433
|
-
else
|
434
|
-
book.errors.full_messages.each { |message| result.errors << message }
|
435
|
-
end
|
367
|
+
return book if book.save
|
436
368
|
|
437
|
-
book
|
369
|
+
Cuprum::Result.new(error: book.errors.full_messages)
|
438
370
|
end
|
439
371
|
|
440
|
-
find_or_create_command = find_command.chain(create_command, :
|
372
|
+
find_or_create_command = find_command.chain(create_command, on: :failure)
|
441
373
|
|
442
374
|
# With a book that exists in the database, the find_command is called and
|
443
|
-
# returns a result with no
|
375
|
+
# returns a result with no error and a value of the found book. The
|
444
376
|
# create_command is not called.
|
445
377
|
hsh = { id: 0, title: 'Journey to the West' }
|
446
378
|
result = find_or_create_command.call(hsh)
|
@@ -448,19 +380,18 @@ book = result.value
|
|
448
380
|
book.id #=> 0
|
449
381
|
book.title #=> 'Journey to the West'
|
450
382
|
result.success? #=> true
|
451
|
-
result.
|
383
|
+
result.error #=> nil
|
452
384
|
|
453
385
|
# With a book that does not exist but with valid attributes, the find command
|
454
386
|
# returns a failing result with a value of nil. The create_command is called and
|
455
|
-
# creates a new book with the attributes, returning a passing result
|
456
|
-
# preserving the errors.
|
387
|
+
# creates a new book with the attributes, returning a passing result.
|
457
388
|
hsh = { id: 1, title: 'The Ramayana' }
|
458
389
|
result = find_or_create_command.call(hsh)
|
459
390
|
book = result.value
|
460
391
|
book.id #=> 1
|
461
392
|
book.title #=> 'The Ramayana'
|
462
393
|
result.success? #=> true
|
463
|
-
result.
|
394
|
+
result.error #=> nil
|
464
395
|
|
465
396
|
# With a book that does not exist and with invalid attributes, the find command
|
466
397
|
# returns a failing result with a value of nil. The create_command is called and
|
@@ -472,36 +403,7 @@ book = result.value
|
|
472
403
|
book.id #=> 2
|
473
404
|
book.title #=> nil
|
474
405
|
result.success? #=> false
|
475
|
-
result.
|
476
|
-
```
|
477
|
-
|
478
|
-
The `#success` method can be used as shorthand for `chain(command, :on => :success)`. Likewise, the `#failure` method can be used in place of `chain(command, :on => :failure)`.
|
479
|
-
|
480
|
-
#### Halting A Command Chain
|
481
|
-
|
482
|
-
If the `#halt` method is called as part of a Command block or `#process` method, the command chain is halted. Any subsequent chained commands will not be called unless they were chained with the `:on => :always` option. This allows you to terminate a Command chain early without having to raise and rescue an exception.
|
483
|
-
|
484
|
-
```ruby
|
485
|
-
double_command = Cuprum::Command.new { |i| 2 * i }
|
486
|
-
halt_command = Cuprum::Command.new { |value| value.tap { result.halt! } }
|
487
|
-
add_one_command = Cuprum::Command.new { |i| i + 1 }
|
488
|
-
|
489
|
-
chained_command =
|
490
|
-
double_command
|
491
|
-
.chain(halt_command)
|
492
|
-
.chain(add_one_command)
|
493
|
-
.chain(:on => :always) { |count| "There are #{count} lights!" }
|
494
|
-
|
495
|
-
# First, double_command is called with 2, returning a result with no errors and
|
496
|
-
# a value of 4. Then, halt_command is called, which marks the result as halted.
|
497
|
-
# Because the result is now halted, the add_one_command is not called. Finally,
|
498
|
-
# the last command is called (even though the result is halted, the command is
|
499
|
-
# chained :on => :always), which returns a result with the string value. The
|
500
|
-
# result is passing, but is still halted.
|
501
|
-
result = chained_command.call(2)
|
502
|
-
result.value #=> 'There are 4 lights!'
|
503
|
-
result.success? #=> true
|
504
|
-
result.halted? #=> true
|
406
|
+
result.error #=> ["Title can't be blank"]
|
505
407
|
```
|
506
408
|
|
507
409
|
### Advanced Chaining
|
@@ -515,9 +417,7 @@ The `#tap_result` method allows you to insert arbitrary code into a command chai
|
|
515
417
|
```ruby
|
516
418
|
command =
|
517
419
|
Cuprum::Command.new do
|
518
|
-
|
519
|
-
|
520
|
-
'Example value'
|
420
|
+
Cuprum::Result.new(value: 'Example value', error: 'Example error')
|
521
421
|
end
|
522
422
|
chained_command =
|
523
423
|
command
|
@@ -530,32 +430,32 @@ result = chained_command.call
|
|
530
430
|
result.class #=> Cuprum::Result
|
531
431
|
result.value #=> 'Example value'
|
532
432
|
result.success? #=> false
|
533
|
-
result.
|
433
|
+
result.error #=> 'Example error'
|
534
434
|
```
|
535
435
|
|
536
|
-
Like `#chain`, `#tap_result` can be given an
|
436
|
+
Like `#chain`, `#tap_result` can be given an `on: value` keyword.
|
537
437
|
|
538
438
|
```ruby
|
539
439
|
find_book_command =
|
540
440
|
Cuprum::Command.new do |book_id|
|
541
|
-
book = Book.where(:
|
441
|
+
book = Book.where(id: book_id).first
|
542
442
|
|
543
|
-
|
443
|
+
return book if book
|
544
444
|
|
545
|
-
book
|
445
|
+
Cuprum::Result.new(error: "Unable to find book with id #{book_id}")
|
546
446
|
end
|
547
447
|
|
548
448
|
chained_command =
|
549
449
|
find_book_command
|
550
|
-
.tap_result(:
|
551
|
-
render :show, :
|
450
|
+
.tap_result(on: :success) do |result|
|
451
|
+
render :show, locals: { book: result.value }
|
552
452
|
end
|
553
|
-
.tap_result(:
|
453
|
+
.tap_result(on: :failure) do
|
554
454
|
redirect_to books_path
|
555
455
|
end
|
556
456
|
|
557
457
|
# Calls find_book_command with the id, which queries for the book and returns a
|
558
|
-
# result with a value of the book and no
|
458
|
+
# result with a value of the book and no error. Then, the first tap_result
|
559
459
|
# block is evaluated, calling the render method and passing it the book via the
|
560
460
|
# result.value method. Because the result is passing, the next block is skipped.
|
561
461
|
# Finally, the result of find_book_command is returned unchanged.
|
@@ -563,7 +463,7 @@ result = chained_command.call(valid_id)
|
|
563
463
|
result.class #=> Cuprum::Result
|
564
464
|
result.value #=> an instance of Book
|
565
465
|
result.success? #=> true
|
566
|
-
result.
|
466
|
+
result.error #=> nil
|
567
467
|
|
568
468
|
# Calls find_book_command with the id, which queries for the book and returns a
|
569
469
|
# result with a value of nil and the error message. Because the result is
|
@@ -574,14 +474,14 @@ result = chained_command.call(invalid_id)
|
|
574
474
|
result.class #=> Cuprum::Result
|
575
475
|
result.value #=> nil
|
576
476
|
result.success? #=> false
|
577
|
-
result.
|
477
|
+
result.error #=> ['Unable to find book with id invalid_id']
|
578
478
|
```
|
579
479
|
|
580
480
|
#### Yield Result
|
581
481
|
|
582
482
|
The `#yield_result` method offers advanced control over a chained command step. The method takes a block and yields the previous result. If the object returned by the block is not a result, a new result is created with a value equal to the returned object. In either case, the result is returned and passed to the next command, or returned by `#call` if `#tap_result` is the last item in the chain.
|
583
483
|
|
584
|
-
Unlike `#chain`, the block in `#yield_result` yields the previous result, not the previous value.
|
484
|
+
Unlike `#chain`, the block in `#yield_result` yields the previous result, not the previous value.
|
585
485
|
|
586
486
|
```ruby
|
587
487
|
chained_command =
|
@@ -589,9 +489,7 @@ chained_command =
|
|
589
489
|
'Example value'
|
590
490
|
end
|
591
491
|
.yield_result do |result|
|
592
|
-
|
593
|
-
|
594
|
-
result
|
492
|
+
Cuprum::Result.new(error: 'Example error')
|
595
493
|
end
|
596
494
|
.yield_result do |result|
|
597
495
|
"The last result was a #{result.success? ? 'success' : 'failure'}."
|
@@ -599,54 +497,22 @@ chained_command =
|
|
599
497
|
|
600
498
|
# The first command creates a passing result with a value of 'Example value'.
|
601
499
|
#
|
602
|
-
# This is passed to the first yield_result block, which
|
603
|
-
#
|
604
|
-
#
|
605
|
-
# item in the chain.
|
500
|
+
# This is passed to the first yield_result block, which creates a new result
|
501
|
+
# with the same value and the string 'Example error' as the error object. It is
|
502
|
+
# then passed to the next command in the chain.
|
606
503
|
#
|
607
504
|
# Finally, the second yield_result block is called, which checks the status of
|
608
|
-
# the passed result. Since the
|
505
|
+
# the passed result. Since the final block does not return the previous result,
|
609
506
|
# the previous result is discarded and a new result is created with the string
|
610
507
|
# value starting with 'The last result was ...'.
|
611
508
|
result = chained_command.call
|
612
509
|
result.class #=> Cuprum::Result
|
613
510
|
result.value #=> 'The last result was a failure.'
|
614
511
|
result.success? #=> true
|
615
|
-
result.
|
512
|
+
result.error #=> nil
|
616
513
|
```
|
617
514
|
|
618
|
-
Like `#chain`, `#yield_result` can be given an
|
619
|
-
|
620
|
-
```ruby
|
621
|
-
# The Collatz conjecture in mathematics concerns a sequence of numbers defined
|
622
|
-
# as follows. Start with any positive integer. If the number is even, then
|
623
|
-
# divide the number by two. If the number is odd, multiply by three and add one.
|
624
|
-
# These steps are repeated until the value is one or the numbers loop.
|
625
|
-
step_command =
|
626
|
-
Cuprum::Command.new do |i|
|
627
|
-
result.failure! unless i.even?
|
628
|
-
|
629
|
-
i
|
630
|
-
end
|
631
|
-
.yield_result(:on => :success) { |result| result.value / 2 }
|
632
|
-
.yield_result(:on => :failure) { |result| 1 + 3 * result.value }
|
633
|
-
|
634
|
-
# Because the value is even, the first command returns a passing result with a
|
635
|
-
# value of 8. The first yield_result block is then called with that result,
|
636
|
-
# returning a new result with a value of 4. The result is passing, so the second
|
637
|
-
# yield_result block is skipped and the result is returned.
|
638
|
-
result = collatz_command.call(8)
|
639
|
-
result.value #=> 4
|
640
|
-
result.success? #=> true
|
641
|
-
|
642
|
-
# Because the value is odd, the first command returns a failing result with a
|
643
|
-
# value of 5. Because the result is failing, the first yield_result block is
|
644
|
-
# skipped. The second yield_result block is then called with the result,
|
645
|
-
# returning a new (passing) result with a value of 16.
|
646
|
-
result = collatz_command.call(5)
|
647
|
-
result.value #=> 16
|
648
|
-
result.success? #=> true
|
649
|
-
```
|
515
|
+
Like `#chain`, `#yield_result` can be given an `on: value` keyword.
|
650
516
|
|
651
517
|
Under the hood, both `#chain` and `#tap_result` are implemented on top of `#yield_result`.
|
652
518
|
|
@@ -677,14 +543,14 @@ result = CreateCommentCommand.new.call({ user_id: '12345', body: body })
|
|
677
543
|
|
678
544
|
result.value #=> an instance of Comment with the given user_id and body.
|
679
545
|
result.success? #=> true
|
680
|
-
Comment.count #=> 1
|
546
|
+
Comment.count #=> 1 - the comment was added to the database
|
681
547
|
|
682
548
|
result = CreateCommentCommand.new.call({ user_id: nil, body: body })
|
683
549
|
|
684
550
|
result.value #=> an instance of Comment with the given user_id and body.
|
685
551
|
result.success? #=> false
|
686
|
-
result.
|
687
|
-
Comment.count #=> 1
|
552
|
+
result.error #=> ["User id can't be blank"]
|
553
|
+
Comment.count #=> 1 - the comment was not added to the database
|
688
554
|
```
|
689
555
|
|
690
556
|
### Results
|
@@ -693,36 +559,115 @@ Comment.count #=> 1; the comment was not added to the database
|
|
693
559
|
|
694
560
|
[Class Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum%2FResult)
|
695
561
|
|
696
|
-
A Cuprum::Result is a data object that encapsulates the result of calling a Cuprum command. Each result has a `#value`, an `#
|
562
|
+
A `Cuprum::Result` is a data object that encapsulates the result of calling a Cuprum command. Each result has a `#value`, an `#error` object (defaults to `nil`), and a `#status` (either `:success` or `:failure`, and accessible via the `#success?` and `#failure?` predicates).
|
563
|
+
|
564
|
+
```ruby
|
565
|
+
result = Cuprum::Result.new
|
566
|
+
|
567
|
+
result.value #=> nil
|
568
|
+
result.error #=> nil
|
569
|
+
result.status #=> :success
|
570
|
+
result.success? #=> true
|
571
|
+
result.failure? #=> true
|
572
|
+
```
|
573
|
+
|
574
|
+
Creating a result with a value stores the value.
|
697
575
|
|
698
576
|
```ruby
|
699
577
|
value = 'A result value'.freeze
|
700
|
-
result = Cuprum::Result.new(value)
|
578
|
+
result = Cuprum::Result.new(value: value)
|
701
579
|
|
702
580
|
result.value #=> 'A result value'
|
703
|
-
result.
|
581
|
+
result.error #=> nil
|
582
|
+
result.status #=> :success
|
704
583
|
result.success? #=> true
|
705
584
|
result.failure? #=> false
|
706
|
-
result.halted? #=> false
|
707
585
|
```
|
708
586
|
|
709
|
-
|
587
|
+
Creating a Result with an error stores the error and sets the status to `:failure`.
|
588
|
+
|
589
|
+
```ruby
|
590
|
+
error = Cuprum::Error.new(message: "I'm sorry, something went wrong.")
|
591
|
+
result = Cuprum::Result.new(error: error)
|
592
|
+
result.value #=> nil
|
593
|
+
result.error #=> Error with message "I'm sorry, something went wrong."
|
594
|
+
result.status #=> :failure
|
595
|
+
result.success? #=> false
|
596
|
+
result.failure? #=> true
|
597
|
+
```
|
598
|
+
|
599
|
+
Although using a `Cuprum::Error` instance as the `:error` is recommended, it is not required. You can use a custom error object, or just a string message.
|
710
600
|
|
711
601
|
```ruby
|
712
|
-
result.
|
602
|
+
result = Cuprum::Result.new(error: "I'm sorry, something went wrong.")
|
603
|
+
result.value #=> nil
|
604
|
+
result.error #=> "I'm sorry, something went wrong."
|
605
|
+
result.status #=> :failure
|
713
606
|
result.success? #=> false
|
714
607
|
result.failure? #=> true
|
715
608
|
```
|
716
609
|
|
717
|
-
|
610
|
+
Finally, the status can be overridden via the `:status` keyword.
|
718
611
|
|
719
612
|
```ruby
|
720
|
-
result.
|
721
|
-
result.
|
613
|
+
result = Cuprum::Result.new(status: :failure)
|
614
|
+
result.error #=> nil
|
615
|
+
result.status #=> :failure
|
616
|
+
result.success? #=> false
|
617
|
+
result.failure? #=> true
|
618
|
+
|
619
|
+
error = Cuprum::Error.new(message: "I'm sorry, something went wrong.")
|
620
|
+
result = Cuprum::Result.new(error: error, status: :success)
|
621
|
+
result.error #=> Error with message "I'm sorry, something went wrong."
|
622
|
+
result.status #=> :success
|
722
623
|
result.success? #=> true
|
723
624
|
result.failure? #=> false
|
724
625
|
```
|
725
626
|
|
627
|
+
### Errors
|
628
|
+
|
629
|
+
require 'cuprum/error'
|
630
|
+
|
631
|
+
[Class Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum%2FError)
|
632
|
+
|
633
|
+
A `Cuprum::Error` encapsulates a specific failure state of a Command. Each Error has a `#message` property, which defaults to nil.
|
634
|
+
|
635
|
+
```ruby
|
636
|
+
error = Cuprum::Error.new
|
637
|
+
error.message => # nil
|
638
|
+
|
639
|
+
error = Cuprum::Error.new(message: 'Something went wrong.')
|
640
|
+
error.message => # 'Something went wrong.'
|
641
|
+
```
|
642
|
+
|
643
|
+
Each application should define its own failure states as errors. For example, a typical web application might define the following errors:
|
644
|
+
|
645
|
+
```ruby
|
646
|
+
class NotFoundError < Cuprum::Error
|
647
|
+
def initialize(resource:, resource_id:)
|
648
|
+
@resource = resource
|
649
|
+
@resource_id = resource_id
|
650
|
+
|
651
|
+
super(message: "#{resource} not found with id #{resource_id}")
|
652
|
+
end
|
653
|
+
|
654
|
+
attr_reader :resource, :resource_id
|
655
|
+
end
|
656
|
+
|
657
|
+
class ValidationError < Cuprum::Error
|
658
|
+
def initialize(resource:, errors:)
|
659
|
+
@resource = resource
|
660
|
+
@errors = errors
|
661
|
+
|
662
|
+
super(message: "#{resource} was invalid")
|
663
|
+
end
|
664
|
+
|
665
|
+
attr_reader :resource, :errors
|
666
|
+
end
|
667
|
+
```
|
668
|
+
|
669
|
+
It is optional but recommended to use a `Cuprum::Error` when returning a failed result from a command.
|
670
|
+
|
726
671
|
### Operations
|
727
672
|
|
728
673
|
require 'cuprum'
|
@@ -737,8 +682,8 @@ These two features allow developers to simplify logic around calling and using t
|
|
737
682
|
class CreateBookOperation < Cuprum::Operation
|
738
683
|
def process
|
739
684
|
# Implementation here.
|
740
|
-
end
|
741
|
-
end
|
685
|
+
end
|
686
|
+
end
|
742
687
|
|
743
688
|
# Defining a controller action using an operation.
|
744
689
|
def create
|
@@ -750,13 +695,13 @@ def create
|
|
750
695
|
@book = operation.value
|
751
696
|
|
752
697
|
render :new
|
753
|
-
end
|
754
|
-
end
|
698
|
+
end
|
699
|
+
end
|
755
700
|
```
|
756
701
|
|
757
702
|
Like a Command, an Operation can be defined directly by passing an implementation block to the constructor or by creating a subclass that overwrites the #process method.
|
758
703
|
|
759
|
-
An operation inherits the `#call` method from Cuprum::Command (see above), and delegates the `#value`, `#
|
704
|
+
An operation inherits the `#call` method from Cuprum::Command (see above), and delegates the `#value`, `#error`, `#success?`, and `#failure` methods to the most recent result. If the operation has not been called, these methods will return default values.
|
760
705
|
|
761
706
|
#### The Operation Mixin
|
762
707
|
|
@@ -764,13 +709,6 @@ An operation inherits the `#call` method from Cuprum::Command (see above), and d
|
|
764
709
|
|
765
710
|
The implementation of `Cuprum::Operation` is defined by the `Cuprum::Operation::Mixin` module, which provides the methods defined above. Any command class or instance can be converted to an operation by including (for a class) or extending (for an instance) the operation mixin.
|
766
711
|
|
767
|
-
Finally, the result can be halted using the `#halt` method, which indicates that further chained commands should not be executed.
|
768
|
-
|
769
|
-
```ruby
|
770
|
-
result.halt!
|
771
|
-
result.halted? #=> true
|
772
|
-
```
|
773
|
-
|
774
712
|
### Command Factories
|
775
713
|
|
776
714
|
[Class Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum%2FCommandFactory)
|
@@ -898,15 +836,15 @@ class PublishedBooksCommand < Cuprum::Command
|
|
898
836
|
end
|
899
837
|
|
900
838
|
class BookFactory < Cuprum::CommandFactory
|
901
|
-
command :published do
|
902
|
-
PublishedBooksCommand.new(books_collection)
|
903
|
-
end
|
904
|
-
|
905
839
|
def initialize(books)
|
906
840
|
@books_collection = books
|
907
841
|
end
|
908
842
|
|
909
843
|
attr_reader :books_collection
|
844
|
+
|
845
|
+
command :published do
|
846
|
+
PublishedBooksCommand.new(books_collection)
|
847
|
+
end
|
910
848
|
end
|
911
849
|
```
|
912
850
|
|
@@ -1207,16 +1145,6 @@ Returns a new instance of Cuprum::Command. If a block is given, the `#call` meth
|
|
1207
1145
|
|
1208
1146
|
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Command#initialize-instance_method)
|
1209
1147
|
|
1210
|
-
#### `#build_errors`
|
1211
|
-
|
1212
|
-
*(Private Method)*
|
1213
|
-
|
1214
|
-
build_errors() #=> Array
|
1215
|
-
|
1216
|
-
Generates an empty errors object. When the command is called, the result will have its `#errors` property initialized to the value returned by `#build_errors`. By default, this is an array. If you want to use a custom errors object type, override this method in a subclass.
|
1217
|
-
|
1218
|
-
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Command#build_errors-instance_method)
|
1219
|
-
|
1220
1148
|
#### `#call`
|
1221
1149
|
|
1222
1150
|
call(*arguments, **keywords) { ... } #=> Cuprum::Result
|
@@ -1235,9 +1163,9 @@ Registers a command or block to run after the current command, or after the last
|
|
1235
1163
|
|
1236
1164
|
The command will be passed the `#value` of the previous command result as its parameter, and the result of the chained command will be returned (or passed to the next chained command, if any).
|
1237
1165
|
|
1238
|
-
The block will be passed the #result of the previous command as its parameter.
|
1166
|
+
The block will be passed the #result of the previous command as its parameter.
|
1239
1167
|
|
1240
|
-
If the block returns a Cuprum::Result (or an object responding to
|
1168
|
+
If the block returns a Cuprum::Result (or an object responding to `#to_cuprum_result`), the block result will be returned (or passed to the next chained command, if any). If the block returns any other value (including `nil`), the `#result` of the previous command will be returned or passed to the next command.
|
1241
1169
|
|
1242
1170
|
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Command#chain-instance_method)
|
1243
1171
|
|
@@ -1253,29 +1181,13 @@ As `#chain`, but modifies the current command instead of creating a clone.
|
|
1253
1181
|
|
1254
1182
|
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Command#chain!-instance_method)
|
1255
1183
|
|
1256
|
-
#### `#else`
|
1257
|
-
|
1258
|
-
else(command) #=> Cuprum::Command
|
1259
|
-
|
1260
|
-
Shorthand for `command.chain(:on => :failure)`. Registers a command or block to run after the current command. The chained command will only run if the previous command was unsuccessfully run.
|
1261
|
-
|
1262
|
-
The command will be passed the `#value` of the previous command result as its parameter, and the result of the chained command will be returned (or passed to the next chained command, if any).
|
1263
|
-
|
1264
|
-
else() { |result| ... } #=> Cuprum::Command
|
1265
|
-
|
1266
|
-
The block will be passed the #result of the previous command as its parameter. If your use case depends on the status of the previous command or on any errors generated, use the block form of #chain.
|
1267
|
-
|
1268
|
-
If the block returns a Cuprum::Result (or an object responding to #value and #success?), the block result will be returned (or passed to the next chained command, if any). If the block returns any other value (including nil), the #result of the previous command will be returned or passed to the next command.
|
1269
|
-
|
1270
|
-
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Command#else-instance_method)
|
1271
|
-
|
1272
1184
|
#### `#tap_result`
|
1273
1185
|
|
1274
1186
|
tap_result(on: nil) { |previous_result| } #=> Cuprum::Result
|
1275
1187
|
|
1276
1188
|
Creates a copy of the command, and then chains the block to execute after the command implementation. When #call is executed, each chained block will be yielded the previous result, and the previous result returned or yielded to the next block. The return value of the block is discarded.
|
1277
1189
|
|
1278
|
-
If the `on` parameter is
|
1190
|
+
If the `on` parameter is set to `:success`, the block will be called if the last result is successful. If the `on` parameter is set to `:failure`, the block will be called if the last result is failing. Finally, if the `on` parameter is set to `:always` or to `nil`, the block will always be called.
|
1279
1191
|
|
1280
1192
|
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Command#tap_result-instance_method)
|
1281
1193
|
|
@@ -1289,29 +1201,13 @@ As `#tap_result`, but modifies the current command instead of creating a clone.
|
|
1289
1201
|
|
1290
1202
|
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Command#tap_result!-instance_method)
|
1291
1203
|
|
1292
|
-
#### `#then`
|
1293
|
-
|
1294
|
-
then(command) #=> Cuprum::Command
|
1295
|
-
|
1296
|
-
Shorthand for `command.chain(:on => :success)`. Registers a command or block to run after the current command. The chained command will only run if the previous command was successfully run.
|
1297
|
-
|
1298
|
-
The command will be passed the `#value` of the previous command result as its parameter, and the result of the chained command will be returned (or passed to the next chained command, if any).
|
1299
|
-
|
1300
|
-
then() { |result| ... } #=> Cuprum::Command
|
1301
|
-
|
1302
|
-
The block will be passed the #result of the previous command as its parameter. If your use case depends on the status of the previous command or on any errors generated, use the block form of #chain.
|
1303
|
-
|
1304
|
-
If the block returns a Cuprum::Result (or an object responding to #value and #success?), the block result will be returned (or passed to the next chained command, if any). If the block returns any other value (including nil), the #result of the previous command will be returned or passed to the next command.
|
1305
|
-
|
1306
|
-
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Command#then-instance_method)
|
1307
|
-
|
1308
1204
|
#### `#yield_result`
|
1309
1205
|
|
1310
1206
|
yield_result(on: nil) { |previous_result| } #=> Cuprum::Result
|
1311
1207
|
|
1312
1208
|
Creates a copy of the command, and then chains the block to execute after the command implementation. When #call is executed, each chained block will be yielded the previous result, and the return value wrapped in a result and returned or yielded to the next block.
|
1313
1209
|
|
1314
|
-
If the `on` parameter is
|
1210
|
+
If the `on` parameter is set to `:success`, the block will be called if the last result is successful. If the `on` parameter is set to `:failure`, the block will be called if the last result is failing. Finally, if the `on` parameter is set to `:always` or to `nil`, the block will always be called.
|
1315
1211
|
|
1316
1212
|
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Command#yield_result-instance_method)
|
1317
1213
|
|
@@ -1367,65 +1263,29 @@ A Cuprum::Result defines the following methods:
|
|
1367
1263
|
|
1368
1264
|
==(other) #=> true, false
|
1369
1265
|
|
1370
|
-
Performs a fuzzy comparison with the other object. At a minimum, the other object must respond to `#value
|
1371
|
-
|
1372
|
-
#### `#empty?`
|
1373
|
-
|
1374
|
-
empty?() #=> true, false
|
1375
|
-
|
1376
|
-
Helper method that returns true for a new result. The method returns false if `result.value` is not nil, if `result.errors` is not empty, if the status has been manually set with `#success!` or `#failure!`, or if the result has been halted.
|
1266
|
+
Performs a fuzzy comparison with the other object. At a minimum, the other object must respond to `#value`, `#success?`, `#error` and the values of `other.value`, `other.success?`, and `other.error` must be equal to the corresponding value on the result. Returns true if all values match, otherwise returns false.
|
1377
1267
|
|
1378
|
-
#### `#
|
1268
|
+
#### `#error`
|
1379
1269
|
|
1380
|
-
|
1270
|
+
error() #=> nil
|
1381
1271
|
|
1382
|
-
The
|
1272
|
+
The error generated by the command, or `nil` if no error was generated.
|
1383
1273
|
|
1384
|
-
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Result#
|
1385
|
-
|
1386
|
-
#### `#failure!`
|
1387
|
-
|
1388
|
-
failure!() #=> Cuprum::Result
|
1389
|
-
|
1390
|
-
Marks the result as failing and returns the result. Calling `#failure?` will return true, even if the result has no errors.
|
1391
|
-
|
1392
|
-
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Result#failure!-instance_method)
|
1274
|
+
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Result#error-instance_method)
|
1393
1275
|
|
1394
1276
|
#### `#failure?`
|
1395
1277
|
|
1396
1278
|
failure?() #=> true, false
|
1397
1279
|
|
1398
|
-
True if the command generated
|
1280
|
+
True if the command generated an error or was marked as failing. Otherwise false.
|
1399
1281
|
|
1400
1282
|
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Result#failure%3F-instance_method)
|
1401
1283
|
|
1402
|
-
#### `#halt!`
|
1403
|
-
|
1404
|
-
halt!() #=> Cuprum::Result
|
1405
|
-
|
1406
|
-
Marks the result as halted and returns the result. Calling `#halted?` will return true.
|
1407
|
-
|
1408
|
-
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Result#halt!-instance_method)
|
1409
|
-
|
1410
|
-
#### `#halted?`
|
1411
|
-
|
1412
|
-
halted?() #=> true, false
|
1413
|
-
|
1414
|
-
True if the result is halted, which prevents chained commands from executing.
|
1415
|
-
|
1416
|
-
#### `#success!`
|
1417
|
-
|
1418
|
-
success!() #=> Cuprum::Result
|
1419
|
-
|
1420
|
-
Marks the result as passing and returns the result. Calling `#success?` will return true, even if the result has errors.
|
1421
|
-
|
1422
|
-
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Result#success!-instance_method)
|
1423
|
-
|
1424
1284
|
#### `#success?`
|
1425
1285
|
|
1426
1286
|
success?() #=> true, false
|
1427
1287
|
|
1428
|
-
True if the command did not generate
|
1288
|
+
True if the command did not generate an error, or the result has an error but was marked as passing. Otherwise false.
|
1429
1289
|
|
1430
1290
|
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Result#success%3F-instance_method)
|
1431
1291
|
|
@@ -1465,9 +1325,9 @@ Finds or creates a spy object for the given module or class. Each time that the
|
|
1465
1325
|
# Observing calls to instances of a command.
|
1466
1326
|
spy = Cuprum::Utils::InstanceSpy.spy_on(CustomCommand)
|
1467
1327
|
|
1468
|
-
expect(spy).to receive(:call).with(1, 2, 3, :
|
1328
|
+
expect(spy).to receive(:call).with(1, 2, 3, four: '4')
|
1469
1329
|
|
1470
|
-
CustomCommand.new.call(1, 2, 3, :
|
1330
|
+
CustomCommand.new.call(1, 2, 3, four: '4')
|
1471
1331
|
|
1472
1332
|
# Observing calls to a chained command.
|
1473
1333
|
spy = Cuprum::Utils::InstanceSpy.spy_on(ChainedCommand)
|
@@ -1483,6 +1343,6 @@ Finds or creates a spy object for the given module or class. Each time that the
|
|
1483
1343
|
expect(spy).to receive(:call)
|
1484
1344
|
|
1485
1345
|
CustomCommand.new.call
|
1486
|
-
end
|
1346
|
+
end
|
1487
1347
|
|
1488
1348
|
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Utils/InstanceSpy#spy_on%3F-instance_method)
|