activeinteractor 0.1.7 → 1.0.0.beta.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 +36 -1
- data/README.md +397 -395
- data/lib/active_interactor.rb +12 -30
- data/lib/active_interactor/base.rb +18 -8
- data/lib/active_interactor/context.rb +4 -181
- data/lib/active_interactor/context/attributes.rb +37 -149
- data/lib/active_interactor/context/base.rb +141 -0
- data/lib/active_interactor/context/loader.rb +45 -0
- data/lib/active_interactor/error.rb +22 -15
- data/lib/active_interactor/interactor.rb +24 -57
- data/lib/active_interactor/interactor/callbacks.rb +64 -76
- data/lib/active_interactor/interactor/context.rb +97 -63
- data/lib/active_interactor/interactor/worker.rb +22 -65
- data/lib/active_interactor/organizer.rb +180 -164
- data/lib/active_interactor/version.rb +2 -3
- data/lib/rails/generators/active_interactor.rb +2 -37
- data/lib/rails/generators/active_interactor/application_interactor_generator.rb +23 -0
- data/lib/rails/generators/active_interactor/install_generator.rb +8 -12
- data/lib/rails/generators/active_interactor/templates/application_context.rb +4 -0
- data/lib/rails/generators/{templates/application_interactor.erb → active_interactor/templates/application_interactor.rb} +0 -0
- data/lib/rails/generators/active_interactor/templates/application_organizer.rb +4 -0
- data/lib/rails/generators/active_interactor/templates/initializer.erb +5 -0
- data/lib/rails/generators/interactor/context/rspec_generator.rb +19 -0
- data/lib/rails/generators/interactor/context/templates/rspec.erb +7 -0
- data/lib/rails/generators/interactor/context/templates/test_unit.erb +9 -0
- data/lib/rails/generators/interactor/context/test_unit_generator.rb +19 -0
- data/lib/rails/generators/interactor/context_generator.rb +19 -0
- data/lib/rails/generators/interactor/interactor_generator.rb +8 -3
- data/lib/rails/generators/interactor/organizer_generator.rb +8 -3
- data/lib/rails/generators/interactor/rspec_generator.rb +4 -3
- data/lib/rails/generators/interactor/templates/context.erb +4 -0
- data/lib/rails/generators/{templates → interactor/templates}/interactor.erb +0 -0
- data/lib/rails/generators/{templates → interactor/templates}/organizer.erb +1 -1
- data/lib/rails/generators/{templates → interactor/templates}/rspec.erb +0 -0
- data/lib/rails/generators/{templates → interactor/templates}/test_unit.erb +0 -0
- data/lib/rails/generators/interactor/test_unit_generator.rb +4 -3
- data/spec/active_interactor/base_spec.rb +51 -0
- data/spec/active_interactor/context/base_spec.rb +229 -0
- data/spec/active_interactor/error_spec.rb +43 -0
- data/spec/active_interactor/interactor/worker_spec.rb +89 -0
- data/spec/active_interactor/organizer_spec.rb +178 -0
- data/spec/active_interactor_spec.rb +26 -0
- data/spec/integration/basic_callback_integration_spec.rb +355 -0
- data/spec/integration/basic_context_integration_spec.rb +73 -0
- data/spec/integration/basic_integration_spec.rb +220 -0
- data/spec/integration/basic_validations_integration_spec.rb +204 -0
- data/spec/spec_helper.rb +44 -0
- data/spec/support/helpers/factories.rb +41 -0
- data/spec/support/shared_examples/a_class_with_interactor_callback_methods_example.rb +99 -0
- data/spec/support/shared_examples/a_class_with_interactor_context_methods_example.rb +58 -0
- data/spec/support/shared_examples/a_class_with_interactor_methods_example.rb +21 -0
- data/spec/support/shared_examples/a_class_with_organizer_callback_methods_example.rb +39 -0
- data/spec/support/spec_helpers.rb +7 -0
- metadata +68 -138
- data/lib/active_interactor/configuration.rb +0 -38
- data/lib/active_interactor/interactor/execution.rb +0 -24
- data/lib/rails/generators/templates/initializer.erb +0 -15
data/lib/active_interactor.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'active_support/dependencies/autoload'
|
4
4
|
|
5
5
|
require 'active_interactor/version'
|
6
6
|
|
@@ -23,46 +23,28 @@ require 'active_interactor/version'
|
|
23
23
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
24
24
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
25
25
|
# THE SOFTWARE.
|
26
|
-
#
|
27
|
-
# @author Aaron Allen <hello@aaronmallen.me>
|
28
|
-
# @since 0.0.1
|
29
|
-
# @version 0.2
|
30
26
|
module ActiveInteractor
|
31
27
|
extend ActiveSupport::Autoload
|
32
28
|
|
33
29
|
autoload :Base
|
34
|
-
autoload :Configuration
|
35
30
|
autoload :Context
|
36
|
-
autoload :Interactor
|
37
31
|
autoload :Organizer
|
38
32
|
|
39
33
|
eager_autoload do
|
40
34
|
autoload :Error
|
41
35
|
end
|
42
36
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
end
|
49
|
-
|
50
|
-
# Configures the ActiveInteractor gem
|
51
|
-
#
|
52
|
-
# @example Configure ActiveInteractor
|
53
|
-
# ActiveInteractor.configure do |config|
|
54
|
-
# config.logger = Rails.logger
|
55
|
-
# end
|
56
|
-
#
|
57
|
-
# @yield [ActiveInteractor#configuration]
|
58
|
-
def configure
|
59
|
-
yield(configuration)
|
60
|
-
end
|
37
|
+
# The ActiveInteractor logger object
|
38
|
+
# @return [Logger] an instance of Logger
|
39
|
+
def self.logger
|
40
|
+
@logger ||= Logger.new(STDOUT)
|
41
|
+
end
|
61
42
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
43
|
+
# Set the ActiveInteractor logger object
|
44
|
+
# @example
|
45
|
+
# ActiveInteractor.logger = ::Rails.logger
|
46
|
+
# @return [Logger] an instance of Logger
|
47
|
+
def self.logger=(logger)
|
48
|
+
@logger = logger
|
67
49
|
end
|
68
50
|
end
|
@@ -1,19 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'active_interactor/interactor'
|
4
|
+
|
3
5
|
module ActiveInteractor
|
4
|
-
# The
|
5
|
-
#
|
6
|
+
# The base interactor class. All interactors should inherit from
|
7
|
+
# {Base}.
|
6
8
|
# @author Aaron Allen <hello@aaronmallen.me>
|
7
9
|
# @since 0.0.1
|
8
|
-
# @
|
10
|
+
# @example a basic interactor
|
11
|
+
# class MyInteractor < ActiveInteractor::Base
|
12
|
+
# def perform
|
13
|
+
# context.called = true
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# MyInteractor.perform
|
18
|
+
# #=> <MyInteractor::Context called=true>
|
9
19
|
class Base
|
10
20
|
include Interactor
|
11
21
|
|
12
|
-
#
|
13
|
-
# @
|
14
|
-
# @return [
|
15
|
-
def
|
16
|
-
|
22
|
+
# Duplicates an instance of {Base}
|
23
|
+
# @since 1.0.0-alpha.1
|
24
|
+
# @return [Base] a new instance of {Base}
|
25
|
+
def dup
|
26
|
+
self.class.new(context.dup)
|
17
27
|
end
|
18
28
|
end
|
19
29
|
end
|
@@ -1,190 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'ostruct'
|
4
|
-
|
5
|
-
Dir[File.expand_path('context/*.rb', __dir__)].each { |file| require file }
|
6
|
-
|
7
3
|
module ActiveInteractor
|
8
|
-
# ActiveInteractor::Context
|
9
|
-
#
|
4
|
+
# ActiveInteractor::Context classes
|
10
5
|
# @author Aaron Allen <hello@aaronmallen.me>
|
11
6
|
# @since 0.0.1
|
12
|
-
# @version 0.1
|
13
7
|
module Context
|
14
|
-
|
15
|
-
#
|
16
|
-
# @author Aaron Allen <hello@aaronmallen.me>
|
17
|
-
# @since 0.0.1
|
18
|
-
# @version 0.2
|
19
|
-
class Base < OpenStruct
|
20
|
-
include ActiveModel::Validations
|
21
|
-
include Attributes
|
22
|
-
|
23
|
-
# A new instance of {Base}
|
24
|
-
# @param interactor [ActiveInteractor::Base] an interactor instance
|
25
|
-
# @param attributes [Hash, nil] the attributes of the context
|
26
|
-
# @return [ActiveInteractor::Context::Base] a new instance of {Base}
|
27
|
-
def initialize(interactor, attributes = {})
|
28
|
-
copy_flags!(attributes)
|
29
|
-
@interactor = interactor
|
30
|
-
super(attributes)
|
31
|
-
end
|
32
|
-
|
33
|
-
# Track that an Interactor has been called. The {#called!} method
|
34
|
-
# is used by the interactor being invoked with this context. After an
|
35
|
-
# interactor is successfully called, the interactor instance is tracked in
|
36
|
-
# the context for the purpose of potential future rollback
|
37
|
-
#
|
38
|
-
# @return [Array<ActiveInteractor::Base>] all called interactors
|
39
|
-
def called!
|
40
|
-
_called << interactor
|
41
|
-
end
|
42
|
-
|
43
|
-
# Fail the context instance. Failing a context raises an error
|
44
|
-
# that may be rescued by the calling interactor. The context is also flagged
|
45
|
-
# as having failed
|
46
|
-
#
|
47
|
-
# @example Fail an interactor context
|
48
|
-
# interactor = MyInteractor.new(name: 'Aaron')
|
49
|
-
# #=> <#MyInteractor name='Aaron'>
|
50
|
-
#
|
51
|
-
# interactor.context.fail!
|
52
|
-
# #=> ActiveInteractor::Error::ContextFailure: <#MyInteractor::Context name='Aaron'>
|
53
|
-
#
|
54
|
-
# @param errors [ActiveModel::Errors, Hash] errors to add to the context on failure
|
55
|
-
# @see https://api.rubyonrails.org/classes/ActiveModel/Errors.html ActiveModel::Errors
|
56
|
-
# @raise [Error::ContextFailure]
|
57
|
-
def fail!(errors = {})
|
58
|
-
merge_errors(errors)
|
59
|
-
mark_failed!
|
60
|
-
raise_context_failure!
|
61
|
-
end
|
62
|
-
|
63
|
-
# Whether the context instance has failed. By default, a new
|
64
|
-
# context is successful and only changes when explicitly failed
|
65
|
-
#
|
66
|
-
# @note The {#failure?} method is the inverse of the {#success?} method
|
67
|
-
#
|
68
|
-
# @example Check if a context has failed
|
69
|
-
# context = MyInteractor::Context.new
|
70
|
-
# #=> <#MyInteractor::Context>
|
71
|
-
#
|
72
|
-
# context.failure?
|
73
|
-
# false
|
74
|
-
#
|
75
|
-
# context.fail!
|
76
|
-
# #=> ActiveInteractor::Error::ContextFailure: <#MyInteractor::Context>
|
77
|
-
#
|
78
|
-
# context.failure?
|
79
|
-
# #=> true
|
80
|
-
#
|
81
|
-
# @return [Boolean] `false` by default or `true` if failed
|
82
|
-
def failure?
|
83
|
-
@_failed || false
|
84
|
-
end
|
85
|
-
alias fail? failure?
|
86
|
-
|
87
|
-
# Attempt to call the interactor for missing validation callback methods
|
88
|
-
# @raise [NameError] if the method is not a validation callback or method
|
89
|
-
# does not exist on the interactor instance
|
90
|
-
def method_missing(name, *args, &block)
|
91
|
-
interactor.send(name, *args, &block) if validation_callback?(name)
|
92
|
-
super
|
93
|
-
end
|
94
|
-
|
95
|
-
# Attempt to call the interactor for missing validation callback methods
|
96
|
-
# @return [Boolean] `true` if method is a validation callback and exists
|
97
|
-
# on the interactor instance
|
98
|
-
def respond_to_missing?(name, include_private)
|
99
|
-
return false unless validation_callback?(name)
|
100
|
-
|
101
|
-
interactor.respond_to?(name, include_private)
|
102
|
-
end
|
103
|
-
|
104
|
-
# Roll back an interactor context. Any interactors to which this
|
105
|
-
# context has been passed and which have been successfully called are asked
|
106
|
-
# to roll themselves back by invoking their
|
107
|
-
# {ActiveInteractor::Interactor#rollback #rollback} instance methods.
|
108
|
-
#
|
109
|
-
# @example Rollback an interactor's context
|
110
|
-
# context = MyInteractor.perform(name: 'Aaron')
|
111
|
-
# #=> <#MyInteractor::Context name='Aaron'>
|
112
|
-
#
|
113
|
-
# context.rollback!
|
114
|
-
# #=> true
|
115
|
-
#
|
116
|
-
# context
|
117
|
-
# #=> <#MyInteractor::Context name='Aaron'>
|
118
|
-
#
|
119
|
-
# @return [Boolean] `true` if rolled back successfully or `false` if already
|
120
|
-
# rolled back
|
121
|
-
def rollback!
|
122
|
-
return false if @_rolled_back
|
123
|
-
|
124
|
-
rollback_called
|
125
|
-
mark_rolledback!
|
126
|
-
end
|
127
|
-
|
128
|
-
# Whether the context instance is successful. By default, a new
|
129
|
-
# context is successful and only changes when explicitly failed
|
130
|
-
#
|
131
|
-
# @note the {#success?} method is the inverse of the {#failure?} method
|
132
|
-
#
|
133
|
-
# @example Check if a context has failed
|
134
|
-
# context = MyInteractor::Context.new
|
135
|
-
# #=> <#MyInteractor::Context>
|
136
|
-
#
|
137
|
-
# context.success?
|
138
|
-
# true
|
139
|
-
#
|
140
|
-
# context.fail!
|
141
|
-
# #=> ActiveInteractor::Error::ContextFailure: <#MyInteractor::Context>
|
142
|
-
#
|
143
|
-
# context.success?
|
144
|
-
# #=> false
|
145
|
-
#
|
146
|
-
# @return [Boolean] `true` by default or `false` if failed
|
147
|
-
def success?
|
148
|
-
!failure?
|
149
|
-
end
|
150
|
-
alias successful? success?
|
151
|
-
|
152
|
-
private
|
153
|
-
|
154
|
-
attr_reader :interactor
|
155
|
-
|
156
|
-
def copy_flags!(context)
|
157
|
-
@_called = context.send(:_called) if context.respond_to?(:_called, true)
|
158
|
-
@_failed = context.failure? if context.respond_to?(:failure?)
|
159
|
-
end
|
160
|
-
|
161
|
-
def _called
|
162
|
-
@_called ||= []
|
163
|
-
end
|
164
|
-
|
165
|
-
def mark_failed!
|
166
|
-
@_failed = true
|
167
|
-
end
|
168
|
-
|
169
|
-
def mark_rolledback!
|
170
|
-
@_rolled_back = true
|
171
|
-
end
|
172
|
-
|
173
|
-
def merge_errors(errors)
|
174
|
-
self.errors.merge!(errors) unless errors.empty?
|
175
|
-
end
|
176
|
-
|
177
|
-
def raise_context_failure!
|
178
|
-
raise Error::ContextFailure, self
|
179
|
-
end
|
180
|
-
|
181
|
-
def rollback_called
|
182
|
-
_called.reverse_each(&:execute_rollback)
|
183
|
-
end
|
8
|
+
extend ActiveSupport::Autoload
|
184
9
|
|
185
|
-
|
186
|
-
|
187
|
-
end
|
188
|
-
end
|
10
|
+
autoload :Base
|
11
|
+
autoload :Loader
|
189
12
|
end
|
190
13
|
end
|
@@ -1,190 +1,78 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'active_support/core_ext/array/wrap'
|
4
|
-
require 'active_support/core_ext/class/attribute'
|
5
|
-
|
6
3
|
module ActiveInteractor
|
7
4
|
module Context
|
8
|
-
#
|
9
|
-
#
|
5
|
+
# Context attribute methods included by all {Context::Base}
|
10
6
|
# @author Aaron Allen <hello@aaronmallen.me>
|
11
7
|
# @since 0.1.4
|
12
|
-
# @version 0.1
|
13
8
|
module Attributes
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
class_attribute :__default_attributes, instance_writer: false, default: []
|
9
|
+
def self.included(base)
|
10
|
+
base.class_eval do
|
11
|
+
extend ClassMethods
|
12
|
+
end
|
19
13
|
end
|
20
14
|
|
15
|
+
# Context attribute class methods extended by all {Context::Base}
|
21
16
|
module ClassMethods
|
22
|
-
#
|
23
|
-
#
|
17
|
+
# Set or get attributes defined on the context class
|
18
|
+
# @example Set attributes on a context class
|
19
|
+
# class MyInteractor::Context < ActiveInteractor::Context::Base
|
20
|
+
# attributes :first_name, :last_name
|
21
|
+
# end
|
24
22
|
# @example Get attributes defined on a context class
|
25
23
|
# MyInteractor::Context.attributes
|
26
24
|
# #=> [:first_name, :last_name]
|
27
|
-
#
|
28
|
-
# @return [Array<Symbol>] the defined attributes
|
29
|
-
def attributes
|
30
|
-
__default_attributes
|
31
|
-
.concat(_validate_callbacks.map(&:filter).map(&:attributes).flatten)
|
32
|
-
.flatten
|
33
|
-
.uniq
|
34
|
-
end
|
35
|
-
|
36
|
-
# Set attributes on a context class
|
37
|
-
#
|
38
|
-
# @param attributes [Array<Symbol, String>] the attributes of the context
|
39
|
-
#
|
40
|
-
# @example Define attributes on a context class
|
41
|
-
# MyInteractor::Context.attributes = :first_name, :last_name
|
42
|
-
# #=> [:first_name, :last_name]
|
43
|
-
#
|
44
25
|
# @return [Array<Symbol>] the defined attributes
|
45
|
-
def attributes
|
46
|
-
|
47
|
-
end
|
48
|
-
|
49
|
-
# Attribute aliases defined on the context class
|
50
|
-
#
|
51
|
-
# @example Get attribute aliases defined on a context class
|
52
|
-
# MyInteractor::Context.attribute_aliases
|
53
|
-
# #=> { last_name: [:sir_name] }
|
54
|
-
#
|
55
|
-
# @return [Hash{Symbol => Array<Symbol>}]
|
56
|
-
def attribute_aliases
|
57
|
-
@attribute_aliases ||= {}
|
58
|
-
end
|
26
|
+
def attributes(*attributes)
|
27
|
+
return __attributes if attributes.empty?
|
59
28
|
|
60
|
-
|
61
|
-
#
|
62
|
-
# @param aliases [Hash{Symbol => Symbol, Array<Symbol>}] the attribute aliases of
|
63
|
-
# the context
|
64
|
-
#
|
65
|
-
# @return [Hash{Symbol => Array<Symbol>}]
|
66
|
-
def alias_attributes(aliases = {})
|
67
|
-
map_attribute_aliases(aliases)
|
68
|
-
attribute_aliases
|
29
|
+
@__attributes = __attributes.concat(attributes).compact.uniq.sort
|
69
30
|
end
|
70
31
|
|
71
32
|
private
|
72
33
|
|
73
|
-
def
|
74
|
-
|
75
|
-
key = attribute.to_sym
|
76
|
-
attribute_aliases[key] ||= []
|
77
|
-
attribute_aliases[key].concat(Array.wrap(aliases[attribute]).map(&:to_sym))
|
78
|
-
end
|
34
|
+
def __attributes
|
35
|
+
@__attributes ||= []
|
79
36
|
end
|
80
37
|
end
|
81
38
|
|
82
|
-
|
83
|
-
|
39
|
+
# @api private
|
40
|
+
# @param context [Hash|Context::Base] attributes to assign to the context
|
41
|
+
# @return [Context::Base] a new instance of {Context::Base}
|
42
|
+
def initialize(context = {})
|
43
|
+
copy_flags!(context)
|
44
|
+
super
|
84
45
|
end
|
85
46
|
|
86
47
|
# Attributes defined on the instance
|
87
|
-
#
|
88
48
|
# @example Get attributes defined on an instance
|
89
|
-
#
|
90
|
-
#
|
91
|
-
#
|
92
|
-
# context = MyInteractor::Context.new(first_name: 'Aaron', last_name: 'Allen')
|
93
|
-
# #=> <#MyInteractor::Context first_name='Aaron', last_name='Allen'>
|
94
|
-
#
|
95
|
-
# context.attributes
|
96
|
-
# #=> { first_name: 'Aaron', last_name: 'Allen' }
|
97
|
-
#
|
98
|
-
# @example Get attributes defined on an instance with unknown attribute
|
99
|
-
# MyInteractor::Context.attributes = :first_name, :last_name
|
100
|
-
# #=> [:first_name, :last_name]
|
101
|
-
#
|
102
|
-
# context = MyInteractor::Context.new(first_name: 'Aaron', last_name: 'Allen', unknown: 'unknown')
|
103
|
-
# #=> <#MyInteractor::Context first_name='Aaron', last_name='Allen', unknown='unknown'>
|
49
|
+
# class MyInteractor::Context < ActiveInteractor::Context::Base
|
50
|
+
# attributes :first_name, :last_name
|
51
|
+
# end
|
104
52
|
#
|
105
|
-
#
|
106
|
-
#
|
53
|
+
# class MyInteractor < ActiveInteractor::Base
|
54
|
+
# def perform; end
|
55
|
+
# end
|
107
56
|
#
|
108
|
-
#
|
109
|
-
#
|
57
|
+
# result = MyInteractor.perform(first_name: 'Aaron', last_name: 'Allen', occupation: 'Software Nerd')
|
58
|
+
# #=> <#MyInteractor::Context first_name='Aaron' last_name='Allen' occupation='Software Nerd'>
|
110
59
|
#
|
111
|
-
#
|
60
|
+
# result.attributes
|
61
|
+
# #=> { first_name: 'Aaron', last_name: 'Allen' }
|
62
|
+
# @return [Hash{Symbol=>*}] the defined attributes and values
|
112
63
|
def attributes
|
113
64
|
self.class.attributes.each_with_object({}) do |attribute, hash|
|
114
65
|
hash[attribute] = self[attribute] if self[attribute]
|
115
66
|
end
|
116
67
|
end
|
117
68
|
|
118
|
-
# Removes properties from the instance that are not
|
119
|
-
# explicitly defined in the context instance {#attributes}
|
120
|
-
#
|
121
|
-
# @example Clean an instance of Context with unknown attribute
|
122
|
-
# MyInteractor::Context.attributes = :first_name, :last_name
|
123
|
-
# #=> [:first_name, :last_name]
|
124
|
-
#
|
125
|
-
# context = MyInteractor::Context.new(first_name: 'Aaron', last_name: 'Allen', unknown: 'unknown')
|
126
|
-
# #=> <#MyInteractor::Context first_name='Aaron', last_name='Allen', unknown='unknown'>
|
127
|
-
#
|
128
|
-
# context.unknown
|
129
|
-
# #=> 'unknown'
|
130
|
-
#
|
131
|
-
# context.clean!
|
132
|
-
# #=> { unknown: 'unknown' }
|
133
|
-
#
|
134
|
-
# context.unknown
|
135
|
-
# #=> nil
|
136
|
-
#
|
137
|
-
# @return [Hash{Symbol => *}] the deleted attributes
|
138
|
-
def clean!
|
139
|
-
return {} if keys.empty?
|
140
|
-
|
141
|
-
clean_keys!
|
142
|
-
end
|
143
|
-
|
144
|
-
# All keys of properties currently defined on the instance
|
145
|
-
#
|
146
|
-
# @example An instance of Context with unknown attribute
|
147
|
-
# MyInteractor::Context.attributes = :first_name, :last_name
|
148
|
-
# #=> [:first_name, :last_name]
|
149
|
-
#
|
150
|
-
# context = MyInteractor::Context.new(first_name: 'Aaron', last_name: 'Allen', unknown: 'unknown')
|
151
|
-
# #=> <#MyInteractor::Context first_name='Aaron', last_name='Allen', unknown='unknown'>
|
152
|
-
#
|
153
|
-
# context.keys
|
154
|
-
# #=> [:first_name, :last_name, :unknown]
|
155
|
-
#
|
156
|
-
# @return [Array<Symbol>] keys defined on the instance
|
157
|
-
def keys
|
158
|
-
each_pair.map { |pair| pair[0].to_sym }
|
159
|
-
end
|
160
|
-
|
161
69
|
private
|
162
70
|
|
163
|
-
def
|
164
|
-
|
165
|
-
|
71
|
+
def copy_flags!(context)
|
72
|
+
%w[_called _failed _rolled_back].each do |flag|
|
73
|
+
value = context.instance_variable_get("@#{flag}")
|
74
|
+
instance_variable_set("@#{flag}", value)
|
166
75
|
end
|
167
|
-
key
|
168
|
-
end
|
169
|
-
|
170
|
-
def clean_keys!
|
171
|
-
keys.reject { |key| self.class.attributes.include?(key) }.each_with_object({}) do |attribute, deleted|
|
172
|
-
deleted[attribute] = self[attribute] if self[attribute]
|
173
|
-
delete_field(key.to_s)
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
def map_attributes(attributes)
|
178
|
-
return {} unless attributes
|
179
|
-
|
180
|
-
attributes.keys.each_with_object({}) do |attribute, hash|
|
181
|
-
key = aliased_key(attribute)
|
182
|
-
hash[key] = attributes[attribute]
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
def new_ostruct_member!(name)
|
187
|
-
super(aliased_key(name))
|
188
76
|
end
|
189
77
|
end
|
190
78
|
end
|