interaktor 0.5.1 → 0.6.0.pre
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/README.md +79 -69
- data/interaktor.gemspec +2 -2
- data/lib/interaktor/attributes.rb +24 -0
- data/lib/interaktor/callable.rb +42 -262
- data/lib/interaktor/error/attribute_error.rb +2 -2
- data/lib/interaktor/error/attribute_validation_error.rb +20 -0
- data/lib/interaktor/error/missing_explicit_success_error.rb +7 -2
- data/lib/interaktor/error/organizer_missing_passed_attribute_error.rb +7 -7
- data/lib/interaktor/error/organizer_success_attribute_missing_error.rb +4 -4
- data/lib/interaktor/error/unknown_attribute_error.rb +4 -4
- data/lib/interaktor/interaction.rb +83 -29
- data/lib/interaktor/organizer.rb +7 -35
- data/lib/interaktor.rb +2 -18
- data/spec/interaktor/hooks_spec.rb +357 -363
- data/spec/interaktor/organizer_spec.rb +57 -48
- data/spec/support/helpers.rb +13 -2
- data/spec/support/lint.rb +219 -271
- metadata +11 -11
- data/lib/interaktor/error/attribute_schema_validation_error.rb +0 -54
- data/spec/interaktor/context_spec.rb +0 -187
|
@@ -49,13 +49,13 @@ RSpec.describe Interaktor::Organizer do
|
|
|
49
49
|
describe "#call" do
|
|
50
50
|
it "calls each interaktor in order" do
|
|
51
51
|
organizer = FakeInteraktor.build_interaktor(type: described_class) do
|
|
52
|
-
input {
|
|
53
|
-
success {
|
|
52
|
+
input { attribute :foo }
|
|
53
|
+
success { attribute :baz }
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
interaktor1 = FakeInteraktor.build_interaktor("Interaktor1") do
|
|
57
|
-
input {
|
|
58
|
-
success {
|
|
57
|
+
input { attribute :foo }
|
|
58
|
+
success { attribute :bar }
|
|
59
59
|
|
|
60
60
|
def call
|
|
61
61
|
success!(bar: "whatever")
|
|
@@ -63,8 +63,8 @@ RSpec.describe Interaktor::Organizer do
|
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
interaktor2 = FakeInteraktor.build_interaktor("Interaktor2") do
|
|
66
|
-
input {
|
|
67
|
-
success {
|
|
66
|
+
input { attribute :bar }
|
|
67
|
+
success { attribute :baz }
|
|
68
68
|
|
|
69
69
|
def call
|
|
70
70
|
success!(baz: "whatever")
|
|
@@ -83,12 +83,12 @@ RSpec.describe Interaktor::Organizer do
|
|
|
83
83
|
|
|
84
84
|
it "allows an interaktor to accept input attributes from an organizer" do
|
|
85
85
|
organizer = FakeInteraktor.build_interaktor(type: described_class) do
|
|
86
|
-
input {
|
|
86
|
+
input { attribute :foo }
|
|
87
87
|
end
|
|
88
88
|
|
|
89
89
|
interaktor1 = FakeInteraktor.build_interaktor("Interaktor1") do
|
|
90
|
-
input {
|
|
91
|
-
success {
|
|
90
|
+
input { attribute :foo }
|
|
91
|
+
success { attribute :bar }
|
|
92
92
|
|
|
93
93
|
def call
|
|
94
94
|
success!(bar: "baz")
|
|
@@ -96,7 +96,7 @@ RSpec.describe Interaktor::Organizer do
|
|
|
96
96
|
end
|
|
97
97
|
|
|
98
98
|
interaktor2 = FakeInteraktor.build_interaktor("Interaktor2") do
|
|
99
|
-
input {
|
|
99
|
+
input { attribute :bar }
|
|
100
100
|
|
|
101
101
|
def call
|
|
102
102
|
end
|
|
@@ -111,11 +111,11 @@ RSpec.describe Interaktor::Organizer do
|
|
|
111
111
|
end
|
|
112
112
|
|
|
113
113
|
it "allows an interaktor to accept input attributes from the previous organized interaktor's input attributes" do
|
|
114
|
-
organizer = FakeInteraktor.build_interaktor(type: described_class) { input {
|
|
115
|
-
interaktor1 = FakeInteraktor.build_interaktor("Interaktor1") { input {
|
|
114
|
+
organizer = FakeInteraktor.build_interaktor(type: described_class) { input { attribute :foo } }
|
|
115
|
+
interaktor1 = FakeInteraktor.build_interaktor("Interaktor1") { input { attribute :foo } }
|
|
116
116
|
interaktor2 = FakeInteraktor.build_interaktor("Interaktor2") do
|
|
117
|
-
input {
|
|
118
|
-
success {
|
|
117
|
+
input { attribute :foo }
|
|
118
|
+
success { attribute :bar }
|
|
119
119
|
|
|
120
120
|
def call
|
|
121
121
|
success!(bar: foo)
|
|
@@ -131,11 +131,11 @@ RSpec.describe Interaktor::Organizer do
|
|
|
131
131
|
end
|
|
132
132
|
|
|
133
133
|
it "allows an interaktor to accept input attributes from the previous organized interaktor's success attributes" do
|
|
134
|
-
organizer = FakeInteraktor.build_interaktor(type: described_class) { input {
|
|
134
|
+
organizer = FakeInteraktor.build_interaktor(type: described_class) { input { attribute :foo } }
|
|
135
135
|
|
|
136
136
|
interaktor1 = FakeInteraktor.build_interaktor("Interaktor1") do
|
|
137
|
-
input {
|
|
138
|
-
success {
|
|
137
|
+
input { attribute :foo }
|
|
138
|
+
success { attribute :bar }
|
|
139
139
|
|
|
140
140
|
def call
|
|
141
141
|
success!(bar: foo)
|
|
@@ -143,8 +143,8 @@ RSpec.describe Interaktor::Organizer do
|
|
|
143
143
|
end
|
|
144
144
|
|
|
145
145
|
interaktor2 = FakeInteraktor.build_interaktor("Interaktor2") do
|
|
146
|
-
input {
|
|
147
|
-
success {
|
|
146
|
+
input { attribute :bar }
|
|
147
|
+
success { attribute :baz }
|
|
148
148
|
|
|
149
149
|
def call
|
|
150
150
|
success!(baz: bar)
|
|
@@ -159,59 +159,68 @@ RSpec.describe Interaktor::Organizer do
|
|
|
159
159
|
organizer.call(foo: "whatever")
|
|
160
160
|
end
|
|
161
161
|
|
|
162
|
-
it "raises an exception if an interaktor
|
|
162
|
+
it "raises an exception if an interaktor cannot receive input attribute from the organizer" do
|
|
163
163
|
organizer = FakeInteraktor.build_interaktor(type: described_class)
|
|
164
|
-
interaktor1 = FakeInteraktor.build_interaktor("Interaktor1")
|
|
164
|
+
interaktor1 = FakeInteraktor.build_interaktor("Interaktor1") do
|
|
165
|
+
input do
|
|
166
|
+
attribute :foo
|
|
167
|
+
validates :foo, presence: true
|
|
168
|
+
end
|
|
169
|
+
end
|
|
165
170
|
|
|
166
171
|
allow(organizer).to receive(:organized).and_return([interaktor1])
|
|
167
172
|
|
|
168
|
-
expect(interaktor1).not_to receive(:call!)
|
|
169
|
-
|
|
170
173
|
expect {
|
|
171
174
|
organizer.call
|
|
172
|
-
}.to raise_error
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
)
|
|
175
|
+
}.to raise_error do |error|
|
|
176
|
+
expect(error).to be_an Interaktor::Error::AttributeValidationError
|
|
177
|
+
expect(error.validation_errors).to eq(
|
|
178
|
+
foo: ["can't be blank"]
|
|
179
|
+
)
|
|
180
|
+
end
|
|
179
181
|
end
|
|
180
182
|
|
|
181
|
-
it "raises an exception if an interaktor
|
|
183
|
+
it "raises an exception if an interaktor cannot receive input attribute from the previous interaktor" do
|
|
182
184
|
organizer = FakeInteraktor.build_interaktor(type: described_class)
|
|
183
185
|
interaktor1 = FakeInteraktor.build_interaktor("Interaktor1")
|
|
184
|
-
interaktor2 = FakeInteraktor.build_interaktor("Interaktor2")
|
|
186
|
+
interaktor2 = FakeInteraktor.build_interaktor("Interaktor2") do
|
|
187
|
+
input do
|
|
188
|
+
attribute :foo
|
|
189
|
+
validates :foo, presence: true
|
|
190
|
+
end
|
|
191
|
+
end
|
|
185
192
|
|
|
186
193
|
allow(organizer).to receive(:organized).and_return([interaktor1, interaktor2])
|
|
187
194
|
|
|
188
|
-
expect(interaktor2).not_to receive(:call!)
|
|
189
|
-
|
|
190
195
|
expect {
|
|
191
196
|
organizer.call
|
|
192
|
-
}.to raise_error
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
)
|
|
197
|
+
}.to raise_error do |error|
|
|
198
|
+
expect(error).to be_an Interaktor::Error::AttributeValidationError
|
|
199
|
+
expect(error.validation_errors).to eq(
|
|
200
|
+
foo: ["can't be blank"]
|
|
201
|
+
)
|
|
202
|
+
end
|
|
199
203
|
end
|
|
200
204
|
|
|
201
205
|
it "raises an exception if the organizer's last interaktor does not include the organizer's success attributes" do
|
|
202
|
-
organizer = FakeInteraktor.build_interaktor(type: described_class)
|
|
206
|
+
organizer = FakeInteraktor.build_interaktor(type: described_class) do
|
|
207
|
+
success do
|
|
208
|
+
attribute :final
|
|
209
|
+
validates :final, presence: true
|
|
210
|
+
end
|
|
211
|
+
end
|
|
203
212
|
interaktor1 = FakeInteraktor.build_interaktor("Interaktor1")
|
|
204
213
|
|
|
205
214
|
allow(organizer).to receive(:organized).and_return([interaktor1])
|
|
206
215
|
|
|
207
|
-
expect(interaktor1).not_to receive(:call!)
|
|
208
|
-
|
|
209
216
|
expect {
|
|
210
217
|
organizer.call
|
|
211
|
-
}.to raise_error
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
218
|
+
}.to raise_error do |error|
|
|
219
|
+
expect(error).to be_an Interaktor::Error::AttributeValidationError
|
|
220
|
+
expect(error.validation_errors).to eq(
|
|
221
|
+
final: ["can't be blank"]
|
|
222
|
+
)
|
|
223
|
+
end
|
|
215
224
|
end
|
|
216
225
|
end
|
|
217
226
|
end
|
data/spec/support/helpers.rb
CHANGED
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
class FakeInteraktor
|
|
2
2
|
# @param name [String]
|
|
3
3
|
def self.build_interaktor(name = nil, type: Interaktor, &block)
|
|
4
|
-
|
|
4
|
+
singular_name = type.to_s.gsub("::", "")
|
|
5
|
+
name ||= "MyTest#{singular_name}"
|
|
6
|
+
|
|
7
|
+
# Attempt to delete the constant we're about to try to create, which might
|
|
8
|
+
# be the case due to previous tests creating an interaktor with the same
|
|
9
|
+
# class name.
|
|
10
|
+
begin
|
|
11
|
+
Object.send(:remove_const, name.to_sym)
|
|
12
|
+
rescue NameError
|
|
13
|
+
end
|
|
5
14
|
|
|
6
15
|
Class.new.include(type).tap do |klass|
|
|
7
|
-
klass.
|
|
16
|
+
klass.define_singleton_method(:name) { name.to_s }
|
|
8
17
|
klass.define_singleton_method(:inspect) { name.to_s }
|
|
9
18
|
klass.define_singleton_method(:to_s) { inspect }
|
|
19
|
+
klass.class_eval(&block) if block
|
|
20
|
+
Object.const_set(name, klass)
|
|
10
21
|
end
|
|
11
22
|
end
|
|
12
23
|
end
|