activeinteractor 1.0.0 → 1.0.5
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 +71 -1
- data/README.md +22 -7
- data/lib/active_interactor.rb +5 -1
- data/lib/active_interactor/config.rb +1 -1
- data/lib/active_interactor/context/attributes.rb +64 -15
- data/lib/active_interactor/context/base.rb +87 -0
- data/lib/active_interactor/context/errors.rb +47 -0
- data/lib/active_interactor/context/loader.rb +1 -1
- data/lib/active_interactor/context/status.rb +12 -19
- data/lib/active_interactor/interactor/context.rb +59 -3
- data/lib/active_interactor/interactor/perform.rb +5 -1
- data/lib/active_interactor/models.rb +13 -28
- data/lib/active_interactor/organizer/interactor_interface.rb +1 -1
- data/lib/active_interactor/organizer/interactor_interface_collection.rb +1 -0
- data/lib/active_interactor/rails/orm/dynamoid.rb +5 -0
- data/lib/active_interactor/rails/orm/mongoid.rb +5 -0
- data/lib/active_interactor/version.rb +1 -1
- data/lib/rails/generators/templates/organizer.erb +2 -2
- data/spec/active_interactor/base_spec.rb +33 -0
- data/spec/active_interactor/context/base_spec.rb +101 -12
- data/spec/integration/a_basic_interactor_spec.rb +48 -0
- data/spec/integration/a_basic_organizer_spec.rb +119 -0
- data/spec/integration/active_record_integration_spec.rb +8 -342
- data/spec/spec_helper.rb +18 -8
- data/spec/support/shared_examples/a_class_that_extends_active_interactor_models_example.rb +81 -0
- metadata +37 -42
- data/spec/support/coverage.rb +0 -4
- data/spec/support/coverage/reporters.rb +0 -11
- data/spec/support/coverage/reporters/codacy.rb +0 -39
- data/spec/support/coverage/reporters/simple_cov.rb +0 -54
- data/spec/support/coverage/runner.rb +0 -66
@@ -22,7 +22,7 @@ module ActiveInteractor
|
|
22
22
|
# @param interactor_class [Const] an {ActiveInteractor::Base interactor} class
|
23
23
|
# @return [Const] a class that inherits from {Base}
|
24
24
|
def self.create(context_class_name, interactor_class)
|
25
|
-
interactor_class.const_set(context_class_name.to_s.
|
25
|
+
interactor_class.const_set(context_class_name.to_s.camelize, Class.new(BASE_CONTEXT))
|
26
26
|
end
|
27
27
|
|
28
28
|
# Find or create a {Base context} class for a given {ActiveInteractor::Base interactor}. If a class exists
|
@@ -37,8 +37,9 @@ module ActiveInteractor
|
|
37
37
|
# @see https://api.rubyonrails.org/classes/ActiveModel/Errors.html ActiveModel::Errors
|
38
38
|
# @raise [Error::ContextFailure]
|
39
39
|
def fail!(errors = nil)
|
40
|
-
|
40
|
+
handle_errors(errors) if errors
|
41
41
|
@_failed = true
|
42
|
+
resolve
|
42
43
|
raise ActiveInteractor::Error::ContextFailure, self
|
43
44
|
end
|
44
45
|
|
@@ -59,6 +60,16 @@ module ActiveInteractor
|
|
59
60
|
end
|
60
61
|
alias fail? failure?
|
61
62
|
|
63
|
+
# Resolve an instance of {Base context}. Called when an interactor
|
64
|
+
# is finished with it's context.
|
65
|
+
#
|
66
|
+
# @since 1.0.3
|
67
|
+
# @return [self] the instance of {Base context}
|
68
|
+
def resolve
|
69
|
+
resolve_errors
|
70
|
+
self
|
71
|
+
end
|
72
|
+
|
62
73
|
# {#rollback! Rollback} an instance of {Base context}. Any {ActiveInteractor::Base interactors} the instance has
|
63
74
|
# been passed via the {#called!} method are asked to roll themselves back by invoking their
|
64
75
|
# {Interactor::Perform#rollback #rollback} methods. The instance is also flagged as rolled back.
|
@@ -90,24 +101,6 @@ module ActiveInteractor
|
|
90
101
|
!failure?
|
91
102
|
end
|
92
103
|
alias successful? success?
|
93
|
-
|
94
|
-
private
|
95
|
-
|
96
|
-
def _called
|
97
|
-
@_called ||= []
|
98
|
-
end
|
99
|
-
|
100
|
-
def copy_called!(context)
|
101
|
-
value = context.instance_variable_get('@_called') || []
|
102
|
-
instance_variable_set('@_called', value)
|
103
|
-
end
|
104
|
-
|
105
|
-
def copy_flags!(context)
|
106
|
-
%w[_failed _rolled_back].each do |flag|
|
107
|
-
value = context.instance_variable_get("@#{flag}")
|
108
|
-
instance_variable_set("@#{flag}", value)
|
109
|
-
end
|
110
|
-
end
|
111
104
|
end
|
112
105
|
end
|
113
106
|
end
|
@@ -27,7 +27,43 @@ module ActiveInteractor
|
|
27
27
|
#
|
28
28
|
# MyInteractor.context_class.attributes
|
29
29
|
# #=> [:first_name, :last_name]
|
30
|
-
|
30
|
+
#
|
31
|
+
# @!method context_attribute_missing(match, *args, &block)
|
32
|
+
# Call {ActiveInteractor::Context::Base.attribute_missing .attribute_missing} on the {Base interactor} class'
|
33
|
+
# {#context_class context class}
|
34
|
+
#
|
35
|
+
# @since 1.0.1
|
36
|
+
#
|
37
|
+
# @!method context_respond_to_without_attributes?(method, include_private_methods = false)
|
38
|
+
# Call {ActiveInteractor::Context::Base.respond_to_without_attributes? .respond_to_without_attributes?} on the
|
39
|
+
# {Base interactor} class' {#context_class context class}
|
40
|
+
#
|
41
|
+
# @since 1.0.1
|
42
|
+
delegate :attributes, :attribute_missing, :respond_to_without_attributes?, to: :context_class, prefix: :context
|
43
|
+
|
44
|
+
# @!method context_attribute(name, type=Type::Value.new, **options)
|
45
|
+
# Call {ActiveInteractor::Context::Base.attribute .attribute} on the {Base interactor} class'
|
46
|
+
# {#context_class context class}
|
47
|
+
#
|
48
|
+
# @since 1.0.1
|
49
|
+
#
|
50
|
+
# @example Setting default values on the {ActiveInteractor::Context::Base context} class
|
51
|
+
# class MyInteractor < ActiveInteractor::Base
|
52
|
+
# context_attribute :first_name, default: -> { 'Aaron' }
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# MyInteractor.perform
|
56
|
+
# #=> <#MyInteractor::Context first_name='Aaron'>
|
57
|
+
#
|
58
|
+
# MyInteractor.perform(first_name: 'Bob')
|
59
|
+
# #=> <#MyInteractor::Context first_name='Bob'>
|
60
|
+
#
|
61
|
+
# @!method context_attribute_names
|
62
|
+
# Call {ActiveInteractor::Context::Base.attribute_names .attribute_names} on the {Base interactor} class'
|
63
|
+
# {#context_class context class}
|
64
|
+
#
|
65
|
+
# @since 1.0.1
|
66
|
+
delegate(*ActiveModel::Attributes::ClassMethods.instance_methods, to: :context_class, prefix: :context)
|
31
67
|
|
32
68
|
# @!method context_attribute_method?(attribute)
|
33
69
|
# Call {ActiveInteractor::Context::Base.attribute_method? .attribute_method?} on the {Base interactor} class'
|
@@ -175,7 +211,7 @@ module ActiveInteractor
|
|
175
211
|
# @return [Const] the {Base interactor} class' {ActiveInteractor::Context::Base context} class
|
176
212
|
def contextualize_with(klass)
|
177
213
|
@context_class = begin
|
178
|
-
context_class = klass.to_s.
|
214
|
+
context_class = klass.to_s.camelize.safe_constantize
|
179
215
|
raise(ActiveInteractor::Error::InvalidContextClass, klass) unless context_class
|
180
216
|
|
181
217
|
context_class
|
@@ -183,18 +219,37 @@ module ActiveInteractor
|
|
183
219
|
end
|
184
220
|
end
|
185
221
|
|
222
|
+
# @!method context_attribute_missing(match, *args, &block)
|
223
|
+
# Call {ActiveInteractor::Context::Base#attribute_missing #attribute_missing} on the {Base interactor} instance's
|
224
|
+
# {ActiveInteractor::Context::Base context} instance
|
225
|
+
#
|
226
|
+
# @since 1.0.1
|
227
|
+
#
|
228
|
+
# @!method context_attribute_names
|
229
|
+
# Call {ActiveInteractor::Context::Base#attribute_names #attribute_names} on the {Base interactor} instance's
|
230
|
+
# {ActiveInteractor::Context::Base context} instance
|
231
|
+
#
|
232
|
+
# @since 1.0.1
|
233
|
+
#
|
186
234
|
# @!method context_fail!(errors = nil)
|
187
235
|
# Call {ActiveInteractor::Context::Status#fail! #fail!} on the {Base interactor} instance's
|
188
236
|
# {ActiveInteractor::Context::Base context} instance
|
189
237
|
#
|
190
238
|
# @since 1.0.0
|
191
239
|
#
|
240
|
+
# @!method context_respond_to_without_attributes?(method, include_private_methods = false)
|
241
|
+
# Call {ActiveInteractor::Context::Base#respond_to_without_attributes? #respond_to_without_attributes?} on the
|
242
|
+
# {Base interactor} instance's {ActiveInteractor::Context::Base context} instance
|
243
|
+
#
|
244
|
+
# @since 1.0.1
|
245
|
+
#
|
192
246
|
# @!method context_rollback!
|
193
247
|
# Call {ActiveInteractor::Context::Status#rollback! #rollback!} on the {Base interactor} instance's
|
194
248
|
# {ActiveInteractor::Context::Base context} instance
|
195
249
|
#
|
196
250
|
# @since 1.0.0
|
197
|
-
delegate :
|
251
|
+
delegate :attribute_missing, :attribute_names, :fail!, :respond_to_without_attributes?, :rollback!,
|
252
|
+
to: :context, prefix: true
|
198
253
|
|
199
254
|
# @!method context_errors
|
200
255
|
# Call {ActiveInteractor::Context::Base#errors #errors} on the {Base interactor} instance's
|
@@ -311,6 +366,7 @@ module ActiveInteractor
|
|
311
366
|
# @return [Class] the {ActiveInteractor::Context::Base context} instance
|
312
367
|
def finalize_context!
|
313
368
|
context.called!(self)
|
369
|
+
context.resolve
|
314
370
|
context
|
315
371
|
end
|
316
372
|
|
@@ -175,7 +175,11 @@ module ActiveInteractor
|
|
175
175
|
#
|
176
176
|
# @return [Base] a duplicated {Base interactor} instance
|
177
177
|
def deep_dup
|
178
|
-
|
178
|
+
dupped = dup
|
179
|
+
%w[@context @options].each do |variable|
|
180
|
+
dupped.instance_variable_set(variable, instance_variable_get(variable)&.dup)
|
181
|
+
end
|
182
|
+
dupped
|
179
183
|
end
|
180
184
|
|
181
185
|
# Options for the {Base interactor} {#perform}
|
@@ -13,39 +13,21 @@ module ActiveInteractor
|
|
13
13
|
# @author Aaron Allen <hello@aaronmallen.me>
|
14
14
|
# @since 1.0.0
|
15
15
|
module InstanceMethods
|
16
|
-
def initialize(
|
17
|
-
|
18
|
-
|
19
|
-
attributes_as_hash = context_attributes_as_hash(attributes)
|
20
|
-
super(attributes_as_hash)
|
21
|
-
end
|
22
|
-
|
23
|
-
# Merge an instance of model class into the calling model class instance
|
24
|
-
#
|
25
|
-
# @see Context::Attributes#merge!
|
26
|
-
#
|
27
|
-
# @param context [Class] a {Base context} instance to be merged
|
28
|
-
# @return [self] the {Base context} instance
|
29
|
-
def merge!(context)
|
30
|
-
copy_flags!(context)
|
31
|
-
context.each_pair do |key, value|
|
32
|
-
self[key] = value unless value.nil?
|
33
|
-
end
|
34
|
-
self
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
def context_attributes_as_hash(attributes)
|
40
|
-
return attributes.to_h if attributes&.respond_to?(:to_h)
|
41
|
-
return attributes.attributes.to_h if attributes.respond_to?(:attributes)
|
16
|
+
def initialize(*)
|
17
|
+
@attributes = self.class._default_attributes&.deep_dup
|
18
|
+
super
|
42
19
|
end
|
43
20
|
end
|
44
21
|
|
45
22
|
# Include methods needed for a {Context::Base context} class to function properly.
|
46
23
|
#
|
24
|
+
# @note You must include ActiveModel::Model and ActiveModel::Attributes or a similar implementation for
|
25
|
+
# the object to function properly.
|
26
|
+
#
|
47
27
|
# @example
|
48
28
|
# class User
|
29
|
+
# include ActiveModel::Model
|
30
|
+
# include ActiveModel::Attributes
|
49
31
|
# extend ActiveInteractor::Models
|
50
32
|
# acts_as_context
|
51
33
|
# end
|
@@ -55,9 +37,12 @@ module ActiveInteractor
|
|
55
37
|
# end
|
56
38
|
def acts_as_context
|
57
39
|
class_eval do
|
58
|
-
|
59
|
-
|
40
|
+
extend ActiveInteractor::Context::Attributes::ClassMethods
|
41
|
+
|
42
|
+
include ActiveInteractor::Context::Attributes
|
43
|
+
include ActiveInteractor::Context::Errors
|
60
44
|
include ActiveInteractor::Context::Status
|
45
|
+
include ActiveInteractor::Models::InstanceMethods
|
61
46
|
delegate :each_pair, to: :attributes
|
62
47
|
end
|
63
48
|
end
|
@@ -40,7 +40,7 @@ module ActiveInteractor
|
|
40
40
|
# {Interactor::Perform::ClassMethods#perform .perform}. See {Interactor::Perform::Options}.
|
41
41
|
# @return [InteractorInterface] a new instance of {InteractorInterface}
|
42
42
|
def initialize(interactor_class, options = {})
|
43
|
-
@interactor_class = interactor_class.to_s.
|
43
|
+
@interactor_class = interactor_class.to_s.camelize.safe_constantize
|
44
44
|
@filters = options.select { |key, _value| CONDITIONAL_FILTERS.include?(key) }
|
45
45
|
@perform_options = options.reject { |key, _value| CONDITIONAL_FILTERS.include?(key) }
|
46
46
|
end
|
@@ -14,6 +14,7 @@ module ActiveInteractor
|
|
14
14
|
# @return [Array<InteractorInterface>] the {InteractorInterface} collection
|
15
15
|
class InteractorInterfaceCollection
|
16
16
|
attr_reader :collection
|
17
|
+
|
17
18
|
# @!method map(&block)
|
18
19
|
# Invokes the given block once for each element of {#collection}.
|
19
20
|
# @return [Array] a new array containing the values returned by the block.
|
@@ -6,8 +6,8 @@ class <%= class_name %> < ApplicationOrganizer
|
|
6
6
|
|
7
7
|
<%- end -%>
|
8
8
|
<%- if interactors.any? -%>
|
9
|
-
organize <%= interactors.
|
9
|
+
organize <%= interactors.join(", ") %>
|
10
10
|
<%- else -%>
|
11
|
-
# organize
|
11
|
+
# organize :interactor_1, :interactor_2
|
12
12
|
<%- end -%>
|
13
13
|
end
|
@@ -27,6 +27,17 @@ RSpec.describe ActiveInteractor::Base do
|
|
27
27
|
subject
|
28
28
|
expect(described_class.context_class).to eq TestContext
|
29
29
|
end
|
30
|
+
|
31
|
+
# https://github.com/aaronmallen/activeinteractor/issues/168
|
32
|
+
context 'when singularized' do
|
33
|
+
let!(:singularized_class) { build_context('PlaceData') }
|
34
|
+
let(:klass) { 'PlaceData' }
|
35
|
+
|
36
|
+
it 'is expected to assign the appropriate context class' do
|
37
|
+
subject
|
38
|
+
expect(described_class.context_class).to eq PlaceData
|
39
|
+
end
|
40
|
+
end
|
30
41
|
end
|
31
42
|
|
32
43
|
context 'when passed as a symbol' do
|
@@ -36,6 +47,17 @@ RSpec.describe ActiveInteractor::Base do
|
|
36
47
|
subject
|
37
48
|
expect(described_class.context_class).to eq TestContext
|
38
49
|
end
|
50
|
+
|
51
|
+
# https://github.com/aaronmallen/activeinteractor/issues/168
|
52
|
+
context 'when singularized' do
|
53
|
+
let!(:singularized_class) { build_context('PlaceData') }
|
54
|
+
let(:klass) { :place_data }
|
55
|
+
|
56
|
+
it 'is expected to assign the appropriate context class' do
|
57
|
+
subject
|
58
|
+
expect(described_class.context_class).to eq PlaceData
|
59
|
+
end
|
60
|
+
end
|
39
61
|
end
|
40
62
|
|
41
63
|
context 'when passed as a constant' do
|
@@ -45,6 +67,17 @@ RSpec.describe ActiveInteractor::Base do
|
|
45
67
|
subject
|
46
68
|
expect(described_class.context_class).to eq TestContext
|
47
69
|
end
|
70
|
+
|
71
|
+
# https://github.com/aaronmallen/activeinteractor/issues/168
|
72
|
+
context 'when singularized' do
|
73
|
+
let!(:singularized_class) { build_context('PlaceData') }
|
74
|
+
let(:klass) { PlaceData }
|
75
|
+
|
76
|
+
it 'is expected to assign the appropriate context class' do
|
77
|
+
subject
|
78
|
+
expect(described_class.context_class).to eq PlaceData
|
79
|
+
end
|
80
|
+
end
|
48
81
|
end
|
49
82
|
end
|
50
83
|
end
|
@@ -3,34 +3,113 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
RSpec.describe ActiveInteractor::Context::Base do
|
6
|
-
|
7
|
-
|
8
|
-
describe '#attributes' do
|
6
|
+
describe '.attributes' do
|
9
7
|
context 'when no arguments are passed' do
|
10
|
-
subject {
|
8
|
+
subject { context_class.attributes }
|
9
|
+
let!(:context_class) { build_context }
|
11
10
|
it { is_expected.to eq [] }
|
12
11
|
|
13
12
|
context 'when an attribute :foo was previously defined' do
|
14
|
-
|
13
|
+
let!(:context_class) do
|
14
|
+
build_context do
|
15
|
+
attributes :foo
|
16
|
+
end
|
17
|
+
end
|
15
18
|
|
16
19
|
it { is_expected.to eq %i[foo] }
|
17
20
|
end
|
18
21
|
end
|
19
22
|
|
20
23
|
context 'when given arguments :foo and :bar' do
|
21
|
-
subject {
|
24
|
+
subject { context_class.attributes(:foo, :bar) }
|
25
|
+
let!(:context_class) { build_context }
|
22
26
|
|
23
27
|
it { is_expected.to eq %i[bar foo] }
|
24
28
|
|
25
29
|
context 'when an attribute :foo was previously defined' do
|
26
|
-
before {
|
30
|
+
before { TestContext.attributes(:foo) }
|
27
31
|
|
28
32
|
it { is_expected.to eq %i[bar foo] }
|
29
33
|
end
|
30
34
|
end
|
31
35
|
end
|
32
36
|
|
33
|
-
describe '
|
37
|
+
describe '#[]' do
|
38
|
+
subject { instance[attribute] }
|
39
|
+
|
40
|
+
context 'with class attributes []' do
|
41
|
+
let(:instance) { build_context.new }
|
42
|
+
|
43
|
+
context 'with attribute nil' do
|
44
|
+
let(:attribute) { :foo }
|
45
|
+
|
46
|
+
it { is_expected.to be_nil }
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'with attribute equal to "foo"' do
|
50
|
+
let(:attribute) { :foo }
|
51
|
+
before { instance.foo = 'foo' }
|
52
|
+
|
53
|
+
it { is_expected.to eq 'foo' }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'with class attributes [:foo]' do
|
58
|
+
let!(:context_class) do
|
59
|
+
build_context do
|
60
|
+
attributes :foo
|
61
|
+
end
|
62
|
+
end
|
63
|
+
let(:instance) { context_class.new }
|
64
|
+
|
65
|
+
context 'with attribute nil' do
|
66
|
+
let(:attribute) { :foo }
|
67
|
+
|
68
|
+
it { is_expected.to be_nil }
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'with attribute equal to "foo"' do
|
72
|
+
let(:attribute) { :foo }
|
73
|
+
before { instance.foo = 'foo' }
|
74
|
+
|
75
|
+
it { is_expected.to eq 'foo' }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe '#attribute?' do
|
81
|
+
subject { instance.attribute?(attribute) }
|
82
|
+
|
83
|
+
context 'with class attributes []' do
|
84
|
+
let(:instance) { build_context.new }
|
85
|
+
let(:attribute) { :foo }
|
86
|
+
|
87
|
+
it { is_expected.to eq false }
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'with class attributes [:foo]' do
|
91
|
+
let!(:context_class) do
|
92
|
+
build_context do
|
93
|
+
attributes :foo
|
94
|
+
end
|
95
|
+
end
|
96
|
+
let(:instance) { context_class.new }
|
97
|
+
|
98
|
+
context 'checking attribute :foo' do
|
99
|
+
let(:attribute) { :foo }
|
100
|
+
|
101
|
+
it { is_expected.to eq true }
|
102
|
+
end
|
103
|
+
|
104
|
+
context 'checking attribute :bar' do
|
105
|
+
let(:attribute) { :bar }
|
106
|
+
|
107
|
+
it { is_expected.to eq false }
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe '#attributes' do
|
34
113
|
subject { instance.attributes }
|
35
114
|
|
36
115
|
context 'with class attributes []' do
|
@@ -43,13 +122,23 @@ RSpec.describe ActiveInteractor::Context::Base do
|
|
43
122
|
end
|
44
123
|
|
45
124
|
context 'with class attributes [:foo, :bar, :baz]' do
|
46
|
-
before {
|
125
|
+
before { build_context.attributes(:foo, :bar) }
|
126
|
+
|
127
|
+
context 'with an instance having attributes { :foo => "foo", :bar => "bar" }' do
|
128
|
+
let(:instance) { TestContext.new(foo: 'foo', bar: 'bar') }
|
129
|
+
|
130
|
+
it { is_expected.to be_a Hash }
|
131
|
+
it { is_expected.to eq(bar: 'bar', foo: 'foo') }
|
132
|
+
end
|
47
133
|
|
48
134
|
context 'with an instance having attributes { :foo => "foo", :bar => "bar", :baz => "baz" }' do
|
49
|
-
let(:instance) {
|
135
|
+
let(:instance) { TestContext.new(foo: 'foo', bar: 'bar', baz: 'baz') }
|
50
136
|
|
51
137
|
it { is_expected.to be_a Hash }
|
52
|
-
it { is_expected.to eq(bar: 'bar',
|
138
|
+
it { is_expected.to eq(bar: 'bar', foo: 'foo') }
|
139
|
+
it 'is expected to assign :baz' do
|
140
|
+
expect(instance.baz).to eq 'baz'
|
141
|
+
end
|
53
142
|
end
|
54
143
|
end
|
55
144
|
end
|
@@ -81,7 +170,7 @@ RSpec.describe ActiveInteractor::Context::Base do
|
|
81
170
|
it { expect { subject }.to raise_error(ActiveInteractor::Error::ContextFailure) }
|
82
171
|
|
83
172
|
it 'is expected not to merge errors' do
|
84
|
-
expect(instance.errors).not_to receive(:merge!)
|
173
|
+
expect(instance.errors).not_to receive(:merge!).with(nil)
|
85
174
|
subject
|
86
175
|
rescue ActiveInteractor::Error::ContextFailure # rubocop:disable Lint/SuppressedException
|
87
176
|
end
|