actioninteractor 0.1.0.1 → 0.2.4
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/lib/action_interactor/base.rb +42 -29
- data/lib/action_interactor/composite.rb +63 -0
- data/lib/action_interactor/errors.rb +1 -1
- data/lib/action_interactor/execution_state.rb +27 -0
- data/lib/action_interactor/results.rb +1 -1
- data/lib/action_interactor/state.rb +87 -0
- data/lib/actioninteractor.rb +3 -0
- data/test/base_test.rb +8 -2
- data/test/composite_test.rb +92 -0
- data/test/execution_state_test.rb +60 -0
- data/test/inheritance_test.rb +19 -7
- metadata +10 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6482218b9fe304483abc4ae16d38e51c8de0cd6b9fe9c1155caaca1bff6a660c
|
4
|
+
data.tar.gz: 98db252d344409893580173b7f982419db14986a598e7b772eba8bca22ce5ed6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb962e73b235f0ebe37c906d00904ee71e1efce001eeef1d3e756317c9994cc2473443629b538451c25024aeb6b6fe949b0542f0a5c324aeb92fa4fe10e9377b
|
7
|
+
data.tar.gz: 6fa15f43b82685f294d5e63a5a01fdde4775cae10405c99023c48aa698ce79da9dc7ba246a337221869037e17bd9e7e8031a07ef83c2e74eb4ab1ef6d66a027d
|
@@ -14,24 +14,25 @@ module ActionInteractor
|
|
14
14
|
#
|
15
15
|
# class RegistrationInteractor < ActionInteractor::Base
|
16
16
|
# def execute
|
17
|
-
# return
|
17
|
+
# return failure! unless payload[:name]
|
18
18
|
# user = User.create!(name: payload[:name])
|
19
19
|
# notiticaion = user.notifications.create!(name: 'Welcome')
|
20
20
|
# RegistrationNotificationJob.perform_later!
|
21
21
|
# results.add(:user, user)
|
22
|
-
#
|
22
|
+
# successful!
|
23
23
|
# end
|
24
24
|
# end
|
25
25
|
class Base
|
26
|
-
attr_reader :payload, :errors, :results
|
26
|
+
attr_reader :payload, :errors, :results, :state, :interactor_name
|
27
27
|
|
28
28
|
# Initialize with payload
|
29
29
|
# Errors and Results data and initial state will be set.
|
30
30
|
def initialize(payload)
|
31
31
|
@payload = payload
|
32
|
-
@errors = Errors.new
|
33
|
-
@results = Results.new
|
34
|
-
|
32
|
+
@errors = payload[:errors] || Errors.new
|
33
|
+
@results = payload[:results] || Results.new
|
34
|
+
@state = payload[:state] || ExecutionState.new
|
35
|
+
@interactor_name = payload[:interactor_name] || underscore(self.class.name)
|
35
36
|
end
|
36
37
|
|
37
38
|
# Execute the operation with given payload.
|
@@ -39,24 +40,24 @@ module ActionInteractor
|
|
39
40
|
def execute
|
40
41
|
# if the interactor already finished execution, do nothing.
|
41
42
|
return if finished?
|
42
|
-
# if contract is not satisfied= (ex: payload is empty), mark as
|
43
|
-
return
|
43
|
+
# if contract is not satisfied= (ex: payload is empty), mark as failure.
|
44
|
+
return failure! if payload.nil?
|
44
45
|
# (Implement some codes for the operation.)
|
45
46
|
|
46
|
-
# if finished execution, mark as
|
47
|
-
|
47
|
+
# if finished execution, mark as successful.
|
48
|
+
successful!
|
48
49
|
end
|
49
50
|
|
50
51
|
# Execute the operation with given payload.
|
51
52
|
# If there are some errors, ActionInteractor::ExeuctionError will be raised.
|
52
53
|
def execute!
|
53
54
|
execute
|
54
|
-
|
55
|
+
successful? || raise(ExecutionError.new("Failed to execute the interactor"))
|
55
56
|
end
|
56
57
|
|
57
58
|
# Returns `true` if marked as finished otherwise `false`.
|
58
59
|
def finished?
|
59
|
-
|
60
|
+
state.successful? || state.failure?
|
60
61
|
end
|
61
62
|
|
62
63
|
# Returns `true` if not marked as finished otherwise `false`.
|
@@ -65,44 +66,46 @@ module ActionInteractor
|
|
65
66
|
end
|
66
67
|
|
67
68
|
# Returns `true` if marked as success and there are no errors otherwise `false`.
|
68
|
-
def
|
69
|
-
|
69
|
+
def successful?
|
70
|
+
state.successful? && @errors.empty?
|
70
71
|
end
|
71
72
|
|
73
|
+
alias_method :success?, :successful?
|
74
|
+
|
72
75
|
# Returns `true` if not marked as success or there are some errors otherwise `false`.
|
73
76
|
def failure?
|
74
|
-
!
|
77
|
+
!successful?
|
75
78
|
end
|
76
79
|
|
77
80
|
# Returns `true` if the operation was not successful and not finished otherwise `false`.
|
78
81
|
def aborted?
|
79
|
-
|
82
|
+
state.aborted?
|
80
83
|
end
|
81
84
|
|
82
85
|
# Reset statuses.
|
83
86
|
def reset!
|
84
|
-
@
|
85
|
-
@_finished = false
|
87
|
+
@state = State.new
|
86
88
|
end
|
87
89
|
|
88
|
-
# Mark the operation as
|
90
|
+
# Mark the operation as aborted.
|
89
91
|
def abort!
|
90
|
-
|
91
|
-
@_finished = false
|
92
|
+
state.aborted!
|
92
93
|
end
|
93
94
|
|
94
|
-
# Mark the operation as
|
95
|
-
def
|
96
|
-
|
97
|
-
@_finished = true
|
95
|
+
# Mark the operation as successful.
|
96
|
+
def successful!
|
97
|
+
state.successful!
|
98
98
|
end
|
99
99
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
100
|
+
alias_method :success!, :successful!
|
101
|
+
|
102
|
+
# Mask the operation as failure.
|
103
|
+
def failure!
|
104
|
+
state.failure!
|
104
105
|
end
|
105
106
|
|
107
|
+
alias_method :fail!, :failure!
|
108
|
+
|
106
109
|
class << self
|
107
110
|
# Execute the operation with given payload.
|
108
111
|
def execute(payload)
|
@@ -115,6 +118,16 @@ module ActionInteractor
|
|
115
118
|
new(payload).tap(&:execute!)
|
116
119
|
end
|
117
120
|
end
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
def underscore(name)
|
125
|
+
name.gsub(/::/, "__")
|
126
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
127
|
+
.gsub(/([a-z\d])([A-Z])/,'\1_\2')
|
128
|
+
.tr("-", "_")
|
129
|
+
.downcase
|
130
|
+
end
|
118
131
|
end
|
119
132
|
|
120
133
|
class ExecutionError < StandardError; end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionInteractor
|
4
|
+
class Composite < Base
|
5
|
+
# == Action \Interactor \Composite
|
6
|
+
#
|
7
|
+
# An interactor class which containing multiple interactors
|
8
|
+
# using the composite pattern.
|
9
|
+
#
|
10
|
+
# It can be used for execute multiple operations and it will be
|
11
|
+
# marked as successful if all operations executed successful.
|
12
|
+
# (otherwise it will be marked as failure.)
|
13
|
+
attr_reader :interactors
|
14
|
+
|
15
|
+
# Initialize with payload and an array for containing interactors.
|
16
|
+
def initialize(payload)
|
17
|
+
super
|
18
|
+
@interactors = []
|
19
|
+
end
|
20
|
+
|
21
|
+
# Execute containing interactors' `execute` method with given payload.
|
22
|
+
def execute
|
23
|
+
return if finished?
|
24
|
+
return failure! if payload.nil?
|
25
|
+
|
26
|
+
interactors.each_with_index do |interactor, index|
|
27
|
+
execute_sub_interactor(interactor, index)
|
28
|
+
return failure! if interactor.failure?
|
29
|
+
end
|
30
|
+
|
31
|
+
successful!
|
32
|
+
end
|
33
|
+
|
34
|
+
# Add an interactor to the interactors array.
|
35
|
+
def add(interactor)
|
36
|
+
interactors << interactor
|
37
|
+
end
|
38
|
+
|
39
|
+
# Delete the interactor from the interactors array.
|
40
|
+
def delete(interactor)
|
41
|
+
interactors.delete(interactor)
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def execute_sub_interactor(interactor, index)
|
47
|
+
interactor.execute
|
48
|
+
if interactor.successful?
|
49
|
+
interactor.results.each_pair do |attr_name, value|
|
50
|
+
results.add(sub_attr_key(interactor, index, attr_name), value)
|
51
|
+
end
|
52
|
+
else interactor.failure?
|
53
|
+
interactor.errors.each_pair do |attr_name, value|
|
54
|
+
errors.add(sub_attr_key(interactor, index, attr_name), value)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def sub_attr_key(interactor, index, attr_name)
|
60
|
+
"#{interactor.interactor_name}_#{index}__#{attr_name}".to_sym
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionInteractor
|
4
|
+
# == Action \Interactor \Execution \State
|
5
|
+
#
|
6
|
+
# State machine used in `ActionInteractor::Base`
|
7
|
+
class ExecutionState < State
|
8
|
+
# Define default states
|
9
|
+
STATES = [
|
10
|
+
:initial, # Initial state
|
11
|
+
:processing, # The operation is processing
|
12
|
+
:successful, # The operation is finished successfully
|
13
|
+
:failure, # The operation is failed
|
14
|
+
:aborted, # The operation is aborted
|
15
|
+
]
|
16
|
+
|
17
|
+
# Define default transitions
|
18
|
+
# key: target state, value: original states
|
19
|
+
TRANSITIONS = {
|
20
|
+
initial: [:processing],
|
21
|
+
processing: [:initial],
|
22
|
+
successful: [:initial, :processing],
|
23
|
+
failure: [:initial, :processing],
|
24
|
+
aborted: [:initial, :processing],
|
25
|
+
}
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionInteractor
|
4
|
+
# == Action \Interactor \State
|
5
|
+
#
|
6
|
+
# Simple state machine for general purpose.
|
7
|
+
# You can declare STATES / TRANSITIONS in subclasses for
|
8
|
+
# customizing the behavior.
|
9
|
+
# See also `ActionInteractor::ExecutionState`
|
10
|
+
class State
|
11
|
+
# Define default states
|
12
|
+
STATES = [:initial, :finished]
|
13
|
+
|
14
|
+
# Define default transitions
|
15
|
+
# key: target state, value: original states
|
16
|
+
TRANSITIONS = {
|
17
|
+
finished: [:initial]
|
18
|
+
}
|
19
|
+
|
20
|
+
attr_reader :state
|
21
|
+
|
22
|
+
def initialize(initial_state=nil)
|
23
|
+
@state = initial_state || default_state
|
24
|
+
end
|
25
|
+
|
26
|
+
# Default initial state
|
27
|
+
# (You can override in subclasses.)
|
28
|
+
def default_state
|
29
|
+
:initial
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns true if transition to target_state from current state
|
33
|
+
def valid_transition?(target_state)
|
34
|
+
transitions[target_state].include?(state)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Available states for the instance
|
38
|
+
def states
|
39
|
+
self.class.states
|
40
|
+
end
|
41
|
+
|
42
|
+
# Avaiolable transitions for the instance's states
|
43
|
+
def transitions
|
44
|
+
self.class.transitions
|
45
|
+
end
|
46
|
+
|
47
|
+
# Available states for the class
|
48
|
+
def self.states
|
49
|
+
self::STATES
|
50
|
+
end
|
51
|
+
|
52
|
+
# Available transitions for the class
|
53
|
+
def self.transitions
|
54
|
+
self::TRANSITIONS
|
55
|
+
end
|
56
|
+
|
57
|
+
def method_missing(method_name, *args)
|
58
|
+
name = method_name.to_s
|
59
|
+
# Returns true if state_name is the same as current state
|
60
|
+
if status_method_with_suffix?(name, "?")
|
61
|
+
return state == name.chop.to_sym
|
62
|
+
end
|
63
|
+
|
64
|
+
# Set current state to the state_name, otherwise raises error
|
65
|
+
if status_method_with_suffix?(name, "!")
|
66
|
+
state_name = name.chop.to_sym
|
67
|
+
unless valid_transition?(state_name)
|
68
|
+
raise TransitionError.new("Could not change state :#{state_name} from :#{state}")
|
69
|
+
end
|
70
|
+
@state = state_name
|
71
|
+
return
|
72
|
+
end
|
73
|
+
|
74
|
+
super
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def status_method_with_suffix?(method_name, suffix)
|
80
|
+
return false unless method_name.end_with?(suffix)
|
81
|
+
states.include?(method_name.chop.to_sym)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Error for invalid transitions
|
85
|
+
class TransitionError < StandardError; end
|
86
|
+
end
|
87
|
+
end
|
data/lib/actioninteractor.rb
CHANGED
@@ -6,4 +6,7 @@ module ActionInteractor
|
|
6
6
|
autoload :Base, "action_interactor/base"
|
7
7
|
autoload :Errors, "action_interactor/errors"
|
8
8
|
autoload :Results, "action_interactor/results"
|
9
|
+
autoload :State, "action_interactor/state"
|
10
|
+
autoload :ExecutionState, "action_interactor/execution_state"
|
11
|
+
autoload :Composite, "action_interactor/composite"
|
9
12
|
end
|
data/test/base_test.rb
CHANGED
@@ -33,7 +33,13 @@ class BaseTest < Test::Unit::TestCase
|
|
33
33
|
assert_instance_of(ActionInteractor::Results, interactor.results)
|
34
34
|
end
|
35
35
|
|
36
|
-
test "#
|
36
|
+
test "#successful? is true" do
|
37
|
+
payload = {}
|
38
|
+
interactor = ActionInteractor::Base.execute(payload)
|
39
|
+
assert interactor.successful?
|
40
|
+
end
|
41
|
+
|
42
|
+
test "#success? (alias) is true" do
|
37
43
|
payload = {}
|
38
44
|
interactor = ActionInteractor::Base.execute(payload)
|
39
45
|
assert interactor.success?
|
@@ -47,7 +53,7 @@ class BaseTest < Test::Unit::TestCase
|
|
47
53
|
|
48
54
|
test "#aborted? is true after #abort!" do
|
49
55
|
payload = {}
|
50
|
-
interactor = ActionInteractor::Base.
|
56
|
+
interactor = ActionInteractor::Base.new(payload)
|
51
57
|
interactor.abort!
|
52
58
|
assert interactor.aborted?
|
53
59
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require_relative "../lib/actioninteractor"
|
3
|
+
|
4
|
+
class ChiefInteractor < ActionInteractor::Composite
|
5
|
+
end
|
6
|
+
|
7
|
+
class CookInteractor < ActionInteractor::Base
|
8
|
+
def execute
|
9
|
+
results.add(:steak, "Juicy beaf steak")
|
10
|
+
successful!
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class ArrangeInteractor < ActionInteractor::Base
|
15
|
+
attr_reader :broken_dish
|
16
|
+
|
17
|
+
def initialize(payload)
|
18
|
+
super
|
19
|
+
@broken_dish = payload[:broken_dish].nil? ? false : payload[:broken_dish]
|
20
|
+
end
|
21
|
+
|
22
|
+
def execute
|
23
|
+
if broken_dish
|
24
|
+
errors.add(:dish, "Broken dish")
|
25
|
+
failure!
|
26
|
+
else
|
27
|
+
successful!
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
class CompositeTest < Test::Unit::TestCase
|
34
|
+
test "initialized successfully" do
|
35
|
+
payload = {}
|
36
|
+
interactor = ActionInteractor::Composite.new(payload)
|
37
|
+
assert_equal(interactor.success?, false)
|
38
|
+
assert_equal(interactor.finished?, false)
|
39
|
+
assert_equal(interactor.errors.empty?, true)
|
40
|
+
end
|
41
|
+
|
42
|
+
test "add interactors" do
|
43
|
+
payload = {}
|
44
|
+
chief_interactor = ChiefInteractor.new(payload)
|
45
|
+
cook_interactor = CookInteractor.new(interactor_name: "cook")
|
46
|
+
arrange_interactor = ArrangeInteractor.new(interactor_name: "arrange")
|
47
|
+
chief_interactor.add(cook_interactor)
|
48
|
+
chief_interactor.add(arrange_interactor)
|
49
|
+
interactor_names = chief_interactor.interactors.map(&:interactor_name)
|
50
|
+
assert_equal(interactor_names, %w[cook arrange])
|
51
|
+
end
|
52
|
+
|
53
|
+
test "remove interactor" do
|
54
|
+
payload = {}
|
55
|
+
chief_interactor = ChiefInteractor.new(payload)
|
56
|
+
cook_interactor = CookInteractor.new(interactor_name: "cook")
|
57
|
+
arrange_interactor = ArrangeInteractor.new(interactor_name: "arrange")
|
58
|
+
chief_interactor.add(cook_interactor)
|
59
|
+
chief_interactor.add(arrange_interactor)
|
60
|
+
chief_interactor.delete(cook_interactor)
|
61
|
+
interactor_names = chief_interactor.interactors.map(&:interactor_name)
|
62
|
+
assert_equal(interactor_names, %w[arrange])
|
63
|
+
end
|
64
|
+
|
65
|
+
test "successful in executing all interactors" do
|
66
|
+
payload = {}
|
67
|
+
chief_interactor = ChiefInteractor.new(payload)
|
68
|
+
cook_interactor = CookInteractor.new(interactor_name: "cook")
|
69
|
+
arrange_interactor = ArrangeInteractor.new(interactor_name: "arrange")
|
70
|
+
chief_interactor.add(cook_interactor)
|
71
|
+
chief_interactor.add(arrange_interactor)
|
72
|
+
chief_interactor.execute
|
73
|
+
assert_equal(chief_interactor.successful?, true)
|
74
|
+
assert_equal(chief_interactor.results.keys, [:cook_0__steak])
|
75
|
+
assert_equal(chief_interactor.results[:cook_0__steak], "Juicy beaf steak")
|
76
|
+
end
|
77
|
+
|
78
|
+
test "failure in executing the last interactor" do
|
79
|
+
payload = {}
|
80
|
+
chief_interactor = ChiefInteractor.new(payload)
|
81
|
+
cook_interactor = CookInteractor.new(interactor_name: "cook")
|
82
|
+
arrange_interactor = ArrangeInteractor.new(interactor_name: "arrange", broken_dish: true)
|
83
|
+
chief_interactor.add(cook_interactor)
|
84
|
+
chief_interactor.add(arrange_interactor)
|
85
|
+
chief_interactor.execute
|
86
|
+
assert_equal(chief_interactor.successful?, false)
|
87
|
+
assert_equal(chief_interactor.results.keys, [:cook_0__steak])
|
88
|
+
assert_equal(chief_interactor.results[:cook_0__steak], "Juicy beaf steak")
|
89
|
+
assert_equal(chief_interactor.errors.keys, [:arrange_1__dish])
|
90
|
+
assert_equal(chief_interactor.errors[:arrange_1__dish], "Broken dish")
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require_relative "../lib/actioninteractor"
|
3
|
+
|
4
|
+
class ExecutionStateTest < Test::Unit::TestCase
|
5
|
+
test "initialized correctly" do
|
6
|
+
assert_nothing_raised { ActionInteractor::ExecutionState.new }
|
7
|
+
end
|
8
|
+
|
9
|
+
test "initial state is :initial" do
|
10
|
+
state = ActionInteractor::ExecutionState.new
|
11
|
+
assert_equal(state.state, :initial)
|
12
|
+
end
|
13
|
+
|
14
|
+
test "default states are :initial, :processing, :successful and :failure" do
|
15
|
+
state = ActionInteractor::ExecutionState.new
|
16
|
+
assert_equal(state.states, [:initial, :processing, :successful, :failure, :aborted])
|
17
|
+
end
|
18
|
+
|
19
|
+
test "default transitions are defined correctly" do
|
20
|
+
state = ActionInteractor::ExecutionState.new
|
21
|
+
assert_equal(
|
22
|
+
state.transitions,
|
23
|
+
{
|
24
|
+
initial: [:processing],
|
25
|
+
processing: [:initial],
|
26
|
+
successful: [:initial, :processing],
|
27
|
+
failure: [:initial, :processing],
|
28
|
+
aborted: [:initial, :processing],
|
29
|
+
}
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
test "able to change state from :initial to :processing" do
|
34
|
+
state = ActionInteractor::ExecutionState.new
|
35
|
+
assert_equal(state.initial?, true)
|
36
|
+
state.processing!
|
37
|
+
assert_equal(state.processing?, true)
|
38
|
+
end
|
39
|
+
|
40
|
+
test "able to change state from :processing to :successful" do
|
41
|
+
state = ActionInteractor::ExecutionState.new(:processing)
|
42
|
+
state.successful!
|
43
|
+
assert_equal(state.successful?, true)
|
44
|
+
end
|
45
|
+
|
46
|
+
test "able to change state from :initial to :failure" do
|
47
|
+
state = ActionInteractor::ExecutionState.new(:initial)
|
48
|
+
state.failure!
|
49
|
+
assert_equal(state.failure?, true)
|
50
|
+
end
|
51
|
+
|
52
|
+
test "raise TransitionError when try to change state from :successful to :failure" do
|
53
|
+
state = ActionInteractor::ExecutionState.new(:successful)
|
54
|
+
assert_equal(state.valid_transition?(:failure), false)
|
55
|
+
error = assert_raises ActionInteractor::ExecutionState::TransitionError do
|
56
|
+
state.failure!
|
57
|
+
end
|
58
|
+
assert_equal("Could not change state :failure from :successful", error.message)
|
59
|
+
end
|
60
|
+
end
|
data/test/inheritance_test.rb
CHANGED
@@ -13,10 +13,10 @@ class RegistrationInteractor < ActionInteractor::Base
|
|
13
13
|
def execute
|
14
14
|
unless payload[:name]
|
15
15
|
errors.add(:name, "can't be blank.")
|
16
|
-
return
|
16
|
+
return failure!
|
17
17
|
end
|
18
18
|
results.add(:user, User.new(name: payload[:name]))
|
19
|
-
|
19
|
+
successful!
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
@@ -24,10 +24,10 @@ class NotificationInteractor < ActionInteractor::Base
|
|
24
24
|
def execute
|
25
25
|
errors.add(:name, "can't be blank.") unless payload[:name]
|
26
26
|
errors.add(:email, "can't be blank.") unless payload[:email]
|
27
|
-
return
|
27
|
+
return failure! if errors.any?
|
28
28
|
results.add(:name, payload[:name])
|
29
29
|
results.add(:email, payload[:email])
|
30
|
-
|
30
|
+
successful!
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
@@ -38,6 +38,18 @@ class InheritanceTest < Test::Unit::TestCase
|
|
38
38
|
assert_nothing_raised { RegistrationInteractor.execute(payload) }
|
39
39
|
end
|
40
40
|
|
41
|
+
test "returns 'registration_interactor' as default interactor name" do
|
42
|
+
payload = { name: 'John'}
|
43
|
+
interactor = RegistrationInteractor.new(payload)
|
44
|
+
assert_equal('registration_interactor', interactor.interactor_name)
|
45
|
+
end
|
46
|
+
|
47
|
+
test "returns 'registration' as specified interactor name" do
|
48
|
+
payload = { name: 'John', interactor_name: 'registration' }
|
49
|
+
interactor = RegistrationInteractor.new(payload)
|
50
|
+
assert_equal('registration', interactor.interactor_name)
|
51
|
+
end
|
52
|
+
|
41
53
|
test ".execute returns an RegistrationInteractor instance" do
|
42
54
|
payload = { name: 'John'}
|
43
55
|
interactor = RegistrationInteractor.execute(payload)
|
@@ -57,10 +69,10 @@ class InheritanceTest < Test::Unit::TestCase
|
|
57
69
|
assert_equal(user.name, 'John')
|
58
70
|
end
|
59
71
|
|
60
|
-
test "#
|
72
|
+
test "#successful? is true" do
|
61
73
|
payload = { name: 'John'}
|
62
74
|
interactor = RegistrationInteractor.execute(payload)
|
63
|
-
assert interactor.
|
75
|
+
assert interactor.successful?
|
64
76
|
end
|
65
77
|
|
66
78
|
test "#finished? is true" do
|
@@ -122,7 +134,7 @@ class InheritanceTest < Test::Unit::TestCase
|
|
122
134
|
test "if only the name is given, the registration is successful but the notification is not." do
|
123
135
|
payload = { name: 'Taro' }
|
124
136
|
registration = RegistrationInteractor.execute(payload)
|
125
|
-
assert registration.
|
137
|
+
assert registration.successful?
|
126
138
|
assert registration.errors.empty?
|
127
139
|
notification = NotificationInteractor.execute(payload)
|
128
140
|
assert notification.failure?
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: actioninteractor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryo Hashimoto
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-04-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -62,11 +62,16 @@ files:
|
|
62
62
|
- Rakefile
|
63
63
|
- actioninteractor.gemspec
|
64
64
|
- lib/action_interactor/base.rb
|
65
|
+
- lib/action_interactor/composite.rb
|
65
66
|
- lib/action_interactor/errors.rb
|
67
|
+
- lib/action_interactor/execution_state.rb
|
66
68
|
- lib/action_interactor/results.rb
|
69
|
+
- lib/action_interactor/state.rb
|
67
70
|
- lib/actioninteractor.rb
|
68
71
|
- test/base_test.rb
|
72
|
+
- test/composite_test.rb
|
69
73
|
- test/errors_test.rb
|
74
|
+
- test/execution_state_test.rb
|
70
75
|
- test/inheritance_test.rb
|
71
76
|
- test/results_test.rb
|
72
77
|
homepage: https://github.com/ryohashimoto/lightrails
|
@@ -88,13 +93,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
93
|
- !ruby/object:Gem::Version
|
89
94
|
version: 1.8.11
|
90
95
|
requirements: []
|
91
|
-
rubygems_version: 3.
|
96
|
+
rubygems_version: 3.1.4
|
92
97
|
signing_key:
|
93
98
|
specification_version: 4
|
94
99
|
summary: Action Interactor provides a simple interface for performing operations (part
|
95
100
|
of Lightrails).
|
96
101
|
test_files:
|
97
102
|
- test/base_test.rb
|
103
|
+
- test/composite_test.rb
|
98
104
|
- test/errors_test.rb
|
105
|
+
- test/execution_state_test.rb
|
99
106
|
- test/inheritance_test.rb
|
100
107
|
- test/results_test.rb
|