activeinteractor 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: df118b852db85867fab87a6582604a59c89fd0a194843e569c663cb09b969abc
4
- data.tar.gz: 281f4e6672238ccfac070bd0c17f6831f76b455c26444a49945388b85738153c
3
+ metadata.gz: 91b9f4936670919fb0f3f1bda4f9320a3abd439adef16b7bae4d8cf14d3fb6da
4
+ data.tar.gz: 725547555164c173ab870afafb3f8ee43b6e355c3fcab3732b5a457d66e4f468
5
5
  SHA512:
6
- metadata.gz: 19822562f299f87b863686d0449e4c66b31096696f9f73c47e2c226a62413cdd8a379150a9e5d35a7d3f5e35433300b787965111a0bf0f9a0e29bcf4628afa04
7
- data.tar.gz: dee8cdf2ad05de200a09549fd3ad4f2c904e34da01374230d69a6a040d2ea9c0542e76cae81a80b0bbd259f81c413784934e21e8069dbfda1b16a1acc1247056
6
+ metadata.gz: bfd019dc0f1b7c86a7de23cca6c663b8be68c6ed5d1e4bb11aa6a09101e72537dab5f06f985b1ee38b5f3cd4b763615473031525227d75f14e70bfa48a33f0f2
7
+ data.tar.gz: 3c1e0a9d3340ec4362de5232fad83172537819b034fc891b5a1ac74f83f079c0ef03a9f2e6eace44125d1546a315ab4818c8989a4c3c931c050480ee1e82e65e
data/CHANGELOG.md CHANGED
@@ -7,6 +7,31 @@ and this project adheres to [Semantic Versioning].
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [v1.0.1] - 2020-01-28
11
+
12
+ ### Added
13
+
14
+ - `ActiveInteractor::Context::Attributes#attribute?`
15
+ - `ActiveInteractor::Context::Attributes#has_attribute?`
16
+ - `ActiveInteractor::Context::Base.attribute`
17
+ - `ActiveInteractor::Context::Base.attribute_missing`
18
+ - `ActiveInteractor::Context::Base.attribute_names`
19
+ - `ActiveInteractor::Context::Base.method_missing`
20
+ - `ActiveInteractor::Context::Base.respond_to?`
21
+ - `ActiveInteractor::Context::Base.respond_to_without_attributes?`
22
+ - `ActiveInteractor::Context::Base#attribute_missing`
23
+ - `ActiveInteractor::Context::Base#attribute_names`
24
+ - `ActiveInteractor::Context::Base#method_missing`
25
+ - `ActiveInteractor::Context::Base#respond_to?`
26
+ - `ActiveInteractor::Context::Base#respond_to_without_attributes?`
27
+ - `ActiveInteractor::Interactor::Context#context_attribute_missing`
28
+ - `ActiveInteractor::Interactor::Context#context_attribute_names`
29
+ - `ActiveInteractor::Interactor::Context#context_respond_to_without_attributes?`
30
+ - `ActiveInteractor::Interactor::Context::ClassMethods#context_attribute`
31
+ - `ActiveInteractor::Interactor::Context::ClassMethods#context_attribute_missing`
32
+ - `ActiveInteractor::Interactor::Context::ClassMethods#context_attribute_names`
33
+ - `ActiveInteractor::Interactor::Context::ClassMethods#context_respond_to_without_attributes?`
34
+
10
35
  ## [v1.0.0] - 2020-01-26
11
36
 
12
37
  ### Added
@@ -134,7 +159,8 @@ and this project adheres to [Semantic Versioning].
134
159
 
135
160
  <!-- versions -->
136
161
 
137
- [Unreleased]: https://github.com/aaronmallen/activeinteractor/compare/v1.0.0...HEAD
162
+ [Unreleased]: https://github.com/aaronmallen/activeinteractor/compare/v1.0.1...HEAD
163
+ [v1.0.1]: https://github.com/aaronmallen/activeinteractor/compare/v1.0.0...v1.0.1
138
164
  [v1.0.0]: https://github.com/aaronmallen/activeinteractor/compare/v0.1.7...v1.0.0
139
165
  [v0.1.7]: https://github.com/aaronmallen/activeinteractor/compare/v0.1.6...v0.1.7
