service_actor 1.0.0 → 1.1.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 +4 -4
- data/README.md +33 -19
- data/lib/actor/context.rb +14 -47
- data/lib/actor/defaultable.rb +6 -1
- data/lib/actor/filtered_context.rb +5 -5
- data/lib/actor/playable.rb +1 -1
- data/lib/actor/requireable.rb +1 -1
- data/lib/actor/version.rb +1 -1
- data/lib/service_actor.rb +2 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1f46ecd0093a05e45fe0bc3ba11a69a8b282b82f4945ab05ff9f5cd1cd32e35e
|
4
|
+
data.tar.gz: 91f2c49e081eba4abbebceaef9abc131c3e8ad1c84a723846d144e2c8a890dff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bee18ffff2ffbf4eb185b28ab16c519ca30e09af6ba61773009d553c563e9dbdf903aa7c5d6a66b3a4c8a49886f00337b474e1e1376f207f81d1cbe268f3f29b
|
7
|
+
data.tar.gz: 68e99c61d126b23877cfc4497a4c830b343e1170f49b027013da7a68062d85f644f689ad389d4c584e5b39206cac66a4cb6ab9e359ac9f65a309832c14dab060
|
data/README.md
CHANGED
@@ -83,19 +83,24 @@ result.greeting # => "Have a wonderful day!"
|
|
83
83
|
Inputs can have defaults:
|
84
84
|
|
85
85
|
```rb
|
86
|
-
class
|
87
|
-
input :user
|
86
|
+
class BuildGreeting < Actor
|
88
87
|
input :adjective, default: "wonderful"
|
89
88
|
input :length_of_time, default: -> { ["day", "week", "month"].sample }
|
90
89
|
|
91
90
|
output :greeting
|
92
91
|
|
93
92
|
def call
|
94
|
-
context.greeting = "
|
93
|
+
context.greeting = "Have a #{adjective} #{length_of_time}!"
|
95
94
|
end
|
96
95
|
end
|
97
96
|
```
|
98
97
|
|
98
|
+
This lets you call the actor without specifying those keys:
|
99
|
+
|
100
|
+
```rb
|
101
|
+
BuildGreeting.call.greeting # => "Have a wonderful week!"
|
102
|
+
```
|
103
|
+
|
99
104
|
### Types
|
100
105
|
|
101
106
|
Inputs can define a type, or an array of possible types it must match:
|
@@ -109,10 +114,22 @@ class UpdateUser < Actor
|
|
109
114
|
end
|
110
115
|
```
|
111
116
|
|
117
|
+
### Required
|
118
|
+
|
119
|
+
To check that an input must not be `nil`, flag it as required.
|
120
|
+
|
121
|
+
```rb
|
122
|
+
class UpdateUser < Actor
|
123
|
+
input :user, required: true
|
124
|
+
|
125
|
+
# …
|
126
|
+
end
|
127
|
+
```
|
128
|
+
|
112
129
|
### Conditions
|
113
130
|
|
114
|
-
|
115
|
-
under `must`:
|
131
|
+
You can also add conditions that the inputs must verify, with the name of your
|
132
|
+
choice under `must`:
|
116
133
|
|
117
134
|
```rb
|
118
135
|
class UpdateAdminUser < Actor
|
@@ -125,7 +142,7 @@ end
|
|
125
142
|
|
126
143
|
### Result
|
127
144
|
|
128
|
-
All actors are successful by default. To stop
|
145
|
+
All actors are successful by default. To stop the execution and mark an actor as
|
129
146
|
having failed, use `fail!`:
|
130
147
|
|
131
148
|
```rb
|
@@ -143,11 +160,10 @@ class UpdateUser
|
|
143
160
|
end
|
144
161
|
```
|
145
162
|
|
146
|
-
|
147
|
-
of `.call`. This will let you test for `success?` or `failure?` on the context
|
148
|
-
instead of raising an exception.
|
163
|
+
This will raise an error in your app.
|
149
164
|
|
150
|
-
|
165
|
+
To test for the success instead of raising, you can use `.result` instead of
|
166
|
+
`.call`. For example in a Rails controller:
|
151
167
|
|
152
168
|
```rb
|
153
169
|
# app/controllers/users_controller.rb
|
@@ -166,7 +182,7 @@ end
|
|
166
182
|
### Play
|
167
183
|
|
168
184
|
An actor can call actors in sequence by using `play`. Each actor will hand over
|
169
|
-
the context to the next actor.
|
185
|
+
the same context to the next actor.
|
170
186
|
|
171
187
|
```rb
|
172
188
|
class PlaceOrder < Actor
|
@@ -182,8 +198,8 @@ end
|
|
182
198
|
When using `play`, if one of the actors calls `fail!`, the following actors will
|
183
199
|
not be called.
|
184
200
|
|
185
|
-
Also,
|
186
|
-
|
201
|
+
Also, all the _previous_ actors that succeeded will have their `rollback`
|
202
|
+
method triggered. For example:
|
187
203
|
|
188
204
|
```rb
|
189
205
|
class CreateOrder < Actor
|
@@ -199,12 +215,12 @@ end
|
|
199
215
|
|
200
216
|
### Early success
|
201
217
|
|
202
|
-
When using `play` you can use `succeed!`
|
203
|
-
|
218
|
+
When using `play` you can use `succeed!` to stop the execution of the following
|
219
|
+
actors, but still consider the actor to be successful.
|
204
220
|
|
205
221
|
### Lambdas
|
206
222
|
|
207
|
-
You can
|
223
|
+
You can use inline actions using lambdas:
|
208
224
|
|
209
225
|
```rb
|
210
226
|
class Pay
|
@@ -264,9 +280,7 @@ However there a a few key differences which make `actor` unique:
|
|
264
280
|
- Multiple organizers.
|
265
281
|
- Conditions inside organizers.
|
266
282
|
- No `before`, `after` and `around` hooks. Prefer simply overriding `call` with `super` which allows wrapping the whole method.
|
267
|
-
- [
|
268
|
-
- Does not print warnings on Ruby 2.7.
|
269
|
-
|
283
|
+
- [Fixes issues with `OpenStruct`](https://github.com/collectiveidea/interactor/issues/183)
|
270
284
|
|
271
285
|
## Development
|
272
286
|
|
data/lib/actor/context.rb
CHANGED
@@ -2,34 +2,28 @@
|
|
2
2
|
|
3
3
|
class Actor
|
4
4
|
# Represents the result of an action.
|
5
|
-
class Context
|
5
|
+
class Context < OpenStruct
|
6
6
|
def self.to_context(data)
|
7
7
|
return data if data.is_a?(self)
|
8
8
|
|
9
|
-
new(data)
|
10
|
-
end
|
11
|
-
|
12
|
-
def initialize(data = {})
|
13
|
-
@data = data.dup
|
14
|
-
end
|
15
|
-
|
16
|
-
def ==(other)
|
17
|
-
other.class == self.class && data == other.data
|
9
|
+
new(data.to_h)
|
18
10
|
end
|
19
11
|
|
20
12
|
def inspect
|
21
|
-
"<ActorContext #{
|
13
|
+
"<ActorContext #{to_h}>"
|
22
14
|
end
|
23
15
|
|
24
16
|
def fail!(context = {})
|
25
17
|
merge!(context)
|
26
|
-
|
18
|
+
merge!(failure?: true)
|
19
|
+
|
27
20
|
raise Actor::Failure, self
|
28
21
|
end
|
29
22
|
|
30
23
|
def succeed!(context = {})
|
31
24
|
merge!(context)
|
32
|
-
|
25
|
+
merge!(failure?: false)
|
26
|
+
|
33
27
|
raise Actor::Success, self
|
34
28
|
end
|
35
29
|
|
@@ -38,55 +32,28 @@ class Actor
|
|
38
32
|
end
|
39
33
|
|
40
34
|
def failure?
|
41
|
-
|
35
|
+
super || false
|
42
36
|
end
|
43
37
|
|
44
38
|
def merge!(context)
|
45
|
-
|
39
|
+
context.each_pair do |key, value|
|
40
|
+
self[key] = value
|
41
|
+
end
|
46
42
|
|
47
43
|
self
|
48
44
|
end
|
49
45
|
|
50
46
|
def key?(name)
|
51
|
-
|
47
|
+
to_h.key?(name)
|
52
48
|
end
|
53
49
|
|
54
50
|
def [](name)
|
55
|
-
|
51
|
+
to_h[name]
|
56
52
|
end
|
57
53
|
|
58
54
|
# Redefined here to override the method on `Object`.
|
59
55
|
def display
|
60
|
-
|
61
|
-
end
|
62
|
-
|
63
|
-
protected
|
64
|
-
|
65
|
-
attr_reader :data
|
66
|
-
|
67
|
-
private
|
68
|
-
|
69
|
-
# rubocop:disable Style/MethodMissingSuper
|
70
|
-
def method_missing(name, *arguments, **)
|
71
|
-
if name =~ /=$/
|
72
|
-
key = name.to_s.sub('=', '').to_sym
|
73
|
-
data[key] = arguments.first
|
74
|
-
else
|
75
|
-
data[name]
|
76
|
-
end
|
77
|
-
end
|
78
|
-
# rubocop:enable Style/MethodMissingSuper
|
79
|
-
|
80
|
-
def respond_to_missing?(*_arguments)
|
81
|
-
true
|
82
|
-
end
|
83
|
-
|
84
|
-
def context_get(key)
|
85
|
-
data[key]
|
86
|
-
end
|
87
|
-
|
88
|
-
def context_set(key, value)
|
89
|
-
data[key] = value
|
56
|
+
to_h.fetch(:display)
|
90
57
|
end
|
91
58
|
end
|
92
59
|
end
|
data/lib/actor/defaultable.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
class Actor
|
4
4
|
# Adds the `default:` option to inputs. Accepts regular values and lambdas.
|
5
|
+
# If no default is set and the value has not been given, raises an error.
|
5
6
|
#
|
6
7
|
# Example:
|
7
8
|
#
|
@@ -12,7 +13,11 @@ class Actor
|
|
12
13
|
module Defaultable
|
13
14
|
def before
|
14
15
|
self.class.inputs.each do |name, input|
|
15
|
-
next if
|
16
|
+
next if @context.key?(name)
|
17
|
+
|
18
|
+
unless input.key?(:default)
|
19
|
+
raise ArgumentError, "Input #{name} on #{self.class} is missing."
|
20
|
+
end
|
16
21
|
|
17
22
|
default = input[:default]
|
18
23
|
default = default.call if default.respond_to?(:call)
|
@@ -27,17 +27,17 @@ class Actor
|
|
27
27
|
|
28
28
|
attr_reader :context, :readers, :setters
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
# rubocop:disable Style/MethodMissingSuper
|
31
|
+
def method_missing(name, *arguments, &block)
|
33
32
|
unless available_methods.include?(name)
|
34
33
|
raise ArgumentError, "Cannot call #{name} on #{inspect}"
|
35
34
|
end
|
36
35
|
|
37
|
-
context.public_send(name, *arguments)
|
36
|
+
context.public_send(name, *arguments, &block)
|
38
37
|
end
|
38
|
+
# rubocop:enable Style/MethodMissingSuper
|
39
39
|
|
40
|
-
def respond_to_missing?(name,
|
40
|
+
def respond_to_missing?(name, _include_private = false)
|
41
41
|
available_methods.include?(name)
|
42
42
|
end
|
43
43
|
|
data/lib/actor/playable.rb
CHANGED
data/lib/actor/requireable.rb
CHANGED
data/lib/actor/version.rb
CHANGED
data/lib/service_actor.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: service_actor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sunny Ripert
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-03-
|
11
|
+
date: 2020-03-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|