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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 91b9f4936670919fb0f3f1bda4f9320a3abd439adef16b7bae4d8cf14d3fb6da
4
- data.tar.gz: 725547555164c173ab870afafb3f8ee43b6e355c3fcab3732b5a457d66e4f468
3
+ metadata.gz: f83ff894cc3ce150f3a97ab2b006035acf9f27c181040f02c04e0058b3d3dd49
4
+ data.tar.gz: fd8d75ec724d1b35eec4b7cd2017c74a9fb61c54209f58830a7ffd5b780b5ba8
5
5
  SHA512:
6
- metadata.gz: bfd019dc0f1b7c86a7de23cca6c663b8be68c6ed5d1e4bb11aa6a09101e72537dab5f06f985b1ee38b5f3cd4b763615473031525227d75f14e70bfa48a33f0f2
7
- data.tar.gz: 3c1e0a9d3340ec4362de5232fad83172537819b034fc891b5a1ac74f83f079c0ef03a9f2e6eace44125d1546a315ab4818c8989a4c3c931c050480ee1e82e65e
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.1...HEAD
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&amp;utm_medium=referral&amp;utm_content=aaronmallen/activeinteractor&amp;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(attributes = nil)
17
- copy_flags!(attributes) if attributes
18
- copy_called!(attributes) if attributes
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
- include ActiveModel::Validations
59
- include ActiveInteractor::Models::InstanceMethods
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
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dynamoid/document'
4
+
5
+ Dynamoid::Document::ClassMethods.include ActiveInteractor::Models
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ ActiveSupport.on_load(:mongoid) do
4
+ Mongoid::Document::ClassMethods.include ActiveInteractor::Models
5
+ end
@@ -3,5 +3,5 @@
3
3
  module ActiveInteractor
4
4
  # The ActiveInteractor version
5
5
  # @return [String] the ActiveInteractor version
6
- VERSION = '1.0.1'
6
+ VERSION = '1.0.2'
7
7
  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) do
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(:model_mock) do
51
- build_class('ModelMock', active_record_base_mock) do
52
- attr_accessor :foo
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
- describe 'as an instance' do
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
- require_relative 'support/coverage'
4
-
5
- Spec::Coverage::Runner.start do
6
- add_formatter :simple_cov_html
7
- add_formatter :codacy
8
- track '/lib/**/*.rb'
9
- filter '/spec/'
10
- filter '/lib/rails/**'
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.1
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-01-28 00:00:00.000000000 Z
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.1/CHANGELOG.md
206
- documentation_uri: https://www.rubydoc.info/gems/activeinteractor/1.0.1
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.1
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/active_interactor_spec.rb
231
- - spec/integration/a_failing_interactor_spec.rb
232
- - spec/integration/active_record_integration_spec.rb
233
- - spec/integration/an_interactor_with_validations_on_called_spec.rb
234
- - spec/integration/an_interactor_with_around_perform_callbacks_spec.rb
235
- - spec/integration/an_interactor_with_before_rollback_callbacks_spec.rb
236
- - spec/integration/a_basic_organizer_spec.rb
237
- - spec/integration/an_interactor_with_around_rollback_callbacks_spec.rb
238
- - spec/integration/an_organizer_with_after_each_callbacks_spec.rb
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/an_interactor_with_validations_on_calling_spec.rb
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/an_interactor_with_after_context_validation_callbacks_spec.rb
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/support/spec_helpers.rb
252
- - spec/support/coverage/reporters.rb
253
- - spec/support/coverage/reporters/codacy.rb
254
- - spec/support/coverage/reporters/simple_cov.rb
255
- - spec/support/coverage/runner.rb
256
- - spec/support/shared_examples/a_class_with_organizer_callback_methods_example.rb
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
@@ -1,4 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'coverage/reporters'
4
- require_relative 'coverage/runner'
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Spec
4
- module Coverage
5
- module Reporters
6
- EMPTY_LOAD_RESULT = [{}, [], []].freeze
7
- end
8
- end
9
- end
10
-
11
- Dir[File.expand_path('reporters/*.rb', __dir__)].sort.each { |file| require file }
@@ -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