140
166
  [v0.1.6]: https://github.com/aaronmallen/activeinteractor/compare/v0.1.5...v0.1.6
data/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
  [![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
9
  [![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)
10
10
 
11
- An implementation of the [command pattern] for Ruby with [ActiveModel::Validations] based on the
11
+ An implementation of the [command pattern] for Ruby with [ActiveModel::Validations] inspired by the
12
12
  [interactor][collective_idea_interactors] gem. Rich support for attributes, callbacks, and validations,
13
13
  and thread safe performance methods.
14
14
 
@@ -17,7 +17,7 @@ and thread safe performance methods.
17
17
  Add this line to your application's Gemfile:
18
18
 
19
19
  ```ruby
20
- gem 'activeinteractor'
20
+ gem 'activeinteractor', require: 'active_interactor'
21
21
  ```
22
22
 
23
23
  And then execute:
@@ -22,7 +22,10 @@ require 'active_interactor/version'
22
22
  # {Base interactor} needs to do its work. When an {Base interactor} does its single purpose, it affects its given
23
23
  # {Context::Base context}.
24
24
  #
25
- # @see https://github.com/aaronmallen/activeinteractor/wiki Usage
25
+ # @see https://medium.com/@aaronmallen/activeinteractor-8557c0dc78db Basic Usage
26
+ # @see https://github.com/aaronmallen/activeinteractor/wiki Advanced Usage
27
+ # @see https://github.com/aaronmallen/activeinteractor Source Code
28
+ # @see https://github.com/aaronmallen/activeinteractor/issues Issues
26
29
  #
27
30
  # ## License
28
31
  #
@@ -25,18 +25,24 @@ module ActiveInteractor
25
25
  # MyContext.attributes
26
26
  # #=> [:first_name, :last_name]
27
27
  #
28
+ # @example Set defaults for attributes on a {Base context} class
29
+ # class MyContext < ActiveInteractor::Context::Base
30
+ # attributes first_name: { default: -> { 'Aaron' } }, last_name: { default: -> { 'Allen' } }
31
+ # end
32
+ #
28
33
  # @return [Array<Symbol>] the defined attributes
29
34
  def attributes(*attributes)
30
- return __attributes if attributes.empty?
35
+ attributes.compact.uniq.each { |attr| attribute(attr) }
31
36
 
32
- @__attributes = __attributes.concat(attributes.map(&:to_sym)).compact.uniq.sort
37
+ attribute_names.sort.collect(&:to_sym)
33
38
  end
34
39
 
35
40
  private
36
41
 
37
- def __attributes
38
- @__attributes ||= []
42
+ def attribute?(attr_name)
43
+ attribute_types.key?(attr_name.to_s)
39
44
  end
45
+ alias has_attribute? attribute?
40
46
  end
41
47
 
42
48
  # Initialize a new instance of {Base}
@@ -48,6 +54,8 @@ module ActiveInteractor
48
54
  copy_flags!(context)
49
55
  copy_called!(context)
50
56
  super
57
+
58
+ merge_attribute_values(context)
51
59
  end
52
60
 
53
61
  # Get values defined on the instance of {Base context} whose keys are defined on the {Base context} class'
@@ -69,10 +77,19 @@ module ActiveInteractor
69
77
  #
70
78
  # @return [Hash{Symbol => *}] the defined attributes and values
71
79
  def attributes
72
- self.class.attributes.each_with_object({}) do |attribute, hash|
73
- hash[attribute] = self[attribute] if self[attribute]
74
- end
80
+ super.symbolize_keys
81
+ end
82
+
83
+ # Check if the {Base context} instance has an attribute
84
+ #
85
+ # @since 1.0.1
86
+ #
87
+ # @param attr_name [Symbol, String] the name of the attribute to check
88
+ # @return [Boolean] whether or not the {Base context} instance has the attribute
89
+ def attribute?(attr_name)
90
+ @attributes.key?(attr_name.to_s)
75
91
  end
92
+ alias has_attribute? attribute?
76
93
 
77
94
  # Merge an instance of {Base context} into the calling {Base context} instance
78
95
  #
@@ -90,13 +107,21 @@ module ActiveInteractor
90
107
  merge_errors!(context.errors) if context.respond_to?(:errors)
91
108
  copy_flags!(context)
92
109
  context.each_pair do |key, value|
93
- self[key] = value unless value.nil?
110
+ public_send("#{key}=", value) unless value.nil?
94
111
  end
95
112
  self
96
113
  end
97
114
 
98
115
  private
99
116
 
117
+ def merge_attribute_values(context)
118
+ return unless context
119
+
120
+ context.each_pair do |key, value|
121
+ public_send("#{key}=", value)
122
+ end
123
+ end
124
+
100
125
  def merge_errors!(errors)
101
126
  if errors.is_a? String
102
127
  self.errors.add(:context, errors)
@@ -7,6 +7,26 @@ module ActiveInteractor
7
7
  # @author Aaron Allen <hello@aaronmallen.me>
8
8
  # @since 0.1.0
9
9
  #
10
+ # @!method attribute(name, type=Type::Value.new, **options)
11
+ # @!scope class
12
+ # @since 1.0.1
13
+ #
14
+ # @example Setting default values on the {Base context} class
15
+ # class MyContext < ActiveInteractor::Context::Base
16
+ # attribute :first_name, default: -> { 'Aaron' }
17
+ # end
18
+ #
19
+ # MyContext.new
20
+ # #=> <#MyContext first_name='Aaron'>
21
+ #
22
+ # MyContext.new(first_name: 'Bob')
23
+ # #=> <#MyContext first_name='Bob'>
24
+ #
25
+ # @see
26
+ # https://api.rubyonrails.org/classes/ActiveModel/Attributes/ClassMethods.html#method-i-attribute
27
+ # ActiveModel::Attributes::ClassMethods#attribute
28
+ #
29
+ #
10
30
  # @!method attribute_method?(attribute)
11
31
  # @!scope class
12
32
  # @since 0.1.0
@@ -14,6 +34,20 @@ module ActiveInteractor
14
34
  # https://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-attribute_method-3F
15
35
  # ActiveModel::Validations::ClassMethods#attribute_method?
16
36
  #
37
+ # @!method attribute_missing(match, *args, &block)
38
+ # @!scope class
39
+ # @since 1.0.1
40
+ # @see
41
+ # https://api.rubyonrails.org/classes/ActiveModel/AttributeMethods.html#method-i-attribute_missing
42
+ # ActiveModel::AttributeMethods#attribute_missing
43
+ #
44
+ # @!method attribute_names
45
+ # @!scope class
46
+ # @since 1.0.1
47
+ # @see
48
+ # https://api.rubyonrails.org/classes/ActiveModel/Attributes/ClassMethods.html#method-i-attribute_names
49
+ # ActiveModel::Attributes::ClassMethods#attribute_names
50
+ #
17
51
  # @!method clear_validators!(attribute)
18
52
  # @!scope class
19
53
  # @since 0.1.0
@@ -21,6 +55,27 @@ module ActiveInteractor
21
55
  # https://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-clear_validators-21
22
56
  # ActiveModel::Validations::ClassMethods#clear_validators!
23
57
  #
58
+ # @!method method_missing(method, *args, &block)
59
+ # @scope class
60
+ # @since 1.0.1
61
+ # @see
62
+ # https://api.rubyonrails.org/classes/ActiveModel/AttributeMethods.html#method-i-method_missing
63
+ # ActiveModel::AttributeMethods#method_missing
64
+ #
65
+ # @!method respond_to?(method, include_private_methods = false)
66
+ # @scope class
67
+ # @since 1.0.1
68
+ # @see
69
+ # https://api.rubyonrails.org/classes/ActiveModel/AttributeMethods.html#method-i-respond_to-3F
70
+ # ActiveModel::AttributeMethods#respond_to?
71
+ #
72
+ # @!method respond_to_without_attributes?(method, include_private_methods = false)
73
+ # @scope class
74
+ # @since 1.0.1
75
+ # @see
76
+ # https://api.rubyonrails.org/classes/ActiveModel/AttributeMethods.html#method-i-respond_to_without_attributes-3F
77
+ # ActiveModel::AttributeMethods#respond_to_without_attributes?
78
+ #
24
79
  # @!method validate(*args, &block)
25
80
  # @!scope class
26
81
  # @since 0.1.0
@@ -140,6 +195,18 @@ module ActiveInteractor
140
195
  # https://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validators_on
141
196
  # ActiveModel::Validations::ClassMethods#validators_on
142
197
  #
198
+ # @!method attribute_missing(match, *args, &block)
199
+ # @since 1.0.1
200
+ # @see
201
+ # https://api.rubyonrails.org/classes/ActiveModel/AttributeMethods.html#method-i-attribute_missing
202
+ # ActiveModel::AttributeMethods#attribute_missing
203
+ #
204
+ # @!method attribute_names
205
+ # @since 1.0.1
206
+ # @see
207
+ # https://api.rubyonrails.org/classes/ActiveModel/Attributes/ClassMethods.html#method-i-attribute_names
208
+ # ActiveModel::Attributes::ClassMethods#attribute_names
209
+ #
143
210
  # @!method errors
144
211
  # @since 0.1.0
145
212
  # @see
@@ -152,6 +219,24 @@ module ActiveInteractor
152
219
  # https://api.rubyonrails.org/classes/ActiveModel/Validations.html#method-i-invalid-3F
153
220
  # ActiveModel::Validations#invalid?
154
221
  #
222
+ # @!method method_missing(method, *args, &block)
223
+ # @since 1.0.1
224
+ # @see
225
+ # https://api.rubyonrails.org/classes/ActiveModel/AttributeMethods.html#method-i-method_missing
226
+ # ActiveModel::AttributeMethods#method_missing
227
+ #
228
+ # @!method respond_to?(method, include_private_methods = false)
229
+ # @since 1.0.1
230
+ # @see
231
+ # https://api.rubyonrails.org/classes/ActiveModel/AttributeMethods.html#method-i-respond_to-3F
232
+ # ActiveModel::AttributeMethods#respond_to?
233
+ #
234
+ # @!method respond_to_without_attributes?(method, include_private_methods = false)
235
+ # @since 1.0.1
236
+ # @see
237
+ # https://api.rubyonrails.org/classes/ActiveModel/AttributeMethods.html#method-i-respond_to_without_attributes-3F
238
+ # ActiveModel::AttributeMethods#respond_to_without_attributes?
239
+ #
155
240
  # @!method valid?(context = nil)
156
241
  # @since 0.1.0
157
242
  # @see
@@ -238,6 +323,7 @@ module ActiveInteractor
238
323
  class Base < OpenStruct
239
324
  extend ActiveInteractor::Context::Attributes::ClassMethods
240
325
 
326
+ include ActiveModel::Attributes
241
327
  include ActiveModel::Validations
242
328
  include ActiveInteractor::Context::Attributes
243
329
  include ActiveInteractor::Context::Status
@@ -27,7 +27,43 @@ module ActiveInteractor
27
27
  #
28
28
  # MyInteractor.context_class.attributes
29
29
  # #=> [:first_name, :last_name]
30
- delegate :attributes, to: :context_class, prefix: :context
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'
@@ -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 :fail!, :rollback!, to: :context, prefix: true
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
@@ -3,5 +3,5 @@
3
3
  module ActiveInteractor
4
4
  # The ActiveInteractor version
5
5
  # @return [String] the ActiveInteractor version
6
- VERSION = '1.0.0'
6
+ VERSION = '1.0.1'
7
7
  end
@@ -3,34 +3,70 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  RSpec.describe ActiveInteractor::Context::Base do
6
- after(:each) { described_class.instance_variable_set('@__attributes', []) }
7
-
8
- describe '#attributes' do
6
+ describe '.attributes' do
9
7
  context 'when no arguments are passed' do
10
- subject { described_class.attributes }
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
- before { described_class.instance_variable_set('@__attributes', %i[foo]) }
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 { described_class.attributes(:foo, :bar) }
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 { described_class.instance_variable_set('@__attributes', %i[foo]) }
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 '.attributes' do
37
+ describe '#attribute?' do
38
+ subject { instance.attribute?(attribute) }
39
+
40
+ context 'with class attributes []' do
41
+ let(:instance) { build_context.new }
42
+ let(:attribute) { :foo }
43
+
44
+ it { is_expected.to eq false }
45
+ end
46
+
47
+ context 'with class attributes [:foo]' do
48
+ let!(:context_class) do
49
+ build_context do
50
+ attributes :foo
51
+ end
52
+ end
53
+ let(:instance) { context_class.new }
54
+
55
+ context 'checking attribute :foo' do
56
+ let(:attribute) { :foo }
57
+
58
+ it { is_expected.to eq true }
59
+ end
60
+
61
+ context 'checking attribute :bar' do
62
+ let(:attribute) { :bar }
63
+
64
+ it { is_expected.to eq false }
65
+ end
66
+ end
67
+ end
68
+
69
+ describe '#attributes' do
34
70
  subject { instance.attributes }
35
71
 
36
72
  context 'with class attributes []' do
@@ -43,13 +79,23 @@ RSpec.describe ActiveInteractor::Context::Base do
43
79
  end
44
80
 
45
81
  context 'with class attributes [:foo, :bar, :baz]' do
46
- before { described_class.attributes(:foo, :bar, :baz) }
82
+ before { build_context.attributes(:foo, :bar) }
83
+
84
+ context 'with an instance having attributes { :foo => "foo", :bar => "bar" }' do
85
+ let(:instance) { TestContext.new(foo: 'foo', bar: 'bar') }
86
+
87
+ it { is_expected.to be_a Hash }
88
+ it { is_expected.to eq(bar: 'bar', foo: 'foo') }
89
+ end
47
90
 
48
91
  context 'with an instance having attributes { :foo => "foo", :bar => "bar", :baz => "baz" }' do
49
- let(:instance) { described_class.new(foo: 'foo', bar: 'bar', baz: 'baz') }
92
+ let(:instance) { TestContext.new(foo: 'foo', bar: 'bar', baz: 'baz') }
50
93
 
51
94
  it { is_expected.to be_a Hash }
52
- it { is_expected.to eq(bar: 'bar', baz: 'baz', foo: 'foo') }
95
+ it { is_expected.to eq(bar: 'bar', foo: 'foo') }
96
+ it 'is expected to assign :baz' do
97
+ expect(instance.baz).to eq 'baz'
98
+ end
53
99
  end
54
100
  end
55
101
  end
@@ -103,4 +103,52 @@ RSpec.describe 'A basic interactor', type: :integration do
103
103
  end
104
104
  end
105
105
  end
106
+
107
+ context 'having default context attributes {:foo => "foo"}' do
108
+ let(:interactor_class) do
109
+ build_interactor do
110
+ context_attribute :foo, default: -> { 'foo' }
111
+ end
112
+ end
113
+
114
+ describe '.perform' do
115
+ subject { interactor_class.perform(context_attributes) }
116
+
117
+ context 'when no context is passed' do
118
+ let(:context_attributes) { {} }
119
+
120
+ it { is_expected.to have_attributes(foo: 'foo') }
121
+ end
122
+
123
+ context 'when context {:foo => "bar"} is passed' do
124
+ let(:context_attributes) { { foo: 'bar' } }
125
+
126
+ it { is_expected.to have_attributes(foo: 'bar') }
127
+ end
128
+ end
129
+ end
130
+
131
+ context 'having default context attributes {:foo => "foo", :bar => "bar"} using the #context_attributes method' do
132
+ let(:interactor_class) do
133
+ build_interactor do
134
+ context_attributes foo: { default: -> { 'foo' } }, bar: { default: -> { 'bar' } }
135
+ end
136
+
137
+ describe '.perform' do
138
+ subject { interactor_class.perform(context_attributes) }
139
+
140
+ context 'when no context is passed' do
141
+ let(:context_attributes) { {} }
142
+
143
+ it { is_expected.to have_attributes(foo: 'foo', bar: 'bar') }
144
+ end
145
+
146
+ context 'when context {:foo => "bar"} is passed' do
147
+ let(:context_attributes) { { foo: 'bar' } }
148
+
149
+ it { is_expected.to have_attributes(foo: 'bar', bar: 'bar') }
150
+ end
151
+ end
152
+ end
153
+ end
106
154
  end
@@ -94,4 +94,83 @@ RSpec.describe 'A basic organizer', type: :integration do
94
94
  end
95
95
  end
96
96
  end
97
+
98
+ # https://github.com/aaronmallen/activeinteractor/issues/151
99
+ context 'with an interactor class having a predefined context class with attributes [:foo]' do
100
+ let!(:test_context_class) do
101
+ build_context('TestInteractor1Context') do
102
+ attributes :foo
103
+ end
104
+ end
105
+
106
+ # rubocop:disable Metrics/AbcSize
107
+ let!(:test_interactor_1) do
108
+ build_interactor('TestInteractor1') do
109
+ def perform
110
+ context.has_foo_as_method = context.foo.present?
111
+ context.has_foo_as_element = context[:foo].present?
112
+ context.has_bar_as_method = context.bar.present?
113
+ context.has_bar_as_element = context[:bar].present?
114
+ end
115
+ end
116
+ end
117
+ # rubocop:enable Metrics/AbcSize
118
+
119
+ let(:interactor_class) do
120
+ build_organizer do
121
+ organize :test_interactor_1
122
+ end
123
+ end
124
+
125
+ context 'when passing a context argument { :foo => "foo", :bar => "bar" }' do
126
+ let(:context_attributes) { { foo: 'foo', bar: 'bar' } }
127
+
128
+ describe '.perform' do
129
+ subject(:result) { interactor_class.perform(context_attributes) }
130
+ it { is_expected.to have_attributes(foo: 'foo', bar: 'bar') }
131
+
132
+ it 'is expected to copy all attributes in the contexts to each interactor' do
133
+ expect(subject.has_foo_as_method).to be true
134
+ expect(subject.has_foo_as_element).to be true
135
+ expect(subject.has_bar_as_method).to be true
136
+ expect(subject.has_bar_as_element).to be true
137
+ end
138
+
139
+ describe '#attributes' do
140
+ subject { result.attributes }
141
+
142
+ it { is_expected.to be_a Hash }
143
+ it { is_expected.to be_empty }
144
+ end
145
+ end
146
+
147
+ context 'with attributes [:foo] on the organizer context class' do
148
+ let!(:interactor_class) do
149
+ build_organizer do
150
+ context_attributes :foo
151
+ organize :test_interactor_1
152
+ end
153
+ end
154
+
155
+ describe '.perform' do
156
+ subject(:result) { interactor_class.perform(context_attributes) }
157
+ it { is_expected.to have_attributes(foo: 'foo', bar: 'bar') }
158
+
159
+ it 'is expected to copy all attributes in the contexts to each interactor' do
160
+ expect(subject.has_foo_as_method).to be true
161
+ expect(subject.has_foo_as_element).to be true
162
+ expect(subject.has_bar_as_method).to be true
163
+ expect(subject.has_bar_as_element).to be true
164
+ end
165
+
166
+ describe '#attributes' do
167
+ subject { result.attributes }
168
+
169
+ it { is_expected.to be_a Hash }
170
+ it { is_expected.to eq(foo: 'foo') }
171
+ end
172
+ end
173
+ end
174
+ end
175
+ end
97
176
  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.0
4
+ version: 1.0.1
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-26 00:00:00.000000000 Z
11
+ date: 2020-01-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -93,7 +93,7 @@ dependencies:
93
93
  - !ruby/object:Gem::Version
94
94
  version: '3.9'
95
95
  description: |
96
- An implementation of the Command Pattern for Ruby with ActiveModel::Validations based on the interactors gem.
96
+ An implementation of the Command Pattern for Ruby with ActiveModel::Validations inspired by the interactor gem.
97
97
  Rich support for attributes, callbacks, and validations, and thread safe performance methods.
98
98
  email:
99
99
  - hello@aaronmallen.me
@@ -202,10 +202,10 @@ licenses:
202
202
  - MIT
203
203
  metadata:
204
204
  bug_tracker_uri: https://github.com/aaronmallen/activeinteractor/issues
205
- changelog_uri: https://github.com/aaronmallen/activeinteractor/blob/v1.0.0/CHANGELOG.md
206
- documentation_uri: https://www.rubydoc.info/gems/activeinteractor/1.0.0
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
207
207
  hompage_uri: https://github.com/aaronmallen/activeinteractor
208
- source_code_uri: https://github.com/aaronmallen/activeinteractor/tree/v1.0.0
208
+ source_code_uri: https://github.com/aaronmallen/activeinteractor/tree/v1.0.1
209
209
  wiki_uri: https://github.com/aaronmallen/activeinteractor/wiki
210
210
  post_install_message:
211
211
  rdoc_options: []