service_actor 3.8.1 → 3.9.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ca3921af29250e8b2b68925ede79f0ad223d87bfa1be362e8e50cc178999658f
4
- data.tar.gz: 86f770c478e718d0c1c20f0809ade458d1687cabeac24b35cfa39d35430ea35d
3
+ metadata.gz: 623c58764fc64e35585264568ad1a611613d35522fdbb703ec7622b972a5141c
4
+ data.tar.gz: 37181c14d5c9484f0ad52bf593f4a5d2e8abac0f282e3a1cd7a4f64b63e10a8c
5
5
  SHA512:
6
- metadata.gz: 29cfec59fba54ea9ea8ddd4a250588513ad3132d5ecef79f6d6f43a58c5fa6aded756bc34cd6e698f233e4d584072f7f7e7342e8e3ee71cb1027463334450c7b
7
- data.tar.gz: 73b264aa00a02f23513da5b3b61b5a4a2b9a5afc72bb627d929f0a27c44a5cebf01b561d7e62c17fdb5293886f1bf65a6af0b69d0bd68674c2cad19eaef92ab3
6
+ metadata.gz: 37cc13ea57081d85e5cabf95657ca4fe938c29c3576e7ea7e74a7f4bbd949dd15791a7d0717cb3cf40b31201de2afde68c48ad84f639fb63cd6f950de3b84a26
7
+ data.tar.gz: 14c0ee2ad5e6556230cb87da94479a120ce64df4a97f85a232f78086e55c182502761fa0c2025c2d2a19c83890fc5500acf8206f5b0e32f03bcf97223d701295
data/README.md CHANGED
@@ -123,6 +123,22 @@ actor.greeting # => "Have a wonderful day!"
123
123
  actor.greeting? # => true
