interactor 3.0.0 → 3.0.1
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/CHANGELOG.md +4 -0
- data/CONTRIBUTING.md +1 -1
- data/interactor.gemspec +1 -1
- data/lib/interactor.rb +116 -0
- data/lib/interactor/context.rb +144 -0
- data/lib/interactor/error.rb +21 -0
- data/lib/interactor/hooks.rb +137 -0
- data/lib/interactor/organizer.rb +54 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eef8d6afd5557c08a2400afb30b40209bb17fec5
|
4
|
+
data.tar.gz: 8513cec42b1bbb273b96803ec06cce6144a4078f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 856f697f4443750d4fe95473ca44674669a8148582c5bff2dbff5ecd46d4ff5626b42c216eb4247c909c4d9bba0511d5a8bbfb50f9a6432f23f88c2a40d6be9f
|
7
|
+
data.tar.gz: 3ebed0429d15e0d9faa85d345523e0f0d9c3adf90ece48c0105761f8fbc1aea833fa718f07c2a362e194499bae18f79fe1309c14d55d720b6c9183c8a576326a
|
data/CHANGELOG.md
CHANGED
data/CONTRIBUTING.md
CHANGED
data/interactor.gemspec
CHANGED
data/lib/interactor.rb
CHANGED
@@ -3,35 +3,141 @@ require "interactor/error"
|
|
3
3
|
require "interactor/hooks"
|
4
4
|
require "interactor/organizer"
|
5
5
|
|
6
|
+
# Public: Interactor methods. Because Interactor is a module, custom Interactor
|
7
|
+
# classes should include Interactor rather than inherit from it.
|
8
|
+
#
|
9
|
+
# Examples
|
10
|
+
#
|
11
|
+
# class MyInteractor
|
12
|
+
# include Interactor
|
13
|
+
#
|
14
|
+
# def call
|
15
|
+
# puts context.foo
|
16
|
+
# end
|
17
|
+
# end
|
6
18
|
module Interactor
|
19
|
+
# Internal: Install Interactor's behavior in the given class.
|
7
20
|
def self.included(base)
|
8
21
|
base.class_eval do
|
9
22
|
extend ClassMethods
|
10
23
|
include Hooks
|
11
24
|
|
25
|
+
# Public: Gets the Interactor::Context of the Interactor instance.
|
12
26
|
attr_reader :context
|
13
27
|
end
|
14
28
|
end
|
15
29
|
|
30
|
+
# Internal: Interactor class methods.
|
16
31
|
module ClassMethods
|
32
|
+
# Public: Invoke an Interactor. This is the primary public API method to an
|
33
|
+
# interactor.
|
34
|
+
#
|
35
|
+
# context - A Hash whose key/value pairs are used in initializing a new
|
36
|
+
# Interactor::Context object. An existing Interactor::Context may
|
37
|
+
# also be given. (default: {})
|
38
|
+
#
|
39
|
+
# Examples
|
40
|
+
#
|
41
|
+
# MyInteractor.call(foo: "bar")
|
42
|
+
# # => #<Interactor::Context foo="bar">
|
43
|
+
#
|
44
|
+
# MyInteractor.call
|
45
|
+
# # => #<Interactor::Context>
|
46
|
+
#
|
47
|
+
# Returns the resulting Interactor::Context after manipulation by the
|
48
|
+
# interactor.
|
17
49
|
def call(context = {})
|
18
50
|
new(context).tap(&:run).context
|
19
51
|
end
|
20
52
|
|
53
|
+
# Public: Invoke an Interactor. The "call!" method behaves identically to
|
54
|
+
# the "call" method with one notable exception. If the context is failed
|
55
|
+
# during invocation of the interactor, the Interactor::Failure is raised.
|
56
|
+
#
|
57
|
+
# context - A Hash whose key/value pairs are used in initializing a new
|
58
|
+
# Interactor::Context object. An existing Interactor::Context may
|
59
|
+
# also be given. (default: {})
|
60
|
+
#
|
61
|
+
# Examples
|
62
|
+
#
|
63
|
+
# MyInteractor.call!(foo: "bar")
|
64
|
+
# # => #<Interactor::Context foo="bar">
|
65
|
+
#
|
66
|
+
# MyInteractor.call!
|
67
|
+
# # => #<Interactor::Context>
|
68
|
+
#
|
69
|
+
# MyInteractor.call!(foo: "baz")
|
70
|
+
# # => Interactor::Failure: #<Interactor::Context foo="baz">
|
71
|
+
#
|
72
|
+
# Returns the resulting Interactor::Context after manipulation by the
|
73
|
+
# interactor.
|
74
|
+
# Raises Interactor::Failure if the context is failed.
|
21
75
|
def call!(context = {})
|
22
76
|
new(context).tap(&:run!).context
|
23
77
|
end
|
24
78
|
end
|
25
79
|
|
80
|
+
# Internal: Initialize an Interactor.
|
81
|
+
#
|
82
|
+
# context - A Hash whose key/value pairs are used in initializing the
|
83
|
+
# interactor's context. An existing Interactor::Context may also be
|
84
|
+
# given. (default: {})
|
85
|
+
#
|
86
|
+
# Examples
|
87
|
+
#
|
88
|
+
# MyInteractor.new(foo: "bar")
|
89
|
+
# # => #<MyInteractor @context=#<Interactor::Context foo="bar">>
|
90
|
+
#
|
91
|
+
# MyInteractor.new
|
92
|
+
# # => #<MyInteractor @context=#<Interactor::Context>>
|
26
93
|
def initialize(context = {})
|
27
94
|
@context = Context.build(context)
|
28
95
|
end
|
29
96
|
|
97
|
+
# Internal: Invoke an interactor instance along with all defined hooks. The
|
98
|
+
# "run" method is used internally by the "call" class method. The following
|
99
|
+
# are equivalent:
|
100
|
+
#
|
101
|
+
# MyInteractor.call(foo: "bar")
|
102
|
+
# # => #<Interactor::Context foo="bar">
|
103
|
+
#
|
104
|
+
# interactor = MyInteractor.new(foo: "bar")
|
105
|
+
# interactor.run
|
106
|
+
# interactor.context
|
107
|
+
# # => #<Interactor::Context foo="bar">
|
108
|
+
#
|
109
|
+
# After successful invocation of the interactor, the instance is tracked
|
110
|
+
# within the context. If the context is failed or any error is raised, the
|
111
|
+
# context is rolled back.
|
112
|
+
#
|
113
|
+
# Returns nothing.
|
30
114
|
def run
|
31
115
|
run!
|
32
116
|
rescue Failure
|
33
117
|
end
|
34
118
|
|
119
|
+
# Internal: Invoke an Interactor instance along with all defined hooks. The
|
120
|
+
# "run!" method is used internally by the "call!" class method. The following
|
121
|
+
# are equivalent:
|
122
|
+
#
|
123
|
+
# MyInteractor.call!(foo: "bar")
|
124
|
+
# # => #<Interactor::Context foo="bar">
|
125
|
+
#
|
126
|
+
# interactor = MyInteractor.new(foo: "bar")
|
127
|
+
# interactor.run!
|
128
|
+
# interactor.context
|
129
|
+
# # => #<Interactor::Context foo="bar">
|
130
|
+
#
|
131
|
+
# After successful invocation of the interactor, the instance is tracked
|
132
|
+
# within the context. If the context is failed or any error is raised, the
|
133
|
+
# context is rolled back.
|
134
|
+
#
|
135
|
+
# The "run!" method behaves identically to the "run" method with one notable
|
136
|
+
# exception. If the context is failed during invocation of the interactor,
|
137
|
+
# the Interactor::Failure is raised.
|
138
|
+
#
|
139
|
+
# Returns nothing.
|
140
|
+
# Raises Interactor::Failure if the context is failed.
|
35
141
|
def run!
|
36
142
|
with_hooks do
|
37
143
|
call
|
@@ -42,9 +148,19 @@ module Interactor
|
|
42
148
|
raise
|
43
149
|
end
|
44
150
|
|
151
|
+
# Public: Invoke an Interactor instance without any hooks, tracking, or
|
152
|
+
# rollback. It is expected that the "call" instance method is overwritten for
|
153
|
+
# each interactor class.
|
154
|
+
#
|
155
|
+
# Returns nothing.
|
45
156
|
def call
|
46
157
|
end
|
47
158
|
|
159
|
+
# Public: Reverse prior invocation of an Interactor instance. Any interactor
|
160
|
+
# class that requires undoing upon downstream failure is expected to overwrite
|
161
|
+
# the "rollback" instance method.
|
162
|
+
#
|
163
|
+
# Returns nothing.
|
48
164
|
def rollback
|
49
165
|
end
|
50
166
|
end
|
data/lib/interactor/context.rb
CHANGED
@@ -1,35 +1,179 @@
|
|
1
1
|
require "ostruct"
|
2
2
|
|
3
3
|
module Interactor
|
4
|
+
# Public: The object for tracking state of an Interactor's invocation. The
|
5
|
+
# context is used to initialize the interactor with the information required
|
6
|
+
# for invocation. The interactor manipulates the context to produce the result
|
7
|
+
# of invocation.
|
8
|
+
#
|
9
|
+
# The context is the mechanism by which success and failure are determined and
|
10
|
+
# the context is responsible for tracking individual interactor invocations
|
11
|
+
# for the purpose of rollback.
|
12
|
+
#
|
13
|
+
# The context may be maniupulated using arbitrary getter and setter methods.
|
14
|
+
#
|
15
|
+
# Examples
|
16
|
+
#
|
17
|
+
# context = Interactor::Context.new
|
18
|
+
# # => #<Interactor::Context>
|
19
|
+
# context.foo = "bar"
|
20
|
+
# # => "bar"
|
21
|
+
# context
|
22
|
+
# # => #<Interactor::Context foo="bar">
|
23
|
+
# context.hello = "world"
|
24
|
+
# # => "world"
|
25
|
+
# context
|
26
|
+
# # => #<Interactor::Context foo="bar" hello="world">
|
27
|
+
# context.foo = "baz"
|
28
|
+
# # => "baz"
|
29
|
+
# context
|
30
|
+
# # => #<Interactor::Context foo="baz" hello="world">
|
4
31
|
class Context < OpenStruct
|
32
|
+
# Internal: Initialize an Interactor::Context or preserve an existing one.
|
33
|
+
# If the argument given is an Interactor::Context, the argument is returned.
|
34
|
+
# Otherwise, a new Interactor::Context is initialized from the provided
|
35
|
+
# hash.
|
36
|
+
#
|
37
|
+
# The "build" method is used during interactor initialization.
|
38
|
+
#
|
39
|
+
# context - A Hash whose key/value pairs are used in initializing a new
|
40
|
+
# Interactor::Context object. If an existing Interactor::Context
|
41
|
+
# is given, it is simply returned. (default: {})
|
42
|
+
#
|
43
|
+
# Examples
|
44
|
+
#
|
45
|
+
# context = Interactor::Context.build(foo: "bar")
|
46
|
+
# # => #<Interactor::Context foo="bar">
|
47
|
+
# context.object_id
|
48
|
+
# # => 2170969340
|
49
|
+
# context = Interactor::Context.build(context)
|
50
|
+
# # => #<Interactor::Context foo="bar">
|
51
|
+
# context.object_id
|
52
|
+
# # => 2170969340
|
53
|
+
#
|
54
|
+
# Returns the Interactor::Context.
|
5
55
|
def self.build(context = {})
|
6
56
|
self === context ? context : new(context)
|
7
57
|
end
|
8
58
|
|
59
|
+
# Public: Whether the Interactor::Context is successful. By default, a new
|
60
|
+
# context is successful and only changes when explicitly failed.
|
61
|
+
#
|
62
|
+
# The "success?" method is the inverse of the "failure?" method.
|
63
|
+
#
|
64
|
+
# Examples
|
65
|
+
#
|
66
|
+
# context = Interactor::Context.new
|
67
|
+
# # => #<Interactor::Context>
|
68
|
+
# context.success?
|
69
|
+
# # => true
|
70
|
+
# context.fail!
|
71
|
+
# # => Interactor::Failure: #<Interactor::Context>
|
72
|
+
# context.success?
|
73
|
+
# # => false
|
74
|
+
#
|
75
|
+
# Returns true by default or false if failed.
|
9
76
|
def success?
|
10
77
|
!failure?
|
11
78
|
end
|
12
79
|
|
80
|
+
# Public: Whether the Interactor::Context has failed. By default, a new
|
81
|
+
# context is successful and only changes when explicitly failed.
|
82
|
+
#
|
83
|
+
# The "failure?" method is the inverse of the "success?" method.
|
84
|
+
#
|
85
|
+
# Examples
|
86
|
+
#
|
87
|
+
# context = Interactor::Context.new
|
88
|
+
# # => #<Interactor::Context>
|
89
|
+
# context.failure?
|
90
|
+
# # => false
|
91
|
+
# context.fail!
|
92
|
+
# # => Interactor::Failure: #<Interactor::Context>
|
93
|
+
# context.failure?
|
94
|
+
# # => true
|
95
|
+
#
|
96
|
+
# Returns false by default or true if failed.
|
13
97
|
def failure?
|
14
98
|
@failure || false
|
15
99
|
end
|
16
100
|
|
101
|
+
# Public: Fail the Interactor::Context. Failing a context raises an error
|
102
|
+
# that may be rescued by the calling interactor. The context is also flagged
|
103
|
+
# as having failed.
|
104
|
+
#
|
105
|
+
# Optionally the caller may provide a hash of key/value pairs to be merged
|
106
|
+
# into the context before failure.
|
107
|
+
#
|
108
|
+
# context - A Hash whose key/value pairs are merged into the existing
|
109
|
+
# Interactor::Context instance. (default: {})
|
110
|
+
#
|
111
|
+
# Examples
|
112
|
+
#
|
113
|
+
# context = Interactor::Context.new
|
114
|
+
# # => #<Interactor::Context>
|
115
|
+
# context.fail!
|
116
|
+
# # => Interactor::Failure: #<Interactor::Context>
|
117
|
+
# context.fail! rescue false
|
118
|
+
# # => false
|
119
|
+
# context.fail!(foo: "baz")
|
120
|
+
# # => Interactor::Failure: #<Interactor::Context foo="baz">
|
121
|
+
#
|
122
|
+
# Raises Interactor::Failure initialized with the Interactor::Context.
|
17
123
|
def fail!(context = {})
|
18
124
|
modifiable.update(context)
|
19
125
|
@failure = true
|
20
126
|
raise Failure, self
|
21
127
|
end
|
22
128
|
|
129
|
+
# Internal: Track that an Interactor has been called. The "called!" method
|
130
|
+
# is used by the interactor being invoked with this context. After an
|
131
|
+
# interactor is successfully called, the interactor instance is tracked in
|
132
|
+
# the context for the purpose of potential future rollback.
|
133
|
+
#
|
134
|
+
# interactor - An Interactor instance that has been successfully called.
|
135
|
+
#
|
136
|
+
# Returns nothing.
|
23
137
|
def called!(interactor)
|
24
138
|
_called << interactor
|
25
139
|
end
|
26
140
|
|
141
|
+
# Public: Roll back the Interactor::Context. Any interactors to which this
|
142
|
+
# context has been passed and which have been successfully called are asked
|
143
|
+
# to roll themselves back by invoking their "rollback" instance methods.
|
144
|
+
#
|
145
|
+
# Examples
|
146
|
+
#
|
147
|
+
# context = MyInteractor.call(foo: "bar")
|
148
|
+
# # => #<Interactor::Context foo="baz">
|
149
|
+
# context.rollback!
|
150
|
+
# # => true
|
151
|
+
# context
|
152
|
+
# # => #<Interactor::Context foo="bar">
|
153
|
+
#
|
154
|
+
# Returns true if rolled back successfully or false if already rolled back.
|
27
155
|
def rollback!
|
28
156
|
return false if @rolled_back
|
29
157
|
_called.reverse_each(&:rollback)
|
30
158
|
@rolled_back = true
|
31
159
|
end
|
32
160
|
|
161
|
+
# Internal: An Array of successfully called Interactor instances invoked
|
162
|
+
# against this Interactor::Context instance.
|
163
|
+
#
|
164
|
+
# Examples
|
165
|
+
#
|
166
|
+
# context = Interactor::Context.new
|
167
|
+
# # => #<Interactor::Context>
|
168
|
+
# context._called
|
169
|
+
# # => []
|
170
|
+
#
|
171
|
+
# context = MyInteractor.call(foo: "bar")
|
172
|
+
# # => #<Interactor::Context foo="baz">
|
173
|
+
# context._called
|
174
|
+
# # => [#<MyInteractor @context=#<Interactor::Context foo="baz">>]
|
175
|
+
#
|
176
|
+
# Returns an Array of Interactor instances or an empty Array.
|
33
177
|
def _called
|
34
178
|
@called ||= []
|
35
179
|
end
|
data/lib/interactor/error.rb
CHANGED
@@ -1,7 +1,28 @@
|
|
1
1
|
module Interactor
|
2
|
+
# Internal: Error raised during Interactor::Context failure. The error stores
|
3
|
+
# a copy of the failed context for debugging purposes.
|
2
4
|
class Failure < StandardError
|
5
|
+
# Internal: Gets the Interactor::Context of the Interactor::Failure
|
6
|
+
# instance.
|
3
7
|
attr_reader :context
|
4
8
|
|
9
|
+
# Internal: Initialize an Interactor::Failure.
|
10
|
+
#
|
11
|
+
# context - An Interactor::Context to be stored within the
|
12
|
+
# Interactor::Failure instance. (default: nil)
|
13
|
+
#
|
14
|
+
# Examples
|
15
|
+
#
|
16
|
+
# Interactor::Failure.new
|
17
|
+
# # => #<Interactor::Failure: Interactor::Failure>
|
18
|
+
#
|
19
|
+
# context = Interactor::Context.new(foo: "bar")
|
20
|
+
# # => #<Interactor::Context foo="bar">
|
21
|
+
# Interactor::Failure.new(context)
|
22
|
+
# # => #<Interactor::Failure: #<Interactor::Context foo="bar">>
|
23
|
+
#
|
24
|
+
# raise Interactor::Failure, context
|
25
|
+
# # => Interactor::Failure: #<Interactor::Context foo="bar">
|
5
26
|
def initialize(context = nil)
|
6
27
|
@context = context
|
7
28
|
super
|
data/lib/interactor/hooks.rb
CHANGED
@@ -1,26 +1,123 @@
|
|
1
1
|
module Interactor
|
2
|
+
# Internal: Methods relating to supporting hooks around Interactor invocation.
|
2
3
|
module Hooks
|
4
|
+
# Internal: Install Interactor's behavior in the given class.
|
3
5
|
def self.included(base)
|
4
6
|
base.class_eval do
|
5
7
|
extend ClassMethods
|
6
8
|
end
|
7
9
|
end
|
8
10
|
|
11
|
+
# Internal: Interactor::Hooks class methods.
|
9
12
|
module ClassMethods
|
13
|
+
# Public: Declare hooks to run before Interactor invocation. The before
|
14
|
+
# method may be called multiple times; subsequent calls append declared
|
15
|
+
# hooks to existing before hooks.
|
16
|
+
#
|
17
|
+
# hooks - Zero or more Symbol method names representing instance methods
|
18
|
+
# to be called before interactor invocation.
|
19
|
+
# block - An optional block to be executed as a hook. If given, the block
|
20
|
+
# is executed after methods corresponding to any given Symbols.
|
21
|
+
#
|
22
|
+
# Examples
|
23
|
+
#
|
24
|
+
# class MyInteractor
|
25
|
+
# include Interactor
|
26
|
+
#
|
27
|
+
# before :set_start_time
|
28
|
+
#
|
29
|
+
# before do
|
30
|
+
# puts "started"
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# def call
|
34
|
+
# puts "called"
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# private
|
38
|
+
#
|
39
|
+
# def set_start_time
|
40
|
+
# context.start_time = Time.now
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# Returns nothing.
|
10
45
|
def before(*hooks, &block)
|
11
46
|
hooks << block if block
|
12
47
|
hooks.each { |hook| before_hooks.push(hook) }
|
13
48
|
end
|
14
49
|
|
50
|
+
# Public: Declare hooks to run after Interactor invocation. The after
|
51
|
+
# method may be called multiple times; subsequent calls prepend declared
|
52
|
+
# hooks to existing after hooks.
|
53
|
+
#
|
54
|
+
# hooks - Zero or more Symbol method names representing instance methods
|
55
|
+
# to be called after interactor invocation.
|
56
|
+
# block - An optional block to be executed as a hook. If given, the block
|
57
|
+
# is executed before methods corresponding to any given Symbols.
|
58
|
+
#
|
59
|
+
# Examples
|
60
|
+
#
|
61
|
+
# class MyInteractor
|
62
|
+
# include Interactor
|
63
|
+
#
|
64
|
+
# after :set_finish_time
|
65
|
+
#
|
66
|
+
# after do
|
67
|
+
# puts "finished"
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
# def call
|
71
|
+
# puts "called"
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
# private
|
75
|
+
#
|
76
|
+
# def set_finish_time
|
77
|
+
# context.finish_time = Time.now
|
78
|
+
# end
|
79
|
+
# end
|
80
|
+
#
|
81
|
+
# Returns nothing.
|
15
82
|
def after(*hooks, &block)
|
16
83
|
hooks << block if block
|
17
84
|
hooks.each { |hook| after_hooks.unshift(hook) }
|
18
85
|
end
|
19
86
|
|
87
|
+
# Internal: An Array of declared hooks to run before Interactor
|
88
|
+
# invocation. The hooks appear in the order in which they will be run.
|
89
|
+
#
|
90
|
+
# Examples
|
91
|
+
#
|
92
|
+
# class MyInteractor
|
93
|
+
# include Interactor
|
94
|
+
#
|
95
|
+
# before :set_start_time, :say_hello
|
96
|
+
# end
|
97
|
+
#
|
98
|
+
# MyInteractor.before_hooks
|
99
|
+
# # => [:set_start_time, :say_hello]
|
100
|
+
#
|
101
|
+
# Returns an Array of Symbols and Procs.
|
20
102
|
def before_hooks
|
21
103
|
@before_hooks ||= []
|
22
104
|
end
|
23
105
|
|
106
|
+
# Internal: An Array of declared hooks to run before Interactor
|
107
|
+
# invocation. The hooks appear in the order in which they will be run.
|
108
|
+
#
|
109
|
+
# Examples
|
110
|
+
#
|
111
|
+
# class MyInteractor
|
112
|
+
# include Interactor
|
113
|
+
#
|
114
|
+
# after :set_finish_time, :say_goodbye
|
115
|
+
# end
|
116
|
+
#
|
117
|
+
# MyInteractor.after_hooks
|
118
|
+
# # => [:say_goodbye, :set_finish_time]
|
119
|
+
#
|
120
|
+
# Returns an Array of Symbols and Procs.
|
24
121
|
def after_hooks
|
25
122
|
@after_hooks ||= []
|
26
123
|
end
|
@@ -28,24 +125,64 @@ module Interactor
|
|
28
125
|
|
29
126
|
private
|
30
127
|
|
128
|
+
# Internal: Run before and after hooks around yielded execution. The
|
129
|
+
# required block is surrounded with hooks and executed.
|
130
|
+
#
|
131
|
+
# Examples
|
132
|
+
#
|
133
|
+
# class MyProcessor
|
134
|
+
# include Interactor::Hooks
|
135
|
+
#
|
136
|
+
# def process_with_hooks
|
137
|
+
# with_hooks do
|
138
|
+
# process
|
139
|
+
# end
|
140
|
+
# end
|
141
|
+
#
|
142
|
+
# def process
|
143
|
+
# puts "processed!"
|
144
|
+
# end
|
145
|
+
# end
|
146
|
+
#
|
147
|
+
# Returns nothing.
|
31
148
|
def with_hooks
|
32
149
|
run_before_hooks
|
33
150
|
yield
|
34
151
|
run_after_hooks
|
35
152
|
end
|
36
153
|
|
154
|
+
# Internal: Run before hooks.
|
155
|
+
#
|
156
|
+
# Returns nothing.
|
37
157
|
def run_before_hooks
|
38
158
|
run_hooks(self.class.before_hooks)
|
39
159
|
end
|
40
160
|
|
161
|
+
# Internal: Run after hooks.
|
162
|
+
#
|
163
|
+
# Returns nothing.
|
41
164
|
def run_after_hooks
|
42
165
|
run_hooks(self.class.after_hooks)
|
43
166
|
end
|
44
167
|
|
168
|
+
# Internal: Run a colection of hooks. The "run_hooks" method is the common
|
169
|
+
# interface by which collections of either before or after hooks are run.
|
170
|
+
#
|
171
|
+
# hooks - An Array of Symbol and Proc hooks.
|
172
|
+
#
|
173
|
+
# Returns nothing.
|
45
174
|
def run_hooks(hooks)
|
46
175
|
hooks.each { |hook| run_hook(hook) }
|
47
176
|
end
|
48
177
|
|
178
|
+
# Internal: Run an individual hook. The "run_hook" method is the common
|
179
|
+
# interface by which an individual hook is run. If the given hook is a
|
180
|
+
# symbol, the method is invoked whether public or private. If the hook is a
|
181
|
+
# proc, the proc is evaluated in the context of the current instance.
|
182
|
+
#
|
183
|
+
# hook - A Symbol or Proc hook.
|
184
|
+
#
|
185
|
+
# Returns nothing.
|
49
186
|
def run_hook(hook)
|
50
187
|
hook.is_a?(Symbol) ? send(hook) : instance_eval(&hook)
|
51
188
|
end
|
data/lib/interactor/organizer.rb
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
module Interactor
|
2
|
+
# Public: Interactor::Organizer methods. Because Interactor::Organizer is a
|
3
|
+
# module, custom Interactor::Organizer classes should include
|
4
|
+
# Interactor::Organizer rather than inherit from it.
|
5
|
+
#
|
6
|
+
# Examples
|
7
|
+
#
|
8
|
+
# class MyOrganizer
|
9
|
+
# include Interactor::Organizer
|
10
|
+
#
|
11
|
+
# organizer InteractorOne, InteractorTwo
|
12
|
+
# end
|
2
13
|
module Organizer
|
14
|
+
# Internal: Install Interactor::Organizer's behavior in the given class.
|
3
15
|
def self.included(base)
|
4
16
|
base.class_eval do
|
5
17
|
include Interactor
|
@@ -9,17 +21,59 @@ module Interactor
|
|
9
21
|
end
|
10
22
|
end
|
11
23
|
|
24
|
+
# Internal: Interactor::Organizer class methods.
|
12
25
|
module ClassMethods
|
26
|
+
# Public: Declare Interactors to be invoked as part of the
|
27
|
+
# Interactor::Organizer's invocation. These interactors will invoked in
|
28
|
+
# the order in which they are declared.
|
29
|
+
#
|
30
|
+
# interactors - Zero or more (or an Array of) Interactor classes.
|
31
|
+
#
|
32
|
+
# Examples
|
33
|
+
#
|
34
|
+
# class MyFirstOrganizer
|
35
|
+
# include Interactor::Organizer
|
36
|
+
#
|
37
|
+
# organize InteractorOne, InteractorTwo
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# class MySecondOrganizer
|
41
|
+
# include Interactor::Organizer
|
42
|
+
#
|
43
|
+
# organize [InteractorThree, InteractorFour]
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# Returns nothing.
|
13
47
|
def organize(*interactors)
|
14
48
|
@organized = interactors.flatten
|
15
49
|
end
|
16
50
|
|
51
|
+
# Internal: An Array of declared Interactors to be invoked.
|
52
|
+
#
|
53
|
+
# Examples
|
54
|
+
#
|
55
|
+
# class MyOrganizer
|
56
|
+
# include Interactor::Organizer
|
57
|
+
#
|
58
|
+
# organizer InteractorOne, InteractorTwo
|
59
|
+
# end
|
60
|
+
#
|
61
|
+
# MyOrganizer.organized
|
62
|
+
# # => [InteractorOne, InteractorTwo]
|
63
|
+
#
|
64
|
+
# Returns an Array of Interactor classes or an empty Array.
|
17
65
|
def organized
|
18
66
|
@organized ||= []
|
19
67
|
end
|
20
68
|
end
|
21
69
|
|
70
|
+
# Internal: Interactor::Organizer instance methods.
|
22
71
|
module InstanceMethods
|
72
|
+
# Internal: Invoke the organized Interactors. An Interactor::Organizer is
|
73
|
+
# expected not to define its own "call" method in favor of this default
|
74
|
+
# implementation.
|
75
|
+
#
|
76
|
+
# Returns nothing.
|
23
77
|
def call
|
24
78
|
self.class.organized.each do |interactor|
|
25
79
|
interactor.call!(context)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: interactor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
4
|
+
version: 3.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Collective Idea
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-09-
|
11
|
+
date: 2014-09-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|