dry-transaction 0.12.0 → 0.13.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +337 -0
- data/LICENSE +20 -0
- data/README.md +16 -43
- data/dry-transaction.gemspec +41 -0
- data/lib/dry-transaction.rb +2 -0
- data/lib/dry/transaction.rb +2 -0
- data/lib/dry/transaction/builder.rb +6 -4
- data/lib/dry/transaction/callable.rb +22 -2
- data/lib/dry/transaction/dsl.rb +9 -7
- data/lib/dry/transaction/errors.rb +2 -0
- data/lib/dry/transaction/instance_methods.rb +24 -20
- data/lib/dry/transaction/operation.rb +5 -3
- data/lib/dry/transaction/operation_resolver.rb +4 -2
- data/lib/dry/transaction/result_matcher.rb +4 -2
- data/lib/dry/transaction/stack.rb +2 -0
- data/lib/dry/transaction/step.rb +37 -24
- data/lib/dry/transaction/step_adapter.rb +6 -4
- data/lib/dry/transaction/step_adapters.rb +9 -7
- data/lib/dry/transaction/step_adapters/around.rb +4 -2
- data/lib/dry/transaction/step_adapters/check.rb +2 -0
- data/lib/dry/transaction/step_adapters/map.rb +2 -0
- data/lib/dry/transaction/step_adapters/raw.rb +5 -3
- data/lib/dry/transaction/step_adapters/tee.rb +2 -0
- data/lib/dry/transaction/step_adapters/try.rb +3 -1
- data/lib/dry/transaction/step_failure.rb +12 -0
- data/lib/dry/transaction/version.rb +3 -1
- metadata +14 -110
- data/Gemfile +0 -15
- data/Gemfile.lock +0 -97
- data/LICENSE.md +0 -9
- data/Rakefile +0 -6
- data/spec/examples.txt +0 -85
- data/spec/integration/around_spec.rb +0 -81
- data/spec/integration/auto_injection_spec.rb +0 -32
- data/spec/integration/custom_step_adapters_spec.rb +0 -41
- data/spec/integration/operation_spec.rb +0 -30
- data/spec/integration/passing_step_arguments_spec.rb +0 -51
- data/spec/integration/publishing_step_events_spec.rb +0 -119
- data/spec/integration/transaction_spec.rb +0 -566
- data/spec/integration/transaction_without_steps_spec.rb +0 -101
- data/spec/spec_helper.rb +0 -116
- data/spec/support/container.rb +0 -10
- data/spec/support/database.rb +0 -12
- data/spec/support/db_transactions.rb +0 -45
- data/spec/support/result_mixin.rb +0 -3
- data/spec/support/test_module_constants.rb +0 -11
- data/spec/unit/step_adapters/around_spec.rb +0 -46
- data/spec/unit/step_adapters/check_spec.rb +0 -43
- data/spec/unit/step_adapters/map_spec.rb +0 -16
- data/spec/unit/step_adapters/raw_spec.rb +0 -36
- data/spec/unit/step_adapters/tee_spec.rb +0 -17
- data/spec/unit/step_adapters/try_spec.rb +0 -89
- data/spec/unit/step_spec.rb +0 -131
@@ -1,17 +0,0 @@
|
|
1
|
-
RSpec.describe Dry::Transaction::StepAdapters::Tee, :adapter do
|
2
|
-
|
3
|
-
subject { described_class.new }
|
4
|
-
|
5
|
-
let(:operation) {
|
6
|
-
-> (input) { input.upcase }
|
7
|
-
}
|
8
|
-
|
9
|
-
let(:options) { { step_name: "unit" } }
|
10
|
-
|
11
|
-
describe "#call" do
|
12
|
-
|
13
|
-
it "return a Success value" do
|
14
|
-
expect(subject.(operation, options, ["input"])).to eql(Success("input"))
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,89 +0,0 @@
|
|
1
|
-
RSpec.describe Dry::Transaction::StepAdapters::Try do
|
2
|
-
|
3
|
-
subject { described_class.new }
|
4
|
-
|
5
|
-
let(:operation) {
|
6
|
-
-> (input) {
|
7
|
-
raise(Test::NotValidError, 'not a string') unless input.is_a? String
|
8
|
-
input.upcase
|
9
|
-
}
|
10
|
-
}
|
11
|
-
|
12
|
-
let(:options) { { catch: Test::NotValidError, step_name: "unit" } }
|
13
|
-
|
14
|
-
before do
|
15
|
-
Test::NotValidError = Class.new(StandardError)
|
16
|
-
Test::BetterNamingError = Class.new(StandardError)
|
17
|
-
end
|
18
|
-
|
19
|
-
describe "#call" do
|
20
|
-
|
21
|
-
context "without the :catch option" do
|
22
|
-
let(:options) { { step_name: "unit" } }
|
23
|
-
|
24
|
-
it "raises an ArgumentError" do
|
25
|
-
expect {
|
26
|
-
subject.(operation, options, ["something"])
|
27
|
-
}.to raise_error(
|
28
|
-
Dry::Transaction::MissingCatchListError,
|
29
|
-
"step +unit+ requires one or more exception classes provided via +catch:+"
|
30
|
-
)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
context "with the :catch option" do
|
35
|
-
|
36
|
-
context "when the error was raised" do
|
37
|
-
|
38
|
-
it "returns a Failure value" do
|
39
|
-
expect(subject.(operation, options, [1234])).to be_a_failure
|
40
|
-
end
|
41
|
-
|
42
|
-
it "returns the raised error as output" do
|
43
|
-
result = subject.(operation, options, [1234])
|
44
|
-
expect(result.failure).to be_a Test::NotValidError
|
45
|
-
expect(result.failure.message).to eql("not a string")
|
46
|
-
end
|
47
|
-
|
48
|
-
context "when using the :raise option" do
|
49
|
-
let(:options) {
|
50
|
-
{
|
51
|
-
catch: Test::NotValidError,
|
52
|
-
raise: Test::BetterNamingError
|
53
|
-
}
|
54
|
-
}
|
55
|
-
|
56
|
-
it "returns a Failure value" do
|
57
|
-
expect(subject.(operation, options, [1234])).to be_a_failure
|
58
|
-
end
|
59
|
-
|
60
|
-
it "returns the error specified by :raise as output" do
|
61
|
-
result = subject.(operation, options, [1234])
|
62
|
-
expect(result.failure).to be_a Test::BetterNamingError
|
63
|
-
expect(result.failure.message).to eql("not a string")
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
context "when the error was NOT raised" do
|
69
|
-
|
70
|
-
it "returns a Success value" do
|
71
|
-
expect(subject.(operation, options, ["input"])).to eql(Success("INPUT"))
|
72
|
-
end
|
73
|
-
|
74
|
-
context "when using the :raise option" do
|
75
|
-
let(:options) {
|
76
|
-
{
|
77
|
-
catch: Test::NotValidError,
|
78
|
-
raise: Test::BetterNamingError
|
79
|
-
}
|
80
|
-
}
|
81
|
-
|
82
|
-
it "returns a Success value" do
|
83
|
-
expect(subject.(operation, options, ["input"])).to eql(Success("INPUT"))
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
data/spec/unit/step_spec.rb
DELETED
@@ -1,131 +0,0 @@
|
|
1
|
-
RSpec.describe Dry::Transaction::Step do
|
2
|
-
let(:step_adapter) { ->(step, input, *args) { step.operation.call(input, *args) } }
|
3
|
-
let(:step_name) { :test }
|
4
|
-
let(:operation_name) { step_name }
|
5
|
-
|
6
|
-
subject(:step) { described_class.new(step_adapter, step_name, operation_name, operation, {}) }
|
7
|
-
|
8
|
-
describe "#call" do
|
9
|
-
let(:listener) do
|
10
|
-
Class.new do
|
11
|
-
attr_reader :started, :success, :failed
|
12
|
-
|
13
|
-
def initialize
|
14
|
-
@started = []
|
15
|
-
@success = []
|
16
|
-
@failed = []
|
17
|
-
end
|
18
|
-
|
19
|
-
def on_step(event)
|
20
|
-
started << event[:step_name]
|
21
|
-
end
|
22
|
-
def on_step_succeeded(event)
|
23
|
-
success << "succeded_#{event[:step_name]}"
|
24
|
-
end
|
25
|
-
def on_step_failed(event)
|
26
|
-
failed << "failed_#{event[:step_name]}"
|
27
|
-
end
|
28
|
-
end.new
|
29
|
-
end
|
30
|
-
|
31
|
-
let(:input) { "input" }
|
32
|
-
subject { step.call(input) }
|
33
|
-
|
34
|
-
context "when operation succeeds" do
|
35
|
-
let(:operation) { proc { |input| Dry::Monads.Success(input) } }
|
36
|
-
|
37
|
-
it { is_expected.to be_success }
|
38
|
-
|
39
|
-
it "publishes step_succeeded" do
|
40
|
-
expect(listener).to receive(:on_step_succeeded).and_call_original
|
41
|
-
step.subscribe(listener)
|
42
|
-
subject
|
43
|
-
|
44
|
-
expect(listener.success).to eq ['succeded_test']
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
context "when operation starts" do
|
49
|
-
let(:operation) { proc { |input| Dry::Monads.Success(input) } }
|
50
|
-
|
51
|
-
it "publishes step" do
|
52
|
-
expect(listener).to receive(:on_step).and_call_original
|
53
|
-
step.subscribe(listener)
|
54
|
-
subject
|
55
|
-
|
56
|
-
expect(listener.started).to eq [:test]
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
context "when operation fails" do
|
61
|
-
let(:operation) { proc { |input| Dry::Monads.Failure("error") } }
|
62
|
-
|
63
|
-
it { is_expected.to be_failure }
|
64
|
-
|
65
|
-
it "wraps value in StepFailure" do
|
66
|
-
aggregate_failures do
|
67
|
-
expect(subject.failure).to be_a Dry::Transaction::StepFailure
|
68
|
-
expect(subject.failure.value).to eq "error"
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
it "publishes step_failed" do
|
73
|
-
expect(listener).to receive(:on_step_failed).and_call_original
|
74
|
-
step.subscribe(listener)
|
75
|
-
subject
|
76
|
-
|
77
|
-
expect(listener.failed).to eq ['failed_test']
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
describe "#with" do
|
83
|
-
let(:operation) { proc { |a, b| a + b } }
|
84
|
-
context "without arguments" do
|
85
|
-
it "returns itself" do
|
86
|
-
expect(step.with).to eq step
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
context "with operation argument" do
|
91
|
-
it "returns new instance with only operation changed" do
|
92
|
-
new_operation = proc { |a,b| a * b }
|
93
|
-
new_step = step.with(operation: new_operation)
|
94
|
-
expect(new_step).to_not eq step
|
95
|
-
expect(new_step.operation_name).to eq step.operation_name
|
96
|
-
expect(new_step.operation).to_not eq step.operation
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
context "with call_args argument" do
|
101
|
-
let(:call_args) { [12] }
|
102
|
-
it "returns new instance with only call_args changed" do
|
103
|
-
new_step = step.with(call_args: call_args)
|
104
|
-
expect(new_step).to_not eq step
|
105
|
-
expect(new_step.operation_name).to eq step.operation_name
|
106
|
-
expect(new_step.call_args).to_not eq step.call_args
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
describe "#arity" do
|
112
|
-
subject { step.arity }
|
113
|
-
|
114
|
-
context "when operation is a proc" do
|
115
|
-
let(:operation) { proc { |a, b| a + b } }
|
116
|
-
it { is_expected.to eq 2 }
|
117
|
-
end
|
118
|
-
|
119
|
-
context "when operation is an object with call method" do
|
120
|
-
let(:operation) do
|
121
|
-
Class.new do
|
122
|
-
def call(a, b, c)
|
123
|
-
a + b + c
|
124
|
-
end
|
125
|
-
end.new
|
126
|
-
end
|
127
|
-
|
128
|
-
it { is_expected.to eq 3 }
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|