activeinteractor 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -1
- data/README.md +19 -3
- data/lib/active_interactor/context/attributes.rb +22 -0
- data/lib/active_interactor/context/status.rb +0 -18
- data/lib/active_interactor/models.rb +12 -28
- 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/spec/integration/active_record_integration_spec.rb +8 -342
- data/spec/spec_helper.rb +19 -8
- data/spec/support/shared_examples/a_class_that_extends_active_interactor_models_example.rb +81 -0
- metadata +40 -46
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f83ff894cc3ce150f3a97ab2b006035acf9f27c181040f02c04e0058b3d3dd49
|
4
|
+
data.tar.gz: fd8d75ec724d1b35eec4b7cd2017c74a9fb61c54209f58830a7ffd5b780b5ba8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '085c0039e71216c6c3dc734a4aad4bb30fc0bf5fa5babe8a9b72e2b961c5066732c5bdfbc5eb1566ababc42cbcf38e1b5e3d87e61a94251e08eec2c13a99c524'
|
7
|
+
data.tar.gz: fa572ba8068e8856bfbc405500cffd4b398f47c67d7b665a02ead9a5d701cdb62983f17e6eb6df7c13f7b29b981c58054a7613b6eb4970a488c45d15acc7bc40
|
data/CHANGELOG.md
CHANGED
@@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning].
|
|
7
7
|
|
8
8
|
## [Unreleased]
|
9
9
|
|
10
|
+
## [v1.0.2] - 2020-02-04
|
11
|
+
|
12
|
+
### Added
|
13
|
+
|
14
|
+
- Support for `Dynamoid` ORM
|
15
|
+
- Support for `Mongoid` ORM
|
16
|
+
|
17
|
+
### Changed
|
18
|
+
|
19
|
+
- `ActiveInteractor::Models#acts_as_context` no longer includes `ActiveModel::Validations`
|
20
|
+
- `ActiveInteractor::Models#acts_as_context` now includes `ActiveInteractor::Context::Attributes`
|
21
|
+
|
22
|
+
### Removed
|
23
|
+
|
24
|
+
- `ActiveInteractor::Models::InstanceMethods#merge!`
|
25
|
+
|
10
26
|
## [v1.0.1] - 2020-01-28
|
11
27
|
|
12
28
|
### Added
|
@@ -159,7 +175,8 @@ and this project adheres to [Semantic Versioning].
|
|
159
175
|
|
160
176
|
<!-- versions -->
|
161
177
|
|
162
|
-
[Unreleased]: https://github.com/aaronmallen/activeinteractor/compare/v1.0.
|
178
|
+
[Unreleased]: https://github.com/aaronmallen/activeinteractor/compare/v1.0.2...HEAD
|
179
|
+
[v1.0.2]: https://github.com/aaronmallen/activeinteractor/compare/v1.0.1...v1.0.2
|
163
180
|
[v1.0.1]: https://github.com/aaronmallen/activeinteractor/compare/v1.0.0...v1.0.1
|
164
181
|
[v1.0.0]: https://github.com/aaronmallen/activeinteractor/compare/v0.1.7...v1.0.0
|
165
182
|
[v0.1.7]: https://github.com/aaronmallen/activeinteractor/compare/v0.1.6...v0.1.7
|
data/README.md
CHANGED
@@ -1,17 +1,28 @@
|
|
1
1
|
# ActiveInteractor
|
2
2
|
|
3
3
|
[![Version](https://img.shields.io/gem/v/activeinteractor.svg?logo=ruby)](https://rubygems.org/gems/activeinteractor)
|
4
|
-
[![License](https://img.shields.io/github/license/aaronmallen/activeinteractor.svg?maxAge=300)](https://github.com/aaronmallen/activeinteractor/blob/master/LICENSE)
|
5
|
-
[![Dependencies](https://img.shields.io/depfu/aaronmallen/activeinteractor.svg?maxAge=300)](https://depfu.com/github/aaronmallen/activeinteractor)
|
6
|
-
|
7
4
|
[![Build Status](https://github.com/aaronmallen/activeinteractor/workflows/Build/badge.svg)](https://github.com/aaronmallen/activeinteractor/actions)
|
8
5
|
[![Code Quality](https://api.codacy.com/project/badge/Grade/be92c4ecf12347da82d266f6a4368b6e)](https://www.codacy.com/manual/aaronmallen/activeinteractor?utm_source=github.com&utm_medium=referral&utm_content=aaronmallen/activeinteractor&utm_campaign=Badge_Grade)
|
9
6
|
[![Test Coverage](https://api.codacy.com/project/badge/Coverage/be92c4ecf12347da82d266f6a4368b6e)](https://www.codacy.com/manual/aaronmallen/activeinteractor?utm_source=github.com&utm_medium=referral&utm_content=aaronmallen/activeinteractor&utm_campaign=Badge_Coverage)
|
7
|
+
[![Dependencies](https://img.shields.io/depfu/aaronmallen/activeinteractor.svg?maxAge=300)](https://depfu.com/github/aaronmallen/activeinteractor)
|
8
|
+
[![Yard Docs](http://img.shields.io/badge/yard-docs-blue.svg)](https://www.rubydoc.info/gems/activeinteractor)
|
9
|
+
[![Inline docs](http://inch-ci.org/github/aaronmallen/activeinteractor.svg?branch=master)](http://inch-ci.org/github/aaronmallen/activeinteractor)
|
10
|
+
[![License](https://img.shields.io/github/license/aaronmallen/activeinteractor.svg?maxAge=300)](https://github.com/aaronmallen/activeinteractor/blob/master/LICENSE)
|
10
11
|
|
11
12
|
An implementation of the [command pattern] for Ruby with [ActiveModel::Validations] inspired by the
|
12
13
|
[interactor][collective_idea_interactors] gem. Rich support for attributes, callbacks, and validations,
|
13
14
|
and thread safe performance methods.
|
14
15
|
|
16
|
+
Reduce controller bloat with procedural service objects. Checkout this [Medium article] for a crash
|
17
|
+
course on how to use ActiveInteractors. Read the [wiki] for detailed usage information.
|
18
|
+
|
19
|
+
## Features
|
20
|
+
|
21
|
+
* [Context validation][wiki_context_validation]
|
22
|
+
* [Callbacks][wiki_callbacks]
|
23
|
+
* Thread safe performance calls
|
24
|
+
* Organize multiple interactors [conditionally][wiki_organizers_conditionally] or in [parallel][wiki_organizers_parallel]
|
25
|
+
|
15
26
|
## Getting Started
|
16
27
|
|
17
28
|
Add this line to your application's Gemfile:
|
@@ -68,6 +79,11 @@ The gem is available as open source under the terms of the [MIT License][mit_lic
|
|
68
79
|
[business_logic_wikipedia]: https://en.wikipedia.org/wiki/Business_logic
|
69
80
|
[collective_idea_interactors]: https://github.com/collectiveidea/interactor
|
70
81
|
[command pattern]: https://en.wikipedia.org/wiki/Command_pattern
|
82
|
+
[Medium article]: https://medium.com/@aaronmallen/activeinteractor-8557c0dc78db
|
71
83
|
[mit_license]: https://opensource.org/licenses/MIT
|
72
84
|
[ruby docs]: https://www.rubydoc.info/gems/activeinteractor
|
73
85
|
[wiki]: https://github.com/aaronmallen/activeinteractor/wiki
|
86
|
+
[wiki_callbacks]: https://github.com/aaronmallen/activeinteractor/wiki/Callbacks
|
87
|
+
[wiki_context_validation]: https://github.com/aaronmallen/activeinteractor/wiki/Context#validating-the-context
|
88
|
+
[wiki_organizers_conditionally]: https://github.com/aaronmallen/activeinteractor/wiki/Interactors#organizing-interactors-conditionally
|
89
|
+
[wiki_organizers_parallel]: https://github.com/aaronmallen/activeinteractor/wiki/Interactors#running-interactors-in-parallel
|
@@ -53,6 +53,7 @@ module ActiveInteractor
|
|
53
53
|
merge_errors!(context.errors) if context.respond_to?(:errors)
|
54
54
|
copy_flags!(context)
|
55
55
|
copy_called!(context)
|
56
|
+
context = context_attributes_as_hash(context) || {}
|
56
57
|
super
|
57
58
|
|
58
59
|
merge_attribute_values(context)
|
@@ -114,6 +115,27 @@ module ActiveInteractor
|
|
114
115
|
|
115
116
|
private
|
116
117
|
|
118
|
+
def _called
|
119
|
+
@_called ||= []
|
120
|
+
end
|
121
|
+
|
122
|
+
def context_attributes_as_hash(context)
|
123
|
+
return context.to_h if context&.respond_to?(:to_h)
|
124
|
+
return context.attributes.to_h if context.respond_to?(:attributes)
|
125
|
+
end
|
126
|
+
|
127
|
+
def copy_called!(context)
|
128
|
+
value = context.instance_variable_get('@_called') || []
|
129
|
+
instance_variable_set('@_called', value)
|
130
|
+
end
|
131
|
+
|
132
|
+
def copy_flags!(context)
|
133
|
+
%w[_failed _rolled_back].each do |flag|
|
134
|
+
value = context.instance_variable_get("@#{flag}")
|
135
|
+
instance_variable_set("@#{flag}", value)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
117
139
|
def merge_attribute_values(context)
|
118
140
|
return unless context
|
119
141
|
|
@@ -90,24 +90,6 @@ module ActiveInteractor
|
|
90
90
|
!failure?
|
91
91
|
end
|
92
92
|
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
93
|
end
|
112
94
|
end
|
113
95
|
end
|
@@ -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,11 @@ 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
|
60
43
|
include ActiveInteractor::Context::Status
|
44
|
+
include ActiveInteractor::Models::InstanceMethods
|
61
45
|
delegate :each_pair, to: :attributes
|
62
46
|
end
|
63
47
|
end
|
@@ -6,356 +6,22 @@ begin
|
|
6
6
|
require 'active_interactor/rails/orm/active_record'
|
7
7
|
|
8
8
|
RSpec.describe 'ActiveRecord integration', type: :integration do
|
9
|
-
let!(:active_record_base_mock)
|
10
|
-
build_class('ActiveRecordBaseMock') do
|
11
|
-
def self.attr_accessor(*attributes)
|
12
|
-
attribute_keys.concat(attributes.map(&:to_sym))
|
13
|
-
super
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.attribute_keys
|
17
|
-
@attribute_keys ||= []
|
18
|
-
end
|
19
|
-
|
20
|
-
def initialize(attributes = nil, _options = {})
|
21
|
-
(attributes || {}).each do |key, value|
|
22
|
-
instance_variable_set("@#{key}", value)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def [](name)
|
27
|
-
instance_variable_get("@#{name}")
|
28
|
-
end
|
29
|
-
|
30
|
-
def []=(name, value)
|
31
|
-
instance_variable_set("@#{name}", value)
|
32
|
-
end
|
33
|
-
|
34
|
-
def attributes
|
35
|
-
self.class.attribute_keys.each_with_object({}) do |key, hash|
|
36
|
-
hash[key] = instance_variable_get("@#{key}")
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def to_h
|
41
|
-
attributes.to_h
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
9
|
+
let!(:active_record_base_mock) { build_class('ActiveRecordBaseMock') }
|
45
10
|
|
46
11
|
context 'after ActiveSupport.run_load_hooks has been received with :active_record' do
|
47
12
|
before { ActiveSupport.run_load_hooks(:active_record, active_record_base_mock) }
|
48
13
|
|
49
|
-
describe 'an ActiveRecord model class with .acts_as_context' do
|
50
|
-
let(:
|
51
|
-
build_class('
|
52
|
-
|
14
|
+
describe 'an ActiveRecord model class with .acts_as_context and attribute :foo' do
|
15
|
+
let(:model_class) do
|
16
|
+
build_class('ModelClass', active_record_base_mock) do
|
17
|
+
include ActiveModel::Attributes
|
18
|
+
include ActiveModel::Model
|
53
19
|
acts_as_context
|
20
|
+
attribute :foo
|
54
21
|
end
|
55
22
|
end
|
56
23
|
|
57
|
-
|
58
|
-
subject { model_mock.new }
|
59
|
-
|
60
|
-
it { is_expected.to respond_to :called! }
|
61
|
-
it { is_expected.to respond_to :fail! }
|
62
|
-
it { is_expected.to respond_to :fail? }
|
63
|
-
it { is_expected.to respond_to :failure? }
|
64
|
-
it { is_expected.to respond_to :merge! }
|
65
|
-
it { is_expected.to respond_to :rollback! }
|
66
|
-
it { is_expected.to respond_to :success? }
|
67
|
-
it { is_expected.to respond_to :successful? }
|
68
|
-
end
|
69
|
-
|
70
|
-
describe '.new' do
|
71
|
-
subject { model_mock.new(attributes) }
|
72
|
-
let(:attributes) { nil }
|
73
|
-
|
74
|
-
it 'is expected not to receive #copy_flags!' do
|
75
|
-
expect_any_instance_of(model_mock).not_to receive(:copy_flags!)
|
76
|
-
subject
|
77
|
-
end
|
78
|
-
|
79
|
-
it 'is expected not to receive #copy_called!' do
|
80
|
-
expect_any_instance_of(model_mock).not_to receive(:copy_called!)
|
81
|
-
subject
|
82
|
-
end
|
83
|
-
|
84
|
-
it 'is expected to receive super on parent class with nil attributes' do
|
85
|
-
expect(active_record_base_mock).to receive(:new).with(nil)
|
86
|
-
subject
|
87
|
-
end
|
88
|
-
|
89
|
-
context 'with attributes { :foo => "foo" }' do
|
90
|
-
let(:attributes) { { foo: 'foo' } }
|
91
|
-
|
92
|
-
it { expect { subject }.not_to raise_error }
|
93
|
-
|
94
|
-
it 'is expected to receive #copy_flags!' do
|
95
|
-
expect_any_instance_of(model_mock).to receive(:copy_flags!).with(foo: 'foo')
|
96
|
-
subject
|
97
|
-
end
|
98
|
-
|
99
|
-
it 'is expected to receive #copy_called!' do
|
100
|
-
expect_any_instance_of(model_mock).to receive(:copy_called!).with(foo: 'foo')
|
101
|
-
subject
|
102
|
-
end
|
103
|
-
|
104
|
-
it 'is expected to receive super on parent class with { :foo => "foo" }' do
|
105
|
-
expect(active_record_base_mock).to receive(:new).with(foo: 'foo')
|
106
|
-
subject
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
context 'with attributes being an instance of ModelMock having attributes { :foo => "foo" }' do
|
111
|
-
let(:previous_instance) { model_mock.new(foo: 'foo') }
|
112
|
-
let(:attributes) { previous_instance }
|
113
|
-
|
114
|
-
it { is_expected.to have_attributes(foo: 'foo') }
|
115
|
-
|
116
|
-
context 'with _failed equal to true on previous instance' do
|
117
|
-
before { previous_instance.instance_variable_set('@_failed', true) }
|
118
|
-
|
119
|
-
it { is_expected.to be_failure }
|
120
|
-
end
|
121
|
-
|
122
|
-
context 'with _rolled_back equal to true on previous instance' do
|
123
|
-
before { previous_instance.instance_variable_set('@_rolled_back', true) }
|
124
|
-
|
125
|
-
it 'is expected to have instance variable @_rolled_back eq to true' do
|
126
|
-
expect(subject.instance_variable_get('@_rolled_back')).to eq true
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
context 'with _called eq to ["foo"] on previous instance' do
|
131
|
-
before { previous_instance.instance_variable_set('@_called', %w[foo]) }
|
132
|
-
|
133
|
-
it 'is expected to have instance variable @_called eq to ["foo"]' do
|
134
|
-
expect(subject.instance_variable_get('@_called')).to eq %w[foo]
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
describe '#merge!' do
|
141
|
-
subject { model_mock.new(attributes).merge!(merge_instance) }
|
142
|
-
context 'having attributes { :foo => nil }' do
|
143
|
-
let(:attributes) { { foo: nil } }
|
144
|
-
|
145
|
-
context 'with merging instance having attributes { :foo => "foo" }' do
|
146
|
-
let(:merge_instance) { model_mock.new(foo: 'foo') }
|
147
|
-
|
148
|
-
it { is_expected.to have_attributes(foo: 'foo') }
|
149
|
-
|
150
|
-
context 'with _failed equal to true on merging instance' do
|
151
|
-
before { merge_instance.instance_variable_set('@_failed', true) }
|
152
|
-
|
153
|
-
it { is_expected.to be_failure }
|
154
|
-
end
|
155
|
-
|
156
|
-
context 'with _rolled_back equal to true on merging instance' do
|
157
|
-
before { merge_instance.instance_variable_set('@_rolled_back', true) }
|
158
|
-
|
159
|
-
it 'is expected to have instance variable @_rolled_back eq to true' do
|
160
|
-
expect(subject.instance_variable_get('@_rolled_back')).to eq true
|
161
|
-
end
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
context 'having attributes { :foo => "foo"}' do
|
167
|
-
let(:attributes) { { foo: 'foo' } }
|
168
|
-
|
169
|
-
context 'with merging instance having attributes { :foo => "bar" }' do
|
170
|
-
let(:merge_instance) { model_mock.new(foo: 'bar') }
|
171
|
-
|
172
|
-
it { is_expected.to have_attributes(foo: 'bar') }
|
173
|
-
|
174
|
-
context 'with _failed equal to true on merging instance' do
|
175
|
-
before { merge_instance.instance_variable_set('@_failed', true) }
|
176
|
-
|
177
|
-
it { is_expected.to be_failure }
|
178
|
-
end
|
179
|
-
|
180
|
-
context 'with _rolled_back equal to true on merging instance' do
|
181
|
-
before { merge_instance.instance_variable_set('@_rolled_back', true) }
|
182
|
-
|
183
|
-
it 'is expected to have instance variable @_rolled_back eq to true' do
|
184
|
-
expect(subject.instance_variable_get('@_rolled_back')).to eq true
|
185
|
-
end
|
186
|
-
end
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
describe 'a basic interactor using an ActiveRecord model class as context' do
|
193
|
-
let!(:model_mock) do
|
194
|
-
require 'active_model'
|
195
|
-
build_class('ModelMock', active_record_base_mock) do
|
196
|
-
include ActiveModel::Validations
|
197
|
-
attr_accessor :foo
|
198
|
-
acts_as_context
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
let(:interactor_class) do
|
203
|
-
build_interactor do
|
204
|
-
contextualize_with :model_mock
|
205
|
-
|
206
|
-
def perform
|
207
|
-
context.foo = 'foo'
|
208
|
-
end
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
include_examples 'a class with interactor methods'
|
213
|
-
include_examples 'a class with interactor callback methods'
|
214
|
-
include_examples 'a class with interactor context methods'
|
215
|
-
|
216
|
-
describe '.context_class' do
|
217
|
-
subject { interactor_class.context_class }
|
218
|
-
|
219
|
-
it { is_expected.to eq model_mock }
|
220
|
-
end
|
221
|
-
|
222
|
-
describe '.perform' do
|
223
|
-
subject { interactor_class.perform }
|
224
|
-
|
225
|
-
it { is_expected.to be_a model_mock }
|
226
|
-
it { is_expected.to be_successful }
|
227
|
-
it { is_expected.to have_attributes(foo: 'foo') }
|
228
|
-
end
|
229
|
-
|
230
|
-
describe '.perform!' do
|
231
|
-
subject { interactor_class.perform! }
|
232
|
-
|
233
|
-
it { expect { subject }.not_to raise_error }
|
234
|
-
it { is_expected.to be_a model_mock }
|
235
|
-
it { is_expected.to be_successful }
|
236
|
-
it { is_expected.to have_attributes(foo: 'foo') }
|
237
|
-
end
|
238
|
-
|
239
|
-
context 'failing the context on #perform' do
|
240
|
-
let(:interactor_class) do
|
241
|
-
build_interactor do
|
242
|
-
contextualize_with :model_mock
|
243
|
-
|
244
|
-
def perform
|
245
|
-
context.fail!
|
246
|
-
end
|
247
|
-
end
|
248
|
-
end
|
249
|
-
|
250
|
-
describe '.perform' do
|
251
|
-
subject { interactor_class.perform }
|
252
|
-
|
253
|
-
it { expect { subject }.not_to raise_error }
|
254
|
-
it { is_expected.to be_a model_mock }
|
255
|
-
it { is_expected.to be_failure }
|
256
|
-
it 'is expected to receive #rollback' do
|
257
|
-
expect_any_instance_of(interactor_class).to receive(:rollback)
|
258
|
-
subject
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
describe '.perform!' do
|
263
|
-
subject { interactor_class.perform! }
|
264
|
-
|
265
|
-
it { expect { subject }.to raise_error(ActiveInteractor::Error::ContextFailure) }
|
266
|
-
end
|
267
|
-
end
|
268
|
-
end
|
269
|
-
|
270
|
-
describe 'a basic organizer using an ActiveRecord model class as context' do
|
271
|
-
let!(:model_mock) do
|
272
|
-
require 'active_model'
|
273
|
-
build_class('ModelMock', active_record_base_mock) do
|
274
|
-
include ActiveModel::Validations
|
275
|
-
attr_accessor :first_name, :last_name
|
276
|
-
acts_as_context
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
|
-
context 'with each organized interactor using the model' do
|
281
|
-
let!(:test_interactor_1) do
|
282
|
-
build_interactor('TestInteractor1') do
|
283
|
-
contextualize_with :model_mock
|
284
|
-
|
285
|
-
def perform
|
286
|
-
context.first_name = 'Test'
|
287
|
-
end
|
288
|
-
end
|
289
|
-
end
|
290
|
-
|
291
|
-
let!(:test_interactor_2) do
|
292
|
-
build_interactor('TestInteractor2') do
|
293
|
-
contextualize_with :model_mock
|
294
|
-
|
295
|
-
def perform
|
296
|
-
context.last_name = 'User'
|
297
|
-
end
|
298
|
-
end
|
299
|
-
end
|
300
|
-
|
301
|
-
let(:interactor_class) do
|
302
|
-
build_organizer do
|
303
|
-
contextualize_with :model_mock
|
304
|
-
organize :test_interactor_1, :test_interactor_2
|
305
|
-
end
|
306
|
-
end
|
307
|
-
|
308
|
-
include_examples 'a class with interactor methods'
|
309
|
-
include_examples 'a class with interactor callback methods'
|
310
|
-
include_examples 'a class with interactor context methods'
|
311
|
-
include_examples 'a class with organizer callback methods'
|
312
|
-
|
313
|
-
describe '.perform' do
|
314
|
-
subject { interactor_class.perform }
|
315
|
-
|
316
|
-
it { is_expected.to be_a model_mock }
|
317
|
-
it { is_expected.to be_successful }
|
318
|
-
it { is_expected.to have_attributes(first_name: 'Test', last_name: 'User') }
|
319
|
-
end
|
320
|
-
end
|
321
|
-
|
322
|
-
context 'with each organized interactor using their default context' do
|
323
|
-
let!(:test_interactor_1) do
|
324
|
-
build_interactor('TestInteractor1') do
|
325
|
-
def perform
|
326
|
-
context.first_name = 'Test'
|
327
|
-
end
|
328
|
-
end
|
329
|
-
end
|
330
|
-
|
331
|
-
let!(:test_interactor_2) do
|
332
|
-
build_interactor('TestInteractor2') do
|
333
|
-
def perform
|
334
|
-
context.last_name = 'User'
|
335
|
-
end
|
336
|
-
end
|
337
|
-
end
|
338
|
-
|
339
|
-
let(:interactor_class) do
|
340
|
-
build_organizer do
|
341
|
-
contextualize_with :model_mock
|
342
|
-
organize :test_interactor_1, :test_interactor_2
|
343
|
-
end
|
344
|
-
end
|
345
|
-
|
346
|
-
include_examples 'a class with interactor methods'
|
347
|
-
include_examples 'a class with interactor callback methods'
|
348
|
-
include_examples 'a class with interactor context methods'
|
349
|
-
include_examples 'a class with organizer callback methods'
|
350
|
-
|
351
|
-
describe '.perform' do
|
352
|
-
subject { interactor_class.perform }
|
353
|
-
|
354
|
-
it { is_expected.to be_a model_mock }
|
355
|
-
it { is_expected.to be_successful }
|
356
|
-
it { is_expected.to have_attributes(first_name: 'Test', last_name: 'User') }
|
357
|
-
end
|
358
|
-
end
|
24
|
+
include_examples 'A class that extends ActiveInteractor::Models'
|
359
25
|
end
|
360
26
|
end
|
361
27
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,13 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
3
|
+
begin
|
4
|
+
require 'codacy-coverage'
|
5
|
+
require 'simplecov'
|
6
|
+
|
7
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(
|
8
|
+
[
|
9
|
+
SimpleCov::Formatter::HTMLFormatter,
|
10
|
+
Codacy::Formatter
|
11
|
+
]
|
12
|
+
)
|
13
|
+
|
14
|
+
SimpleCov.start do
|
15
|
+
enable_coverage :branch
|
16
|
+
add_filter '/spec/'
|
17
|
+
add_filter '/lib/rails/**/*.rb'
|
18
|
+
track_files '/lib/**/*.rb'
|
19
|
+
end
|
20
|
+
rescue LoadError
|
21
|
+
puts 'Skipping coverage...'
|
11
22
|
end
|
12
23
|
|
13
24
|
require 'bundler/setup'
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.shared_examples 'A class that extends ActiveInteractor::Models' do
|
4
|
+
it { expect(model_class).to respond_to :attribute }
|
5
|
+
it { expect(model_class).to respond_to :attributes }
|
6
|
+
|
7
|
+
describe 'as an instance' do
|
8
|
+
subject { model_class.new }
|
9
|
+
|
10
|
+
it { is_expected.to respond_to :attributes }
|
11
|
+
it { is_expected.to respond_to :called! }
|
12
|
+
it { is_expected.to respond_to :fail! }
|
13
|
+
it { is_expected.to respond_to :fail? }
|
14
|
+
it { is_expected.to respond_to :failure? }
|
15
|
+
it { is_expected.to respond_to :merge! }
|
16
|
+
it { is_expected.to respond_to :rollback! }
|
17
|
+
it { is_expected.to respond_to :success? }
|
18
|
+
it { is_expected.to respond_to :successful? }
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '.new' do
|
22
|
+
subject { model_class.new(attributes) }
|
23
|
+
|
24
|
+
describe 'with arguments {:foo => "foo"}' do
|
25
|
+
let(:attributes) { { foo: 'foo' } }
|
26
|
+
|
27
|
+
it { is_expected.to have_attributes(foo: 'foo') }
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'with arguments {:bar => "bar"}' do
|
31
|
+
let(:attributes) { model_class.new(bar: 'bar') }
|
32
|
+
|
33
|
+
it { expect { subject }.to raise_error(ActiveModel::UnknownAttributeError) }
|
34
|
+
end
|
35
|
+
|
36
|
+
describe 'with arguments <#ModelClass foo="foo">' do
|
37
|
+
let(:other_instance) { model_class.new(foo: 'foo') }
|
38
|
+
let(:attributes) { other_instance }
|
39
|
+
|
40
|
+
it { is_expected.to have_attributes(foo: 'foo') }
|
41
|
+
|
42
|
+
context 'with argument instance having @_failed eq to true' do
|
43
|
+
before { other_instance.instance_variable_set('@_failed', true) }
|
44
|
+
|
45
|
+
it { is_expected.to be_failure }
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'with argument instance having @_called eq to ["foo"]' do
|
49
|
+
before { other_instance.instance_variable_set('@_called', %w[foo]) }
|
50
|
+
|
51
|
+
it 'is expected to have instance variable @_called eq to ["foo"]' do
|
52
|
+
expect(subject.instance_variable_get('@_called')).to eq %w[foo]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'with argument instance having @_rolled_back eq to true' do
|
57
|
+
before { other_instance.instance_variable_set('@_rolled_back', true) }
|
58
|
+
|
59
|
+
it 'is expected to have instance variable @_rolled_back eq to true' do
|
60
|
+
expect(subject.instance_variable_get('@_rolled_back')).to eq true
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe 'with arguments <#OtherClass bar="bar">' do
|
66
|
+
let(:attributes) { model_class.new(other_instance) }
|
67
|
+
let!(:other_class) do
|
68
|
+
build_class('OtherClass') do
|
69
|
+
include ActiveModel::Attributes
|
70
|
+
include ActiveModel::Model
|
71
|
+
extend ActiveInteractor::Models
|
72
|
+
acts_as_context
|
73
|
+
attribute :bar
|
74
|
+
end
|
75
|
+
end
|
76
|
+
let(:other_instance) { other_class.new(bar: 'bar') }
|
77
|
+
|
78
|
+
it { expect { subject }.to raise_error(ActiveModel::UnknownAttributeError) }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activeinteractor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Allen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-02-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -127,6 +127,8 @@ files:
|
|
127
127
|
- lib/active_interactor/organizer/perform.rb
|
128
128
|
- lib/active_interactor/rails.rb
|
129
129
|
- lib/active_interactor/rails/orm/active_record.rb
|
130
|
+
- lib/active_interactor/rails/orm/dynamoid.rb
|
131
|
+
- lib/active_interactor/rails/orm/mongoid.rb
|
130
132
|
- lib/active_interactor/rails/railtie.rb
|
131
133
|
- lib/active_interactor/version.rb
|
132
134
|
- lib/rails/generators/active_interactor.rb
|
@@ -186,12 +188,8 @@ files:
|
|
186
188
|
- spec/integration/an_organizer_with_before_each_callbacks_spec.rb
|
187
189
|
- spec/integration/an_organizer_with_conditionally_organized_interactors_spec.rb
|
188
190
|
- spec/spec_helper.rb
|
189
|
-
- spec/support/coverage.rb
|
190
|
-
- spec/support/coverage/reporters.rb
|
191
|
-
- spec/support/coverage/reporters/codacy.rb
|
192
|
-
- spec/support/coverage/reporters/simple_cov.rb
|
193
|
-
- spec/support/coverage/runner.rb
|
194
191
|
- spec/support/helpers/factories.rb
|
192
|
+
- spec/support/shared_examples/a_class_that_extends_active_interactor_models_example.rb
|
195
193
|
- spec/support/shared_examples/a_class_with_interactor_callback_methods_example.rb
|
196
194
|
- spec/support/shared_examples/a_class_with_interactor_context_methods_example.rb
|
197
195
|
- spec/support/shared_examples/a_class_with_interactor_methods_example.rb
|
@@ -202,10 +200,10 @@ licenses:
|
|
202
200
|
- MIT
|
203
201
|
metadata:
|
204
202
|
bug_tracker_uri: https://github.com/aaronmallen/activeinteractor/issues
|
205
|
-
changelog_uri: https://github.com/aaronmallen/activeinteractor/blob/v1.0.
|
206
|
-
documentation_uri: https://www.rubydoc.info/gems/activeinteractor/1.0.
|
203
|
+
changelog_uri: https://github.com/aaronmallen/activeinteractor/blob/v1.0.2/CHANGELOG.md
|
204
|
+
documentation_uri: https://www.rubydoc.info/gems/activeinteractor/1.0.2
|
207
205
|
hompage_uri: https://github.com/aaronmallen/activeinteractor
|
208
|
-
source_code_uri: https://github.com/aaronmallen/activeinteractor/tree/v1.0.
|
206
|
+
source_code_uri: https://github.com/aaronmallen/activeinteractor/tree/v1.0.2
|
209
207
|
wiki_uri: https://github.com/aaronmallen/activeinteractor/wiki
|
210
208
|
post_install_message:
|
211
209
|
rdoc_options: []
|
@@ -227,45 +225,41 @@ signing_key:
|
|
227
225
|
specification_version: 4
|
228
226
|
summary: Ruby interactors with ActiveModel::Validations
|
229
227
|
test_files:
|
230
|
-
- spec/
|
231
|
-
- spec/
|
232
|
-
- spec/
|
233
|
-
- spec/
|
234
|
-
- spec/
|
235
|
-
- spec/
|
236
|
-
- spec/
|
237
|
-
- spec/
|
238
|
-
- spec/
|
228
|
+
- spec/spec_helper.rb
|
229
|
+
- spec/support/helpers/factories.rb
|
230
|
+
- spec/support/spec_helpers.rb
|
231
|
+
- spec/support/shared_examples/a_class_with_interactor_context_methods_example.rb
|
232
|
+
- spec/support/shared_examples/a_class_with_interactor_methods_example.rb
|
233
|
+
- spec/support/shared_examples/a_class_that_extends_active_interactor_models_example.rb
|
234
|
+
- spec/support/shared_examples/a_class_with_organizer_callback_methods_example.rb
|
235
|
+
- spec/support/shared_examples/a_class_with_interactor_callback_methods_example.rb
|
236
|
+
- spec/active_interactor/interactor/perform/options_spec.rb
|
237
|
+
- spec/active_interactor/interactor/worker_spec.rb
|
238
|
+
- spec/active_interactor/error_spec.rb
|
239
|
+
- spec/active_interactor/config_spec.rb
|
240
|
+
- spec/active_interactor/organizer/interactor_interface_collection_spec.rb
|
241
|
+
- spec/active_interactor/organizer/interactor_interface_spec.rb
|
242
|
+
- spec/active_interactor/organizer/base_spec.rb
|
243
|
+
- spec/active_interactor/base_spec.rb
|
244
|
+
- spec/active_interactor/context/base_spec.rb
|
239
245
|
- spec/integration/an_organizer_performing_in_parallel_spec.rb
|
240
|
-
- spec/integration/an_interactor_with_an_existing_context_class_spec.rb
|
241
|
-
- spec/integration/an_interactor_with_after_rollback_callbacks_spec.rb
|
242
|
-
- spec/integration/an_interactor_with_validations_spec.rb
|
243
246
|
- spec/integration/a_basic_interactor_spec.rb
|
244
|
-
- spec/integration/
|
247
|
+
- spec/integration/an_interactor_with_an_existing_context_class_spec.rb
|
248
|
+
- spec/integration/a_failing_interactor_spec.rb
|
245
249
|
- spec/integration/an_interactor_with_before_perform_callbacks_spec.rb
|
246
|
-
- spec/integration/an_organizer_with_before_each_callbacks_spec.rb
|
247
250
|
- spec/integration/an_organizer_with_conditionally_organized_interactors_spec.rb
|
251
|
+
- spec/integration/an_interactor_with_validations_spec.rb
|
252
|
+
- spec/integration/an_organizer_with_before_each_callbacks_spec.rb
|
253
|
+
- spec/integration/an_interactor_with_after_rollback_callbacks_spec.rb
|
248
254
|
- spec/integration/an_organizer_with_around_each_callbacks_spec.rb
|
249
|
-
- spec/integration/
|
255
|
+
- spec/integration/an_interactor_with_before_rollback_callbacks_spec.rb
|
256
|
+
- spec/integration/an_interactor_with_validations_on_calling_spec.rb
|
257
|
+
- spec/integration/an_organizer_with_after_each_callbacks_spec.rb
|
258
|
+
- spec/integration/a_basic_organizer_spec.rb
|
250
259
|
- spec/integration/an_interactor_with_after_perform_callbacks_spec.rb
|
251
|
-
- spec/
|
252
|
-
- spec/
|
253
|
-
- spec/
|
254
|
-
- spec/
|
255
|
-
- spec/
|
256
|
-
- spec/
|
257
|
-
- spec/support/shared_examples/a_class_with_interactor_callback_methods_example.rb
|
258
|
-
- spec/support/shared_examples/a_class_with_interactor_methods_example.rb
|
259
|
-
- spec/support/shared_examples/a_class_with_interactor_context_methods_example.rb
|
260
|
-
- spec/support/helpers/factories.rb
|
261
|
-
- spec/support/coverage.rb
|
262
|
-
- spec/spec_helper.rb
|
263
|
-
- spec/active_interactor/context/base_spec.rb
|
264
|
-
- spec/active_interactor/base_spec.rb
|
265
|
-
- spec/active_interactor/config_spec.rb
|
266
|
-
- spec/active_interactor/organizer/base_spec.rb
|
267
|
-
- spec/active_interactor/organizer/interactor_interface_spec.rb
|
268
|
-
- spec/active_interactor/organizer/interactor_interface_collection_spec.rb
|
269
|
-
- spec/active_interactor/interactor/worker_spec.rb
|
270
|
-
- spec/active_interactor/interactor/perform/options_spec.rb
|
271
|
-
- spec/active_interactor/error_spec.rb
|
260
|
+
- spec/integration/an_interactor_with_around_rollback_callbacks_spec.rb
|
261
|
+
- spec/integration/an_interactor_with_around_perform_callbacks_spec.rb
|
262
|
+
- spec/integration/an_interactor_with_validations_on_called_spec.rb
|
263
|
+
- spec/integration/an_interactor_with_after_context_validation_callbacks_spec.rb
|
264
|
+
- spec/integration/active_record_integration_spec.rb
|
265
|
+
- spec/active_interactor_spec.rb
|
data/spec/support/coverage.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Spec
|
4
|
-
module Coverage
|
5
|
-
module Reporters
|
6
|
-
module Codacy
|
7
|
-
class << self
|
8
|
-
def load
|
9
|
-
return EMPTY_LOAD_RESULT unless load_dependencies
|
10
|
-
|
11
|
-
[formatters, initialize_steps, run_steps]
|
12
|
-
end
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
def load_dependencies
|
17
|
-
require 'codacy-coverage'
|
18
|
-
true
|
19
|
-
rescue LoadError
|
20
|
-
puts 'Skipping Codacy Coverage reporting...'
|
21
|
-
false
|
22
|
-
end
|
23
|
-
|
24
|
-
def formatters
|
25
|
-
{ codacy: ::Codacy::Formatter }
|
26
|
-
end
|
27
|
-
|
28
|
-
def initialize_steps
|
29
|
-
[]
|
30
|
-
end
|
31
|
-
|
32
|
-
def run_steps
|
33
|
-
[]
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,54 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Spec
|
4
|
-
module Coverage
|
5
|
-
module Reporters
|
6
|
-
module SimpleCov
|
7
|
-
class << self
|
8
|
-
def load
|
9
|
-
return EMPTY_LOAD_RESULT unless load_dependencies
|
10
|
-
|
11
|
-
[formatters, initialize_steps, run_steps]
|
12
|
-
end
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
def load_dependencies
|
17
|
-
require 'simplecov'
|
18
|
-
true
|
19
|
-
rescue LoadError
|
20
|
-
puts 'Skipping SimpleCov reporting...'
|
21
|
-
false
|
22
|
-
end
|
23
|
-
|
24
|
-
def formatters
|
25
|
-
{ simple_cov_html: ::SimpleCov::Formatter::HTMLFormatter }
|
26
|
-
end
|
27
|
-
|
28
|
-
def initialize_steps
|
29
|
-
[setup_formatters]
|
30
|
-
end
|
31
|
-
|
32
|
-
def run_steps
|
33
|
-
[start_simplecov]
|
34
|
-
end
|
35
|
-
|
36
|
-
def setup_formatters
|
37
|
-
lambda do |runner|
|
38
|
-
::SimpleCov.formatter = ::SimpleCov::Formatter::MultiFormatter.new(runner.formatters)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def start_simplecov
|
43
|
-
lambda do |runner|
|
44
|
-
::SimpleCov.start do
|
45
|
-
runner.tracked_files.each { |f| track_files f }
|
46
|
-
runner.filtered_files.each { |f| add_filter f }
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
@@ -1,66 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Spec
|
4
|
-
module Coverage
|
5
|
-
class Runner
|
6
|
-
attr_accessor :filtered_files, :formatters, :tracked_files
|
7
|
-
|
8
|
-
def self.start(&block)
|
9
|
-
instance = new
|
10
|
-
instance.instance_eval(&block) if block
|
11
|
-
instance.start
|
12
|
-
end
|
13
|
-
|
14
|
-
def initialize(options = {})
|
15
|
-
load_reporters!
|
16
|
-
@formatters = options[:formatters] || []
|
17
|
-
@filtered_files = options[:filtered_files] || []
|
18
|
-
@tracked_files = options[:tracked_files] || []
|
19
|
-
end
|
20
|
-
|
21
|
-
def add_formatter(formatter)
|
22
|
-
formatter_class = reporters[:formatters][formatter.to_sym]
|
23
|
-
formatters << formatter_class if formatter_class
|
24
|
-
self
|
25
|
-
end
|
26
|
-
|
27
|
-
def filter(pattern)
|
28
|
-
filtered_files << pattern
|
29
|
-
self
|
30
|
-
end
|
31
|
-
|
32
|
-
def start
|
33
|
-
initialize_reporters
|
34
|
-
run_reporters
|
35
|
-
end
|
36
|
-
|
37
|
-
def track(pattern)
|
38
|
-
tracked_files << pattern
|
39
|
-
self
|
40
|
-
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
attr_reader :reporters
|
45
|
-
|
46
|
-
def initialize_reporters
|
47
|
-
reporters[:initialize_steps].each { |step| step.call(self) }
|
48
|
-
end
|
49
|
-
|
50
|
-
def load_reporters!
|
51
|
-
@reporters = { formatters: {}, initialize_steps: [], run_steps: [] }
|
52
|
-
%w[SimpleCov Codacy].each do |dep|
|
53
|
-
reporter = Reporters.const_get(dep)
|
54
|
-
formatters, initialize_steps, run_steps = reporter.load
|
55
|
-
@reporters[:formatters].merge!(formatters)
|
56
|
-
@reporters[:initialize_steps].concat(initialize_steps)
|
57
|
-
@reporters[:run_steps].concat(run_steps)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def run_reporters
|
62
|
-
reporters[:run_steps].each { |step| step.call(self) }
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|