cuprum 0.7.0 → 0.8.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 +16 -0
- data/DEVELOPMENT.md +47 -41
- data/README.md +372 -56
- data/lib/cuprum/chaining.rb +128 -28
- data/lib/cuprum/command.rb +0 -3
- data/lib/cuprum/command_factory.rb +276 -0
- data/lib/cuprum/errors.rb +6 -0
- data/lib/cuprum/{not_implemented_error.rb → errors/process_not_implemented_error.rb} +7 -7
- data/lib/cuprum/operation.rb +3 -3
- data/lib/cuprum/processing.rb +10 -24
- data/lib/cuprum/result.rb +14 -2
- data/lib/cuprum/version.rb +1 -1
- metadata +19 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cafecaeff8b2c0209616cd9303613d88723c2477
|
4
|
+
data.tar.gz: b4d1c2cdde687815ac835631c460a45d15a3306d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f465ecb20dd65d5e835f6f506bbaca272e39637a5b127fac31929fef88a880069ed8b7f86802b207b01b767de952d641a688344dfabd8b1d4347d904daf926d7
|
7
|
+
data.tar.gz: be12f0a8d8be45ba1aabc854b48be53be13e2716d39e1c48fecae038b99019880c19686fd96bb1d1ff04272400650723df47b789ebe48b60da1e6ba844175f3a
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,21 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 0.8.0
|
4
|
+
|
5
|
+
The "We Have The Technology" Update.
|
6
|
+
|
7
|
+
### Commands
|
8
|
+
|
9
|
+
Added protected chaining methods `#chain!`, `#tap_result!` and `#yield_result!`. These methods function as their non-imperative counterparts, but add the chained command or block to the current command instead of a clone.
|
10
|
+
|
11
|
+
Removed the ResultHelpers mixin from the default Command class. To use the result helper methods, include Cuprum::ResultHelpers in your command class.
|
12
|
+
|
13
|
+
Removed the #build_errors helper - each Result is now responsible for building its own errors object. To use a custom errors object, define a subclass of Cuprum::Result and override its #build_errors method, then update your Command's #build_result method to use your custom result class.
|
14
|
+
|
15
|
+
### Command Factory
|
16
|
+
|
17
|
+
Implemented the CommandFactory class, which provides a builder interface and DSL for grouping and creating commands with a common purpose or with shared configuration.
|
18
|
+
|
3
19
|
## 0.7.0
|
4
20
|
|
5
21
|
The "To Strive, To Seek, To Find, And Not To Yield" Update.
|
data/DEVELOPMENT.md
CHANGED
@@ -1,43 +1,36 @@
|
|
1
1
|
# Development
|
2
2
|
|
3
|
-
## Version
|
3
|
+
## Version 0.9.0
|
4
4
|
|
5
|
-
|
5
|
+
The "Second Star To The Right" Update
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
### Actions
|
8
|
+
|
9
|
+
#### LifecycleHooks
|
10
|
+
|
11
|
+
- :before, :after hooks
|
12
|
+
- NOT included in Command by default
|
13
|
+
|
14
|
+
## Version 0.10.0
|
15
|
+
|
16
|
+
'The "Out Of Context Problem" Update'
|
9
17
|
|
10
18
|
### Commands
|
11
19
|
|
12
|
-
- Protected Chaining Methods:
|
13
|
-
- #chain!, #success!, #failure!, #tap_chain!, #yield_result!
|
14
|
-
- adds chained command to current command instead of a clone.
|
15
|
-
- Command#to_proc
|
16
|
-
- :clear_errors => true option on #chain
|
17
20
|
- #context object
|
18
|
-
- command currying
|
19
21
|
|
20
|
-
|
22
|
+
## Version 1.0.0
|
21
23
|
|
22
|
-
|
23
|
-
- ::rescue - `rescue StandardError do ... end`, rescues matched errors in #process
|
24
|
-
- chaining methods:
|
25
|
-
- ::chain (::success, ::failure):
|
26
|
-
on #initialize, chains the given command. Can be given a command class
|
27
|
-
(if ::new takes no arguments) or a block that returns a command.
|
28
|
-
- constructor methods:
|
29
|
-
- Programmatically generate a constructor method. Raises an error if
|
30
|
-
#initialize is defined. Automatically sets instance variables on initialize,
|
31
|
-
and defines reader methods.
|
32
|
-
- ::arguments - sets all positional arguments in the constructor. Takes 0 or
|
33
|
-
more String or Symbol arguments representing required arguments. Takes an
|
34
|
-
optional hash with String/Symbol keys and arbitrary values, representing
|
35
|
-
optional arguments and their default values.
|
36
|
-
- ::keywords - sets keyword arguments; same arguments as ::arguments.
|
24
|
+
'The "Look On My Works, Ye Mighty, and Despair" Update'
|
37
25
|
|
38
|
-
|
26
|
+
- Integration specs.
|
27
|
+
- Configuration option to raise, warn, ignore discarded results.
|
28
|
+
- Code cleanup: Hash syntax, remove end comments, remove file headers
|
29
|
+
|
30
|
+
### Commands
|
39
31
|
|
40
|
-
-
|
32
|
+
- Command#to_proc
|
33
|
+
- :clear_errors => true option on #chain
|
41
34
|
|
42
35
|
### Commands - Built In
|
43
36
|
|
@@ -45,19 +38,6 @@
|
|
45
38
|
as array
|
46
39
|
- RetryCommand
|
47
40
|
|
48
|
-
### CommandFactory
|
49
|
-
|
50
|
-
- builder/aggregator for command objects, esp. with shared
|
51
|
-
initializers/parameters, e.g. actions for a resource
|
52
|
-
- Syntax: |
|
53
|
-
|
54
|
-
actions = ResourceCommandFactory.new(Book)
|
55
|
-
command = actions::Build.new #=> returns a book builder command
|
56
|
-
result = command.call(attributes) #=> returns a result with value => a Book
|
57
|
-
# OR
|
58
|
-
result = actions.build(attributes) #=> returns a result with value => a Book
|
59
|
-
book = result.value
|
60
|
-
|
61
41
|
### Documentation
|
62
42
|
|
63
43
|
Chaining Case Study: |
|
@@ -73,3 +53,29 @@ Chaining Case Study: |
|
|
73
53
|
Create Content
|
74
54
|
Create ContentVersion
|
75
55
|
Tags.each { FindOrCreate Tag }
|
56
|
+
|
57
|
+
## Future Versions
|
58
|
+
|
59
|
+
### Commands
|
60
|
+
|
61
|
+
- command currying
|
62
|
+
|
63
|
+
#### Cuprum::DSL
|
64
|
+
|
65
|
+
- ::process - shortcut for defining #process
|
66
|
+
- ::rescue - `rescue StandardError do ... end`, rescues matched errors in #process
|
67
|
+
- chaining methods:
|
68
|
+
- ::chain (::success, ::failure):
|
69
|
+
on #initialize, chains the given command. Can be given a command class
|
70
|
+
(if ::new takes no arguments) or a block that returns a command.
|
71
|
+
- constructor methods:
|
72
|
+
- Programmatically generate a constructor method. Raises an error if
|
73
|
+
#initialize is defined. Automatically sets instance variables on initialize,
|
74
|
+
and defines reader methods.
|
75
|
+
- ::arguments - sets all positional arguments in the constructor. Takes 0 or
|
76
|
+
more String or Symbol arguments representing required arguments. Takes an
|
77
|
+
optional hash with String/Symbol keys and arbitrary values, representing
|
78
|
+
optional arguments and their default values.
|
79
|
+
- ::keywords - sets keyword arguments; same arguments as ::arguments.
|
80
|
+
|
81
|
+
#### Hooks
|
data/README.md
CHANGED
@@ -31,7 +31,7 @@ If you want to extract your logic but Cuprum is not the right solution for you,
|
|
31
31
|
|
32
32
|
### Compatibility
|
33
33
|
|
34
|
-
Cuprum is tested against Ruby (MRI) 2.
|
34
|
+
Cuprum is tested against Ruby (MRI) 2.3 through 2.5.
|
35
35
|
|
36
36
|
### Documentation
|
37
37
|
|
@@ -650,6 +650,43 @@ result.success? #=> true
|
|
650
650
|
|
651
651
|
Under the hood, both `#chain` and `#tap_result` are implemented on top of `#yield_result`.
|
652
652
|
|
653
|
+
#### Protected Chaining Methods
|
654
|
+
|
655
|
+
Each Command also defines the `#chain!`, `#tap_result!`, and `#yield_result!` methods - note the imperative `!`. These methods behave identically to their non-imperative counterparts, but they modify the current command directly instead of creating a clone. They are also protected methods, so they cannot be called from outside the command itself. These methods are designed for use when defining commands.
|
656
|
+
|
657
|
+
```ruby
|
658
|
+
# We subclass the build command, which will be executed first.
|
659
|
+
class CreateCommentCommand < BuildCommentCommand
|
660
|
+
include Cuprum::Chaining
|
661
|
+
include Cuprum::Processing
|
662
|
+
#
|
663
|
+
def initialize
|
664
|
+
# After the build step is run, we validate the comment.
|
665
|
+
chain!(ValidateCommentCommand.new)
|
666
|
+
#
|
667
|
+
# If the validation passes, we then save the comment.
|
668
|
+
chain!(SaveCommentCommand.new, on: :success)
|
669
|
+
end
|
670
|
+
end
|
671
|
+
|
672
|
+
Comment.count #=> 0
|
673
|
+
|
674
|
+
body = 'Why do hot dogs come in packages of ten, and hot dog buns come in ' \
|
675
|
+
'packages of eight?'
|
676
|
+
result = CreateCommentCommand.new.call({ user_id: '12345', body: body })
|
677
|
+
|
678
|
+
result.value #=> an instance of Comment with the given user_id and body.
|
679
|
+
result.success? #=> true
|
680
|
+
Comment.count #=> 1; the comment was added to the database
|
681
|
+
|
682
|
+
result = CreateCommentCommand.new.call({ user_id: nil, body: body })
|
683
|
+
|
684
|
+
result.value #=> an instance of Comment with the given user_id and body.
|
685
|
+
result.success? #=> false
|
686
|
+
result.errors #=> ["User id can't be blank"]
|
687
|
+
Comment.count #=> 1; the comment was not added to the database
|
688
|
+
```
|
689
|
+
|
653
690
|
### Results
|
654
691
|
|
655
692
|
require 'cuprum'
|
@@ -734,6 +771,306 @@ result.halt!
|
|
734
771
|
result.halted? #=> true
|
735
772
|
```
|
736
773
|
|
774
|
+
### Command Factories
|
775
|
+
|
776
|
+
[Class Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum%2FCommandFactory)
|
777
|
+
|
778
|
+
Commands are powerful and flexible objects, but they do have a few disadvantages compared to traditional service objects which allow the developer to group together related functionality and shared implementation details. To bridge this gap, Cuprum implements the CommandFactory class. Command factories provide a DSL to quickly group together related commands and create context-specific command classes or instances.
|
779
|
+
|
780
|
+
For example, consider a basic entity command:
|
781
|
+
|
782
|
+
```ruby
|
783
|
+
class Book
|
784
|
+
def initialize(attributes = {})
|
785
|
+
@title = attributes[:title]
|
786
|
+
@author = attributes[:author]
|
787
|
+
end
|
788
|
+
|
789
|
+
attr_accessor :author, :publisher, :title
|
790
|
+
end
|
791
|
+
|
792
|
+
class BuildBookCommand < Cuprum::Command
|
793
|
+
private
|
794
|
+
|
795
|
+
def process(attributes = {})
|
796
|
+
Book.new(attributes)
|
797
|
+
end
|
798
|
+
end
|
799
|
+
|
800
|
+
class BookFactory < Cuprum::CommandFactory
|
801
|
+
command :build, BuildBookCommand
|
802
|
+
end
|
803
|
+
```
|
804
|
+
|
805
|
+
Our factory is defined by subclassing `Cuprum::CommandFactory`, and then we map the individual commands with the `::command` or `::command_class` class methods. In this case, we've defined a Book factory with the build command. The build command can be accessed on a factory instance in one of two ways.
|
806
|
+
|
807
|
+
First, the command class can be accessed directly as a constant on the factory instance.
|
808
|
+
|
809
|
+
```ruby
|
810
|
+
factory = BookFactory.new
|
811
|
+
factory::Build #=> BuildBookCommand
|
812
|
+
```
|
813
|
+
|
814
|
+
Second, the factory instance now defines a `#build` method, which returns an instance of our defined command class. This command instance can be called like any command, or returned or passed around like any other object.
|
815
|
+
|
816
|
+
```ruby
|
817
|
+
factory = BookFactory.new
|
818
|
+
|
819
|
+
attrs = { title: 'A Wizard of Earthsea', author: 'Ursula K. Le Guin' }
|
820
|
+
command = factory.build() #=> an instance of BuildBookCommand
|
821
|
+
result = command.call(attrs) #=> an instance of Cuprum::Result
|
822
|
+
book = result.value #=> an instance of Book
|
823
|
+
|
824
|
+
book.title #=> 'A Wizard of Earthsea'
|
825
|
+
book.author #=> 'Ursula K. Le Guin'
|
826
|
+
book.publisher #=> nil
|
827
|
+
```
|
828
|
+
|
829
|
+
#### The ::command Method And A Command Class
|
830
|
+
|
831
|
+
The first way to define a command for a factory is by calling the `::command` method and passing it the name of the command and a command class:
|
832
|
+
|
833
|
+
```ruby
|
834
|
+
class BookFactory < Cuprum::CommandFactory
|
835
|
+
command :build, BuildBookCommand
|
836
|
+
end
|
837
|
+
```
|
838
|
+
|
839
|
+
This makes the command class available on a factory instance as `::Build`, and generates the `#build` method which returns an instance of `BuildBookCommand`.
|
840
|
+
|
841
|
+
#### The ::command Method And A Block
|
842
|
+
|
843
|
+
By calling the `::command` method with a block, you can define a command with additional control over how the generated command. The block must return an instance of a subclass of Cuprum::Command.
|
844
|
+
|
845
|
+
```ruby
|
846
|
+
class PublishBookCommand < Cuprum::Command
|
847
|
+
def initialize(publisher:)
|
848
|
+
@publisher = publisher
|
849
|
+
end
|
850
|
+
|
851
|
+
attr_reader :publisher
|
852
|
+
|
853
|
+
private
|
854
|
+
|
855
|
+
def process(book)
|
856
|
+
book.publisher = publisher
|
857
|
+
|
858
|
+
book
|
859
|
+
end
|
860
|
+
end
|
861
|
+
|
862
|
+
class BookFactory < Cuprum::CommandFactory
|
863
|
+
command :publish do |publisher|
|
864
|
+
PublishBookCommand.new(publisher: publisher)
|
865
|
+
end
|
866
|
+
end
|
867
|
+
```
|
868
|
+
|
869
|
+
This defines the `#publish` method on an instance of the factory. The method takes one argument (the publisher), which is then passed on to the constructor for `PublishBookCommand` by our block. Finally, the block returns an instance of the publish command, which is then returned by `#publish`.
|
870
|
+
|
871
|
+
```ruby
|
872
|
+
factory = BookFactory.new
|
873
|
+
book = Book.new(title: 'The Tombs of Atuan', author: 'Ursula K. Le Guin')
|
874
|
+
book.publisher #=> nil
|
875
|
+
|
876
|
+
command = factory.publish('Harper & Row') #=> an instance of PublishBookCommand
|
877
|
+
result = command.call(book) #=> an instance of Cuprum::Result
|
878
|
+
book.publisher #=> 'Harper & Row'
|
879
|
+
```
|
880
|
+
|
881
|
+
Note that unlike when `::command` is called with a command class, calling `::command` with a block will not set a constant on the factory instance. In this case, trying to access the `PublishBookCommand` at `factory::Publish` will raise a `NameError`.
|
882
|
+
|
883
|
+
The block is evaluated in the context of the factory instance. This means that instance variables or methods are available to the block, allowing you to create commands with instance-specific configuration.
|
884
|
+
|
885
|
+
```ruby
|
886
|
+
class PublishedBooksCommand < Cuprum::Command
|
887
|
+
def initialize(collection = [])
|
888
|
+
@collection = collection
|
889
|
+
end
|
890
|
+
|
891
|
+
attr_reader :collection
|
892
|
+
|
893
|
+
private
|
894
|
+
|
895
|
+
def process
|
896
|
+
books.reject { |book| book.publisher.nil? }
|
897
|
+
end
|
898
|
+
end
|
899
|
+
|
900
|
+
class BookFactory < Cuprum::CommandFactory
|
901
|
+
command :published do
|
902
|
+
PublishedBooksCommand.new(books_collection)
|
903
|
+
end
|
904
|
+
|
905
|
+
def initialize(books)
|
906
|
+
@books_collection = books
|
907
|
+
end
|
908
|
+
|
909
|
+
attr_reader :books_collection
|
910
|
+
end
|
911
|
+
```
|
912
|
+
|
913
|
+
This defines the `#published` method on an instance of the factory. The method takes no arguments, but grabs the books collection from the factory instance. The block returns an instance of `PublishedBooksCommand`, which is then returned by `#published`.
|
914
|
+
|
915
|
+
```ruby
|
916
|
+
books = [Book.new, Book.new(publisher: 'Baen'), Book.new(publisher: 'Tor')]
|
917
|
+
factory = BookFactory.new(books)
|
918
|
+
factory.books_collection #=> the books array
|
919
|
+
|
920
|
+
command = factory.published #=> an instance of PublishedBooksCommand
|
921
|
+
result = command.call #=> an instance of Cuprum::Result
|
922
|
+
ary = result.value #=> an array with the published books
|
923
|
+
|
924
|
+
ary.count #=> 2
|
925
|
+
ary.any? { |book| book.publisher == 'Baen' } #=> true
|
926
|
+
ary.any? { |book| book.publisher.nil? } #=> false
|
927
|
+
```
|
928
|
+
|
929
|
+
Simple commands can be defined directly in the block, rather than referencing an existing command class:
|
930
|
+
|
931
|
+
```ruby
|
932
|
+
class BookFactory < Cuprum::CommandFactory
|
933
|
+
command :published_by_baen do
|
934
|
+
Cuprum::Command.new do |books|
|
935
|
+
books.select { |book| book.publisher == 'Baen' }
|
936
|
+
end
|
937
|
+
end
|
938
|
+
end
|
939
|
+
|
940
|
+
books = [Book.new, Book.new(publisher: 'Baen'), Book.new(publisher: 'Tor')]
|
941
|
+
factory = BookFactory.new(books)
|
942
|
+
|
943
|
+
command = factory.published_by_baen #=> an instance of the anonymous command
|
944
|
+
result = command.call #=> an instance of Cuprum::Result
|
945
|
+
ary = result.value #=> an array with the selected books
|
946
|
+
|
947
|
+
ary.count #=> 1
|
948
|
+
```
|
949
|
+
|
950
|
+
#### The ::command_class Method
|
951
|
+
|
952
|
+
The final way to define a command for a factory is calling the `::command_class` method with the command name and a block. The block must return a subclass (not an instance) of Cuprum::Command. This offers a balance between flexibility and power.
|
953
|
+
|
954
|
+
```ruby
|
955
|
+
class SelectByAuthorCommand < Cuprum::Command
|
956
|
+
def initialize(author)
|
957
|
+
@author = author
|
958
|
+
end
|
959
|
+
|
960
|
+
attr_reader :author
|
961
|
+
|
962
|
+
private
|
963
|
+
|
964
|
+
def process(books)
|
965
|
+
books.select { |book| book.author == author }
|
966
|
+
end
|
967
|
+
end
|
968
|
+
|
969
|
+
class BooksFactory < Cuprum::CommandFactory
|
970
|
+
command_class :select_by_author do
|
971
|
+
SelectByAuthorCommand
|
972
|
+
end
|
973
|
+
end
|
974
|
+
```
|
975
|
+
|
976
|
+
The command class can be accessed directly as a constant on the factory instance:
|
977
|
+
|
978
|
+
```ruby
|
979
|
+
factory = BookFactory.new
|
980
|
+
factory::SelectByAuthor #=> SelectByAuthorCommand
|
981
|
+
```
|
982
|
+
|
983
|
+
The factory instance now defines a `#select_by_author` method, which returns an instance of our defined command class. This command instance can be called like any command, or returned or passed around like any other object.
|
984
|
+
|
985
|
+
```ruby
|
986
|
+
factory = BookFactory.new
|
987
|
+
books = [
|
988
|
+
Book.new,
|
989
|
+
Book.new(author: 'Arthur C. Clarke'),
|
990
|
+
Book.new(author: 'Ursula K. Le Guin')
|
991
|
+
]
|
992
|
+
|
993
|
+
command = factory.select_by_author('Ursula K. Le Guin')
|
994
|
+
#=> an instance of SelectByAuthorCommand
|
995
|
+
command.author #=> 'Ursula K. Le Guin'
|
996
|
+
|
997
|
+
result = command.call(books) #=> an instance of Cuprum::Result
|
998
|
+
ary = result.value #=> an array with the selected books
|
999
|
+
|
1000
|
+
ary.count #=> 1
|
1001
|
+
ary.any? { |book| book.author == 'Ursula K. Le Guin' } #=> true
|
1002
|
+
ary.any? { |book| book.author == 'Arthur C. Clarke' } #=> false
|
1003
|
+
ary.any? { |book| book.author.nil? } #=> false
|
1004
|
+
```
|
1005
|
+
|
1006
|
+
The block is evaluated in the context of the factory instance. This means that instance variables or methods are available to the block, allowing you to create custom command subclasses with instance-specific configuration.
|
1007
|
+
|
1008
|
+
```ruby
|
1009
|
+
class SaveBookCommand < Cuprum::Command
|
1010
|
+
def initialize(collection = [])
|
1011
|
+
@collection = collection
|
1012
|
+
end
|
1013
|
+
|
1014
|
+
attr_reader :collection
|
1015
|
+
|
1016
|
+
private
|
1017
|
+
|
1018
|
+
def process(book)
|
1019
|
+
books << book
|
1020
|
+
|
1021
|
+
book
|
1022
|
+
end
|
1023
|
+
end
|
1024
|
+
|
1025
|
+
class BookFactory < Cuprum::CommandFactory
|
1026
|
+
command :save do
|
1027
|
+
collection = self.books_collection
|
1028
|
+
|
1029
|
+
Class.new(SaveBookCommand) do
|
1030
|
+
define_method(:initialize) do
|
1031
|
+
@books = collection
|
1032
|
+
end
|
1033
|
+
end
|
1034
|
+
end
|
1035
|
+
|
1036
|
+
def initialize(books)
|
1037
|
+
@books_collection = books
|
1038
|
+
end
|
1039
|
+
|
1040
|
+
attr_reader :books_collection
|
1041
|
+
end
|
1042
|
+
```
|
1043
|
+
|
1044
|
+
The custom command subclass can be accessed directly as a constant on the factory instance:
|
1045
|
+
|
1046
|
+
```ruby
|
1047
|
+
books = [Book.new, Book.new, Book.new]
|
1048
|
+
factory = BookFactory.new(books)
|
1049
|
+
factory::Save #=> a subclass of SaveBookCommand
|
1050
|
+
|
1051
|
+
command = factory::Save.new # an instance of the command subclass
|
1052
|
+
command.collection #=> the books array
|
1053
|
+
command.collection.count #=> 3
|
1054
|
+
```
|
1055
|
+
|
1056
|
+
The factory instance now defines a `#save` method, which returns an instance of our custom command subclass. This command instance can be called like any command, or returned or passed around like any other object.
|
1057
|
+
|
1058
|
+
The custom command subclass can be accessed directly as a constant on the factory instance:
|
1059
|
+
|
1060
|
+
```ruby
|
1061
|
+
books = [Book.new, Book.new, Book.new]
|
1062
|
+
factory = BookFactory.new(books)
|
1063
|
+
command = factory.save # an instance of the command subclass
|
1064
|
+
command.collection #=> the books array
|
1065
|
+
command.collection.count #=> 3
|
1066
|
+
|
1067
|
+
book = Book.new(title: 'The Farthest Shore', author: 'Ursula K. Le Guin')
|
1068
|
+
result = command.call(book) #=> an instance of Cuprum::Result
|
1069
|
+
|
1070
|
+
books.count #=> 4
|
1071
|
+
books.include?(book) #=> true
|
1072
|
+
```
|
1073
|
+
|
737
1074
|
### Built In Commands
|
738
1075
|
|
739
1076
|
Cuprum includes a small number of predefined commands and their equivalent operations.
|
@@ -880,7 +1217,7 @@ Generates an empty errors object. When the command is called, the result will ha
|
|
880
1217
|
|
881
1218
|
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Command#build_errors-instance_method)
|
882
1219
|
|
883
|
-
####
|
1220
|
+
#### `#call`
|
884
1221
|
|
885
1222
|
call(*arguments, **keywords) { ... } #=> Cuprum::Result
|
886
1223
|
|
@@ -888,7 +1225,7 @@ Executes the logic encoded in the constructor block, or the #process method if n
|
|
888
1225
|
|
889
1226
|
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Command#call-instance_method)
|
890
1227
|
|
891
|
-
####
|
1228
|
+
#### `#chain`
|
892
1229
|
|
893
1230
|
chain(on: nil) { |result| ... } #=> Cuprum::Command
|
894
1231
|
|
@@ -904,6 +1241,18 @@ If the block returns a Cuprum::Result (or an object responding to #value and #su
|
|
904
1241
|
|
905
1242
|
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Command#chain-instance_method)
|
906
1243
|
|
1244
|
+
#### `#chain!`
|
1245
|
+
|
1246
|
+
*(Protected Method)*
|
1247
|
+
|
1248
|
+
chain!(on: nil) { |result| ... } #=> Cuprum::Command
|
1249
|
+
|
1250
|
+
chain!(command, on: nil) #=> Cuprum::Command
|
1251
|
+
|
1252
|
+
As `#chain`, but modifies the current command instead of creating a clone.
|
1253
|
+
|
1254
|
+
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Command#chain!-instance_method)
|
1255
|
+
|
907
1256
|
#### `#else`
|
908
1257
|
|
909
1258
|
else(command) #=> Cuprum::Command
|
@@ -920,68 +1269,25 @@ If the block returns a Cuprum::Result (or an object responding to #value and #su
|
|
920
1269
|
|
921
1270
|
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Command#else-instance_method)
|
922
1271
|
|
923
|
-
#### `#
|
924
|
-
|
925
|
-
*(Private Method)*
|
926
|
-
|
927
|
-
errors() #=> Array
|
928
|
-
|
929
|
-
Only available while the Command is being called. Provides access to the errors object of the generated Cuprum::Result, which is by default an instance of Array.
|
930
|
-
|
931
|
-
Inside of the Command block or the `#process` method, you can add errors to the result.
|
932
|
-
|
933
|
-
command =
|
934
|
-
Cuprum::Command.new do
|
935
|
-
errors << "I'm sorry, something went wrong."
|
936
|
-
|
937
|
-
nil
|
938
|
-
end # command
|
939
|
-
|
940
|
-
result = command.call
|
941
|
-
result.failure?
|
942
|
-
#=> true
|
943
|
-
result.errors
|
944
|
-
#=> ["I'm sorry, something went wrong."]
|
945
|
-
|
946
|
-
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Command#errors-instance_method)
|
947
|
-
|
948
|
-
#### `#failure!`
|
949
|
-
|
950
|
-
failure!() #=> NilClass
|
951
|
-
|
952
|
-
*(Private Method)*
|
953
|
-
|
954
|
-
Only available while the Command is being called. If called, marks the result object as failing, even if the result does not have errors.
|
955
|
-
|
956
|
-
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Command#failure!-instance_method)
|
957
|
-
|
958
|
-
#### `#halt!`
|
959
|
-
|
960
|
-
halt!() #=> NilClass
|
961
|
-
|
962
|
-
*(Private Method)*
|
963
|
-
|
964
|
-
Only available while the Command is being called. If called, halts the command chain (see Chaining Commands, below). Subsequent chained commands will not be called unless they were chained with the `:on => :always` option.
|
965
|
-
|
966
|
-
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Command#halt!-instance_method)
|
1272
|
+
#### `#tap_result`
|
967
1273
|
|
968
|
-
|
1274
|
+
tap_result(on: nil) { |previous_result| } #=> Cuprum::Result
|
969
1275
|
|
970
|
-
|
1276
|
+
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.
|
971
1277
|
|
972
|
-
|
1278
|
+
If the `on` parameter is omitted, the block will be called if the last result is not halted. If the `on` parameter is set to `:success`, the block will be called if the last result is successful and not halted. If the `on` parameter is set to `:failure`, the block will be called if the last result is failing and not halted. Finally, if the `on` parameter is set to `:always`, the block will always be called, even if the last result is halted.
|
973
1279
|
|
974
|
-
|
1280
|
+
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Command#tap_result-instance_method)
|
975
1281
|
|
976
|
-
|
1282
|
+
#### `#tap_result!`
|
977
1283
|
|
978
|
-
|
1284
|
+
*(Protected Method)*
|
979
1285
|
|
980
|
-
tap_result(on: nil) { |previous_result| } #=> Cuprum::Result
|
1286
|
+
tap_result!(on: nil) { |previous_result| } #=> Cuprum::Result
|
981
1287
|
|
982
|
-
|
1288
|
+
As `#tap_result`, but modifies the current command instead of creating a clone.
|
983
1289
|
|
984
|
-
|
1290
|
+
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Command#tap_result!-instance_method)
|
985
1291
|
|
986
1292
|
#### `#then`
|
987
1293
|
|
@@ -1009,6 +1315,16 @@ If the `on` parameter is omitted, the block will be called if the last result is
|
|
1009
1315
|
|
1010
1316
|
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Command#yield_result-instance_method)
|
1011
1317
|
|
1318
|
+
#### `#yield_result!`
|
1319
|
+
|
1320
|
+
*(Protected Method)*
|
1321
|
+
|
1322
|
+
yield_result!(on: nil) { |previous_result| } #=> Cuprum::Result
|
1323
|
+
|
1324
|
+
As `#yield_result`, but modifies the current command instead of creating a clone.
|
1325
|
+
|
1326
|
+
[Method Documentation](http://www.rubydoc.info/github/sleepingkingstudios/cuprum/master/Cuprum/Command#yield_result!-instance_method)
|
1327
|
+
|
1012
1328
|
### Cuprum::Operation
|
1013
1329
|
|
1014
1330
|
require 'cuprum'
|