cuprum 0.8.0 → 0.9.0.beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
data/lib/cuprum.rb
CHANGED
@@ -5,35 +5,10 @@ module Cuprum
|
|
5
5
|
autoload :Operation, 'cuprum/operation'
|
6
6
|
autoload :Result, 'cuprum/result'
|
7
7
|
|
8
|
-
DEFAULT_WARNING_PROC = ->(message) { Kernel.warn message }
|
9
|
-
private_constant :DEFAULT_WARNING_PROC
|
10
|
-
|
11
8
|
class << self
|
12
|
-
# @return [Proc] The proc called to display a warning message. By default,
|
13
|
-
# delegates to Kernel#warn. Set this to configure the warning behavior
|
14
|
-
# (e.g. to call a Logger).
|
15
|
-
attr_writer :warning_proc
|
16
|
-
|
17
9
|
# @return [String] The current version of the gem.
|
18
10
|
def version
|
19
11
|
VERSION
|
20
12
|
end # method version
|
21
|
-
|
22
|
-
# Displays a warning message. By default, delegates to Kernel#warn. The
|
23
|
-
# warning behavior can be configured (e.g. to call a Logger) using the
|
24
|
-
# #warning_proc= method.
|
25
|
-
#
|
26
|
-
# @param message [String] The warning message to display.
|
27
|
-
#
|
28
|
-
# @see #warning_proc=
|
29
|
-
def warn message
|
30
|
-
warning_proc.call(message)
|
31
|
-
end # method warn
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def warning_proc
|
36
|
-
@warning_proc ||= DEFAULT_WARNING_PROC
|
37
|
-
end # method warning_proc
|
38
13
|
end # eigenclass
|
39
14
|
end # module
|
@@ -12,15 +12,15 @@ module Cuprum::BuiltIn
|
|
12
12
|
# #=> true
|
13
13
|
#
|
14
14
|
# @example With a result.
|
15
|
-
#
|
16
|
-
# value = Cuprum::Result.new('result value', :
|
15
|
+
# error = 'errors.messages.unknown'
|
16
|
+
# value = Cuprum::Result.new(value: 'result value', error: error)
|
17
17
|
# result = IdentityCommand.new.call(value)
|
18
18
|
# result.value
|
19
19
|
# #=> 'result value'
|
20
20
|
# result.success?
|
21
21
|
# #=> false
|
22
|
-
# result.
|
23
|
-
# #=>
|
22
|
+
# result.error
|
23
|
+
# #=> 'errors.messages.unknown'
|
24
24
|
class IdentityCommand < Cuprum::Command
|
25
25
|
private
|
26
26
|
|
data/lib/cuprum/chaining.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'cuprum'
|
2
4
|
|
3
5
|
module Cuprum
|
@@ -25,8 +27,8 @@ module Cuprum
|
|
25
27
|
# chain(UrlSafeCommand.new).
|
26
28
|
# chain(PrependDateCommand.new(post.created_at)).
|
27
29
|
# call(post.title)
|
28
|
-
# end
|
29
|
-
# end
|
30
|
+
# end
|
31
|
+
# end
|
30
32
|
#
|
31
33
|
# title = 'Greetings, programs!'
|
32
34
|
# date = '1982-07-09'
|
@@ -53,50 +55,76 @@ module Cuprum
|
|
53
55
|
#
|
54
56
|
# private
|
55
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
|
+
#
|
56
86
|
# # Tries to find the tag with the given name. If that fails, creates a
|
57
87
|
# # new tag with the given name. If the tag is found, or if the new tag is
|
58
88
|
# # successfully created, then creates a tagging using the tag. If the tag
|
59
89
|
# # is not found and cannot be created, then the tagging is not created
|
60
90
|
# # and the result of the CreateTaggingCommand is a failure with the
|
61
91
|
# # appropriate error messages.
|
62
|
-
# def process
|
63
|
-
#
|
64
|
-
#
|
65
|
-
#
|
66
|
-
#
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
# Tag.create(tag_name)
|
73
|
-
# end.
|
74
|
-
# chain(:on => :success) do |tag|
|
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.
|
75
102
|
# tag.create_tagging(taggable)
|
76
103
|
# end
|
77
|
-
#
|
78
|
-
#
|
104
|
+
# .call(tag_name)
|
105
|
+
# end
|
106
|
+
# end
|
79
107
|
#
|
80
108
|
# post = Post.create(:title => 'Tagging Example')
|
81
109
|
# example_tag = Tag.create(:name => 'Example Tag')
|
82
110
|
#
|
83
111
|
# result = CreateTaggingCommand.new.call(post, 'Example Tag')
|
84
112
|
# result.success? #=> true
|
85
|
-
# result.
|
113
|
+
# result.error #=> nil
|
86
114
|
# result.value #=> an instance of Tagging
|
87
115
|
# post.tags.map(&:name)
|
88
116
|
# #=> ['Example Tag']
|
89
117
|
#
|
90
118
|
# result = CreateTaggingCommand.new.call(post, 'Another Tag')
|
91
119
|
# result.success? #=> true
|
92
|
-
# result.
|
120
|
+
# result.error #=> nil
|
93
121
|
# result.value #=> an instance of Tagging
|
94
122
|
# post.tags.map(&:name)
|
95
123
|
# #=> ['Example Tag', 'Another Tag']
|
96
124
|
#
|
97
125
|
# result = CreateTaggingCommand.new.call(post, 'An Invalid Tag Name')
|
98
126
|
# result.success? #=> false
|
99
|
-
# result.
|
127
|
+
# result.error #=> [{ tag: { name: ['is invalid'] }}]
|
100
128
|
# post.tags.map(&:name)
|
101
129
|
# #=> ['Example Tag', 'Another Tag']
|
102
130
|
#
|
@@ -123,12 +151,8 @@ module Cuprum
|
|
123
151
|
# Find.new(Post).call(id).
|
124
152
|
# yield_result(:on => :failure) do |result|
|
125
153
|
# redirect_to posts_path
|
126
|
-
#
|
127
|
-
# # A halted result prevents further :on => :failure commands from
|
128
|
-
# # being called.
|
129
|
-
# result.halt!
|
130
154
|
# end.
|
131
|
-
# yield_result do |result|
|
155
|
+
# yield_result(on: :success) do |result|
|
132
156
|
# # Assign our attributes and save the post.
|
133
157
|
# UpdateAttributes.new.call(result.value, attributes)
|
134
158
|
# end.
|
@@ -140,11 +164,11 @@ module Cuprum
|
|
140
164
|
# end.
|
141
165
|
# tap_result(:on => :always) do |result|
|
142
166
|
# # Chaining :on => :always ensures that the command will be run,
|
143
|
-
# # even if the previous result is failing
|
167
|
+
# # even if the previous result is failing.
|
144
168
|
# if result.failure?
|
145
169
|
# log_errors(
|
146
170
|
# :command => UpdatePostCommand,
|
147
|
-
# :
|
171
|
+
# :error => result.error
|
148
172
|
# )
|
149
173
|
# end
|
150
174
|
# end
|
@@ -172,6 +196,11 @@ module Cuprum
|
|
172
196
|
#
|
173
197
|
# @see Cuprum::Command
|
174
198
|
module Chaining
|
199
|
+
# (see Cuprum::Processing#call)
|
200
|
+
def call(*args, &block)
|
201
|
+
yield_chain(super)
|
202
|
+
end
|
203
|
+
|
175
204
|
# Creates a copy of the first command, and then chains the given command or
|
176
205
|
# block to execute after the first command's implementation. When #call is
|
177
206
|
# executed, each chained command will be called with the previous result
|
@@ -190,13 +219,11 @@ module Cuprum
|
|
190
219
|
# @param on [Symbol] Sets a condition on when the chained block can run,
|
191
220
|
# based on the previous result. Valid values are :success, :failure, and
|
192
221
|
# :always. If the value is :success, the block will be called only if
|
193
|
-
# the previous result succeeded
|
194
|
-
#
|
195
|
-
#
|
196
|
-
#
|
197
|
-
#
|
198
|
-
# previous command was a success or a failure, but not if the command
|
199
|
-
# chain has been halted.
|
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.
|
200
227
|
#
|
201
228
|
# @overload chain(on: nil) { |value| }
|
202
229
|
# Creates an anonymous command from the given block. The command will be
|
@@ -205,62 +232,16 @@ module Cuprum
|
|
205
232
|
# @param on [Symbol] Sets a condition on when the chained block can run,
|
206
233
|
# based on the previous result. Valid values are :success, :failure, and
|
207
234
|
# :always. If the value is :success, the block will be called only if
|
208
|
-
# the previous result succeeded
|
209
|
-
#
|
210
|
-
#
|
211
|
-
#
|
212
|
-
#
|
213
|
-
# previous command was a success or a failure, but not if the command
|
214
|
-
# chain has been halted.
|
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.
|
215
240
|
#
|
216
241
|
# @yieldparam value [Object] The value of the previous result.
|
217
|
-
def chain
|
218
|
-
clone.chain!(command, :
|
219
|
-
end
|
220
|
-
|
221
|
-
# Shorthand for command.chain(:on => :failure). Creates a copy of the first
|
222
|
-
# command, and then chains the given command or block to execute after the
|
223
|
-
# first command's implementation, but only if the previous command is
|
224
|
-
# failing.
|
225
|
-
#
|
226
|
-
# @return [Cuprum::Chaining] A copy of the command, with the chained
|
227
|
-
# command.
|
228
|
-
#
|
229
|
-
# @see #chain
|
230
|
-
#
|
231
|
-
# @overload failure(command)
|
232
|
-
# @param command [Cuprum::Command] The command to chain.
|
233
|
-
#
|
234
|
-
# @overload failure() { |value| }
|
235
|
-
# Creates an anonymous command from the given block. The command will be
|
236
|
-
# passed the value of the previous result.
|
237
|
-
#
|
238
|
-
# @yieldparam value [Object] The value of the previous result.
|
239
|
-
def failure command = nil, &block
|
240
|
-
clone.chain!(command, :on => :failure, &block)
|
241
|
-
end # method failure
|
242
|
-
|
243
|
-
# Shorthand for command.chain(:on => :success). Creates a copy of the first
|
244
|
-
# command, and then chains the given command or block to execute after the
|
245
|
-
# first command's implementation, but only if the previous command is
|
246
|
-
# failing.
|
247
|
-
#
|
248
|
-
# @return [Cuprum::Chaining] A copy of the command, with the chained
|
249
|
-
# command.
|
250
|
-
#
|
251
|
-
# @see #chain
|
252
|
-
#
|
253
|
-
# @overload success(command)
|
254
|
-
# @param command [Cuprum::Command] The command to chain.
|
255
|
-
#
|
256
|
-
# @overload success() { |value| }
|
257
|
-
# Creates an anonymous command from the given block. The command will be
|
258
|
-
# passed the value of the previous result.
|
259
|
-
#
|
260
|
-
# @yieldparam value [Object] The value of the previous result.
|
261
|
-
def success command = nil, &block
|
262
|
-
clone.chain!(command, :on => :success, &block)
|
263
|
-
end # method success
|
242
|
+
def chain(command = nil, on: nil, &block)
|
243
|
+
clone.chain!(command, on: on, &block)
|
244
|
+
end
|
264
245
|
|
265
246
|
# As #yield_result, but always returns the previous result when the block is
|
266
247
|
# called. The return value of the block is discarded.
|
@@ -272,9 +253,9 @@ module Cuprum
|
|
272
253
|
# @return (see #yield_result)
|
273
254
|
#
|
274
255
|
# @see #yield_result
|
275
|
-
def tap_result
|
276
|
-
clone.tap_result!(:
|
277
|
-
end
|
256
|
+
def tap_result(on: nil, &block)
|
257
|
+
clone.tap_result!(on: on, &block)
|
258
|
+
end
|
278
259
|
|
279
260
|
# Creates a copy of the command, and then chains the block to execute after
|
280
261
|
# the command implementation. When #call is executed, each chained block
|
@@ -284,21 +265,20 @@ module Cuprum
|
|
284
265
|
# @param on [Symbol] Sets a condition on when the chained block can run,
|
285
266
|
# based on the previous result. Valid values are :success, :failure, and
|
286
267
|
# :always. If the value is :success, the block will be called only if the
|
287
|
-
# previous result succeeded
|
288
|
-
#
|
289
|
-
#
|
290
|
-
# the previous result status, even if the previous result is halted. If no
|
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
|
291
271
|
# value is given, the command will run whether the previous command was a
|
292
|
-
# success or a failure
|
272
|
+
# success or a failure.
|
293
273
|
#
|
294
274
|
# @yieldparam result [Cuprum::Result] The #result of the previous command.
|
295
275
|
#
|
296
276
|
# @return [Cuprum::Chaining] A copy of the command, with the chained block.
|
297
277
|
#
|
298
278
|
# @see #tap_result
|
299
|
-
def yield_result
|
300
|
-
clone.yield_result!(:
|
301
|
-
end
|
279
|
+
def yield_result(on: nil, &block)
|
280
|
+
clone.yield_result!(on: on, &block)
|
281
|
+
end
|
302
282
|
|
303
283
|
protected
|
304
284
|
|
@@ -318,13 +298,11 @@ module Cuprum
|
|
318
298
|
# @param on [Symbol] Sets a condition on when the chained block can run,
|
319
299
|
# based on the previous result. Valid values are :success, :failure, and
|
320
300
|
# :always. If the value is :success, the block will be called only if
|
321
|
-
# the previous result succeeded
|
322
|
-
#
|
323
|
-
#
|
324
|
-
#
|
325
|
-
#
|
326
|
-
# previous command was a success or a failure, but not if the command
|
327
|
-
# chain has been halted.
|
301
|
+
# the previous result succeeded. If the value is :failure, the block
|
302
|
+
# will be called only if the previous result failed. If the value is
|
303
|
+
# :always, the block will be called regardless of the previous result
|
304
|
+
# status. If no value is given, the command will run whether the
|
305
|
+
# previous command was a success or a failure.
|
328
306
|
#
|
329
307
|
# @overload chain!(on: nil) { |value| }
|
330
308
|
# Creates an anonymous command from the given block. The command will be
|
@@ -333,34 +311,28 @@ module Cuprum
|
|
333
311
|
# @param on [Symbol] Sets a condition on when the chained block can run,
|
334
312
|
# based on the previous result. Valid values are :success, :failure, and
|
335
313
|
# :always. If the value is :success, the block will be called only if
|
336
|
-
# the previous result succeeded
|
337
|
-
#
|
338
|
-
#
|
339
|
-
#
|
340
|
-
#
|
341
|
-
# previous command was a success or a failure, but not if the command
|
342
|
-
# chain has been halted.
|
314
|
+
# the previous result succeeded. If the value is :failure, the block
|
315
|
+
# will be called only if the previous result failed. If the value is
|
316
|
+
# :always, the block will be called regardless of the previous result
|
317
|
+
# status. If no value is given, the command will run whether the
|
318
|
+
# previous command was a success or a failure.
|
343
319
|
#
|
344
320
|
# @yieldparam value [Object] The value of the previous result.
|
345
|
-
def chain!
|
321
|
+
def chain!(command = nil, on: nil, &block)
|
346
322
|
command ||= Cuprum::Command.new(&block)
|
347
323
|
|
348
324
|
chained_procs <<
|
349
325
|
{
|
350
|
-
:
|
351
|
-
:
|
326
|
+
proc: chain_command(command),
|
327
|
+
on: on
|
352
328
|
} # end hash
|
353
329
|
|
354
330
|
self
|
355
|
-
end
|
331
|
+
end
|
356
332
|
|
357
333
|
def chained_procs
|
358
334
|
@chained_procs ||= []
|
359
|
-
end
|
360
|
-
|
361
|
-
def process_with_result *args, &block
|
362
|
-
yield_chain(super)
|
363
|
-
end # method call
|
335
|
+
end
|
364
336
|
|
365
337
|
# @!visibility public
|
366
338
|
#
|
@@ -375,17 +347,17 @@ module Cuprum
|
|
375
347
|
# @return (see #tap_result)
|
376
348
|
#
|
377
349
|
# @see #tap_result
|
378
|
-
def tap_result!
|
350
|
+
def tap_result!(on: nil, &block)
|
379
351
|
tapped = ->(result) { result.tap { block.call(result) } }
|
380
352
|
|
381
353
|
chained_procs <<
|
382
354
|
{
|
383
|
-
:
|
384
|
-
:
|
355
|
+
proc: tapped,
|
356
|
+
on: on
|
385
357
|
} # end hash
|
386
358
|
|
387
359
|
self
|
388
|
-
end
|
360
|
+
end
|
389
361
|
|
390
362
|
# @!visibility public
|
391
363
|
#
|
@@ -400,51 +372,49 @@ module Cuprum
|
|
400
372
|
# @return (see #yield_result)
|
401
373
|
#
|
402
374
|
# @see #yield_result
|
403
|
-
def yield_result!
|
375
|
+
def yield_result!(on: nil, &block)
|
404
376
|
chained_procs <<
|
405
377
|
{
|
406
|
-
:
|
407
|
-
:
|
378
|
+
proc: block,
|
379
|
+
on: on
|
408
380
|
} # end hash
|
409
381
|
|
410
382
|
self
|
411
|
-
end
|
383
|
+
end
|
412
384
|
|
413
385
|
private
|
414
386
|
|
415
|
-
def chain_command
|
387
|
+
def chain_command(command)
|
416
388
|
if command.arity.zero?
|
417
|
-
->(
|
389
|
+
->(_result) { command.call }
|
418
390
|
else
|
419
|
-
->(result) { command.
|
420
|
-
end
|
421
|
-
end
|
391
|
+
->(result) { command.call(result.value) }
|
392
|
+
end
|
393
|
+
end
|
422
394
|
|
423
|
-
def skip_chained_proc?
|
395
|
+
def skip_chained_proc?(last_result, on:)
|
424
396
|
return false if on == :always
|
425
397
|
|
426
|
-
return true if last_result.respond_to?(:halted?) && last_result.halted?
|
427
|
-
|
428
398
|
case on
|
429
399
|
when :success
|
430
400
|
!last_result.success?
|
431
401
|
when :failure
|
432
402
|
!last_result.failure?
|
433
|
-
end
|
434
|
-
end
|
403
|
+
end
|
404
|
+
end
|
435
405
|
|
436
|
-
def yield_chain
|
406
|
+
def yield_chain(first_result)
|
437
407
|
chained_procs.reduce(first_result) do |result, hsh|
|
438
|
-
next result if skip_chained_proc?(result, :
|
408
|
+
next result if skip_chained_proc?(result, on: hsh[:on])
|
439
409
|
|
440
410
|
value = hsh.fetch(:proc).call(result)
|
441
411
|
|
442
412
|
if value_is_result?(value)
|
443
|
-
value.
|
413
|
+
value.to_cuprum_result
|
444
414
|
else
|
445
|
-
build_result(value)
|
446
|
-
end
|
447
|
-
end
|
448
|
-
end
|
449
|
-
end
|
450
|
-
end
|
415
|
+
build_result(value: value)
|
416
|
+
end
|
417
|
+
end
|
418
|
+
end
|
419
|
+
end
|
420
|
+
end
|