interactor 3.0.0 → 3.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|