124
124
  ```
125
125
 
126
+ If you only have one value you want from an actor, you can skip defining an
127
+ output by making it the return value of `.call()` and calling your actor with
128
+ `.value()`:
129
+
130
+ ```rb
131
+ class BuildGreeting < Actor
132
+ input :name
133
+
134
+ def call
135
+ "Have a wonderful day, #{name}!"
136
+ end
137
+ end
138
+
139
+ BuildGreeting.value(name: "Fred") # => "Have a wonderful day, Fred!"
140
+ ```
141
+
126
142
  ### Fail
127
143
 
128
144
  To stop the execution and mark an actor as having failed, use `fail!`:
@@ -183,6 +199,9 @@ Calling this actor will now call every actor along the way. Inputs and outputs
183
199
  will go from one actor to the next, all sharing the same result set until it is
184
200
  finally returned.
185
201
 
202
+ If you use `.value()` to call this actor, it will give the return value of
203
+ the final actor in the play chain.
204
+
186
205
  ### Rollback
187
206
 
188
207
  When using `play`, if an actor calls `fail!`, the following actors will not be
@@ -15,6 +15,7 @@ module ServiceActor::Base
15
15
  base.include(ServiceActor::Checkable)
16
16
  base.include(ServiceActor::Defaultable)
17
17
  base.include(ServiceActor::Failable)
18
+ base.include(ServiceActor::Valuable)
18
19
  end
19
20
  end
20
21
  end
@@ -20,8 +20,9 @@ module ServiceActor::Checkable
20
20
  self.service_actor_argument_errors = []
21
21
 
22
22
  service_actor_checks_for(:input)
23
- super
23
+ return_val = super
24
24
  service_actor_checks_for(:output)
25
+ return_val
25
26
  end
26
27
 
27
28
  private
@@ -45,6 +45,8 @@ module ServiceActor::Core
45
45
  # This method is used internally to override behavior on call. Overriding
46
46
  # `call` instead would mean that end-users have to call `super` in their
47
47
  # actors.
48
+ # When overriding and calling `super`, make sure the final value is the return
49
+ # value of `super` (see e.g. ServiceActor::Checkable).
48
50
  # :nodoc:
49
51
  def _call
50
52
  call
@@ -54,11 +54,17 @@ module ServiceActor::Playable
54
54
 
55
55
  module PrependedMethods
56
56
  def call
57
+ default_output = nil
58
+
57
59
  self.class.play_actors.each do |options|
58
60
  next unless callable_actor?(options)
59
61
 
60
- options[:actors].each { |actor| play_actor(actor) }
62
+ options[:actors].each do |actor|
63
+ default_output = play_actor(actor)
64
+ end
61
65
  end
66
+
67
+ default_output
62
68
  rescue self.class.failure_class
63
69
  rollback
64
70
  raise
@@ -84,34 +90,32 @@ module ServiceActor::Playable
84
90
  end
85
91
 
86
92
  def play_actor(actor)
87
- play_service_actor(actor) ||
88
- play_method(actor) ||
89
- play_interactor(actor) ||
93
+ if actor.is_a?(Symbol)
94
+ send(actor)
95
+ elsif actor.is_a?(Class) && actor.ancestors.include?(ServiceActor::Core)
96
+ play_service_actor(actor)
97
+ elsif actor.is_a?(Class) &&
98
+ actor.ancestors.map(&:name).include?("Interactor")
99
+ play_interactor(actor)
100
+ else
90
101
  actor.call(result)
102
+ end
91
103
  end
92
104
 
93
105
  def play_service_actor(actor)
94
- return unless actor.is_a?(Class)
95
- return unless actor.ancestors.include?(ServiceActor::Core)
96
-
97
106
  actor = actor.new(result)
98
- actor._call
107
+ call_output = actor._call
99
108
 
100
109
  (@played_actors ||= []).unshift(actor)
110
+
111
+ call_output
101
112
  end
102
113
 
103
114
  def play_method(actor)
104
- return unless actor.is_a?(Symbol)
105
-
106
115
  send(actor)
107
-
108
- true
109
116
  end
110
117
 
111
118
  def play_interactor(actor)
112
- return unless actor.is_a?(Class)
113
- return unless actor.ancestors.map(&:name).include?("Interactor")
114
-
115
119
  result.merge!(actor.call(result.to_h).to_h)
116
120
  end
117
121
  end
@@ -33,7 +33,7 @@ class ServiceActor::Result < BasicObject
33
33
  end
34
34
 
35
35
  def to_h
36
- data
36
+ filter_default_output(data)
37
37
  end
38
38
 
39
39
  def inspect
@@ -59,7 +59,7 @@ class ServiceActor::Result < BasicObject
59
59
  end
60
60
 
61
61
  def failure?
62
- data[:failure] || false
62
+ data[:failure] || data[:failure?] || false
63
63
  end
64
64
 
65
65
  def error
@@ -103,6 +103,14 @@ class ServiceActor::Result < BasicObject
103
103
 
104
104
  attr_reader :data
105
105
 
106
+ # Key `_default_output` is an internal datum used by actor class
107
+ # method `.valuable`. Don't expose it with the rest of the result.
108
+ def filter_default_output(h)
109
+ # using `filter` instead of `except` to maintain Ruby 2.7 compatibility
110
+ # update once support for 2.7 is dropped
111
+ h.filter { |k| k != :_default_output }
112
+ end
113
+
106
114
  def respond_to_missing?(method_name, _include_private = false)
107
115
  return true if method_name.end_with?("=")
108
116
  if method_name.end_with?("?") &&
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Adds the `value` method to actors. This allows you to call `.value` and get
4
+ # back the return value of that actor's `call` method.
5
+ #
6
+ # In the case of play actors, it will return the value of the final actor's
7
+ # `call` method in the chain.
8
+ #
9
+ # class MyActor < Actor
10
+ # def call
11
+ # "foo"
12
+ # end
13
+ # end
14
+ #
15
+ # > MyActor.value
16
+ # => "foo"
17
+ module ServiceActor::Valuable
18
+ class << self
19
+ def included(base)
20
+ base.extend(ClassMethods)
21
+ base.prepend(PrependedMethods)
22
+ end
23
+ end
24
+
25
+ module ClassMethods
26
+ def value(result = nil, **arguments)
27
+ call(result, **arguments)[:_default_output]
28
+ end
29
+ end
30
+
31
+ module PrependedMethods
32
+ def _call
33
+ result[:_default_output] = super
34
+ end
35
+ end
36
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ServiceActor
4
- VERSION = "3.8.1"
4
+ VERSION = "3.9.1"
5
5
  end
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: 3.8.1
4
+ version: 3.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sunny Ripert
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-26 00:00:00.000000000 Z
11
+ date: 2024-04-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: zeitwerk
@@ -223,6 +223,7 @@ files:
223
223
  - lib/service_actor/playable.rb
224
224
  - lib/service_actor/result.rb
225
225
  - lib/service_actor/support/loader.rb
226
+ - lib/service_actor/valuable.rb
226
227
  - lib/service_actor/version.rb
227
228
  homepage: https://github.com/sunny/actor
228
229
  licenses: