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 +4 -4
- data/CHANGELOG.md +27 -1
- data/README.md +2 -2
- data/lib/active_interactor.rb +4 -1
- data/lib/active_interactor/context/attributes.rb +33 -8
- data/lib/active_interactor/context/base.rb +86 -0
- data/lib/active_interactor/interactor/context.rb +57 -2
- data/lib/active_interactor/version.rb +1 -1
- data/spec/active_interactor/context/base_spec.rb +57 -11
- data/spec/integration/a_basic_interactor_spec.rb +48 -0
- data/spec/integration/a_basic_organizer_spec.rb +79 -0
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 91b9f4936670919fb0f3f1bda4f9320a3abd439adef16b7bae4d8cf14d3fb6da
|
4
|
+
data.tar.gz: 725547555164c173ab870afafb3f8ee43b6e355c3fcab3732b5a457d66e4f468
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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
|
[](https://www.codacy.com/manual/aaronmallen/activeinteractor?utm_source=github.com&utm_medium=referral&utm_content=aaronmallen/activeinteractor&utm_campaign=Badge_Grade)
|
9
9
|
[](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]
|
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:
|
data/lib/active_interactor.rb
CHANGED
@@ -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://
|
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
|
-
|
35
|
+
attributes.compact.uniq.each { |attr| attribute(attr) }
|
31
36
|
|
32
|
-
|
37
|
+
attribute_names.sort.collect(&:to_sym)
|
33
38
|
end
|
34
39
|
|
35
40
|
private
|
36
41
|
|
37
|
-
def
|
38
|
-
|
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
|
-
|
73
|
-
|
74
|
-
|
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
|
-
|
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
|
-
|
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 :
|
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,34 +3,70 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
RSpec.describe ActiveInteractor::Context::Base do
|
6
|
-
|
7
|
-
|
8
|
-
describe '#attributes' do
|
6
|
+
describe '.attributes' do
|
9
7
|
context 'when no arguments are passed' do
|
10
|
-
subject {
|
8
|
+
subject { context_class.attributes }
|
9
|
+
let!(:context_class) { build_context }
|
11
10
|
it { is_expected.to eq [] }
|
12
11
|
|
13
12
|
context 'when an attribute :foo was previously defined' do
|
14
|
-
|
13
|
+
let!(:context_class) do
|
14
|
+
build_context do
|
15
|
+
attributes :foo
|
16
|
+
end
|
17
|
+
end
|
15
18
|
|
16
19
|
it { is_expected.to eq %i[foo] }
|
17
20
|
end
|
18
21
|
end
|
19
22
|
|
20
23
|
context 'when given arguments :foo and :bar' do
|
21
|
-
subject {
|
24
|
+
subject { context_class.attributes(:foo, :bar) }
|
25
|
+
let!(:context_class) { build_context }
|
22
26
|
|
23
27
|
it { is_expected.to eq %i[bar foo] }
|
24
28
|
|
25
29
|
context 'when an attribute :foo was previously defined' do
|
26
|
-
before {
|
30
|
+
before { TestContext.attributes(:foo) }
|
27
31
|
|
28
32
|
it { is_expected.to eq %i[bar foo] }
|
29
33
|
end
|
30
34
|
end
|
31
35
|
end
|
32
36
|
|
33
|
-
describe '
|
37
|
+
describe '#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 {
|
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) {
|
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',
|
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.
|
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-
|
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
|
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.
|
206
|
-
documentation_uri: https://www.rubydoc.info/gems/activeinteractor/1.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.
|
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: []
|