teckel 0.1.0 → 0.6.0
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 +114 -0
- data/LICENSE_LOGO +4 -0
- data/README.md +22 -14
- data/lib/teckel.rb +11 -2
- data/lib/teckel/chain.rb +47 -152
- data/lib/teckel/chain/config.rb +246 -0
- data/lib/teckel/chain/result.rb +38 -0
- data/lib/teckel/chain/runner.rb +62 -0
- data/lib/teckel/chain/step.rb +18 -0
- data/lib/teckel/config.rb +41 -52
- data/lib/teckel/contracts.rb +19 -0
- data/lib/teckel/operation.rb +108 -253
- data/lib/teckel/operation/config.rb +396 -0
- data/lib/teckel/operation/result.rb +92 -0
- data/lib/teckel/operation/runner.rb +75 -0
- data/lib/teckel/result.rb +52 -53
- data/lib/teckel/version.rb +1 -1
- data/spec/chain/default_settings_spec.rb +39 -0
- data/spec/chain/inheritance_spec.rb +116 -0
- data/spec/chain/none_input_spec.rb +36 -0
- data/spec/chain/results_spec.rb +53 -0
- data/spec/chain_around_hook_spec.rb +100 -0
- data/spec/chain_spec.rb +180 -0
- data/spec/config_spec.rb +26 -0
- data/spec/doctest_helper.rb +7 -0
- data/spec/operation/contract_trace_spec.rb +116 -0
- data/spec/operation/default_settings_spec.rb +94 -0
- data/spec/operation/inheritance_spec.rb +94 -0
- data/spec/operation/result_spec.rb +34 -0
- data/spec/operation/results_spec.rb +117 -0
- data/spec/operation_spec.rb +483 -0
- data/spec/rb27/pattern_matching_spec.rb +193 -0
- data/spec/result_spec.rb +22 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/support/dry_base.rb +8 -0
- data/spec/support/fake_db.rb +12 -0
- data/spec/support/fake_models.rb +20 -0
- data/spec/teckel_spec.rb +7 -0
- metadata +64 -46
- data/.github/workflows/ci.yml +0 -67
- data/.github/workflows/pages.yml +0 -50
- data/.gitignore +0 -13
- data/.rspec +0 -3
- data/.rubocop.yml +0 -12
- data/.ruby-version +0 -1
- data/DEVELOPMENT.md +0 -28
- data/Gemfile +0 -8
- data/Gemfile.lock +0 -71
- data/Rakefile +0 -30
- data/bin/console +0 -15
- data/bin/rake +0 -29
- data/bin/rspec +0 -29
- data/bin/rubocop +0 -18
- data/bin/setup +0 -8
- data/lib/teckel/operation/results.rb +0 -71
- data/teckel.gemspec +0 -33
@@ -0,0 +1,193 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
@warning = Warning[:experimental]
|
3
|
+
Warning[:experimental] = false
|
4
|
+
|
5
|
+
require 'support/dry_base'
|
6
|
+
require 'support/fake_models'
|
7
|
+
|
8
|
+
RSpec.describe "Ruby 2.7 pattern matches for Result and Chain" do
|
9
|
+
module TeckelChainPatternMatchingTest
|
10
|
+
class CreateUser
|
11
|
+
include ::Teckel::Operation
|
12
|
+
|
13
|
+
result!
|
14
|
+
|
15
|
+
input Types::Hash.schema(name: Types::String, age: Types::Coercible::Integer.optional)
|
16
|
+
output Types.Instance(User)
|
17
|
+
error Types::Hash.schema(message: Types::String, errors: Types::Array.of(Types::Hash))
|
18
|
+
|
19
|
+
def call(input)
|
20
|
+
user = User.new(name: input[:name], age: input[:age])
|
21
|
+
if user.save
|
22
|
+
success!(user)
|
23
|
+
else
|
24
|
+
fail!(message: "Could not save User", errors: user.errors)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class LogUser
|
30
|
+
include ::Teckel::Operation
|
31
|
+
|
32
|
+
result!
|
33
|
+
|
34
|
+
input Types.Instance(User)
|
35
|
+
error none
|
36
|
+
output input
|
37
|
+
|
38
|
+
def call(usr)
|
39
|
+
Logger.new(File::NULL).info("User #{usr.name} created")
|
40
|
+
success! usr
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class AddFriend
|
45
|
+
include ::Teckel::Operation
|
46
|
+
|
47
|
+
result!
|
48
|
+
|
49
|
+
settings Struct.new(:fail_befriend)
|
50
|
+
|
51
|
+
input Types.Instance(User)
|
52
|
+
output Types::Hash.schema(user: Types.Instance(User), friend: Types.Instance(User))
|
53
|
+
error Types::Hash.schema(message: Types::String)
|
54
|
+
|
55
|
+
def call(user)
|
56
|
+
if settings&.fail_befriend
|
57
|
+
fail!(message: "Did not find a friend.")
|
58
|
+
else
|
59
|
+
success!(user: user, friend: User.new(name: "A friend", age: 42))
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class Chain
|
65
|
+
include Teckel::Chain
|
66
|
+
|
67
|
+
step :create, CreateUser
|
68
|
+
step :log, LogUser
|
69
|
+
step :befriend, AddFriend
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "Operation Result" do
|
74
|
+
context "success" do
|
75
|
+
specify "pattern matching with keys" do
|
76
|
+
x =
|
77
|
+
case TeckelChainPatternMatchingTest::AddFriend.call(User.new(name: "bob", age: 23))
|
78
|
+
in { success: false, value: value }
|
79
|
+
["Failed", value]
|
80
|
+
in { success: true, value: value }
|
81
|
+
["Success result", value]
|
82
|
+
else
|
83
|
+
raise "Unexpected Result"
|
84
|
+
end
|
85
|
+
|
86
|
+
expect(x).to contain_exactly("Success result", hash_including(:friend, :user))
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context "failure" do
|
91
|
+
specify "pattern matching with keys" do
|
92
|
+
result =
|
93
|
+
TeckelChainPatternMatchingTest::AddFriend.
|
94
|
+
with(befriend: :fail).
|
95
|
+
call(User.new(name: "bob", age: 23))
|
96
|
+
|
97
|
+
x =
|
98
|
+
case result
|
99
|
+
in { success: false, value: value }
|
100
|
+
["Failed", value]
|
101
|
+
in { success: true, value: value }
|
102
|
+
["Success result", value]
|
103
|
+
else
|
104
|
+
raise "Unexpected Result"
|
105
|
+
end
|
106
|
+
|
107
|
+
expect(x).to contain_exactly("Failed", hash_including(:message))
|
108
|
+
end
|
109
|
+
|
110
|
+
specify "pattern matching array" do
|
111
|
+
result =
|
112
|
+
TeckelChainPatternMatchingTest::AddFriend.
|
113
|
+
with(befriend: :fail).
|
114
|
+
call(User.new(name: "bob", age: 23))
|
115
|
+
|
116
|
+
x =
|
117
|
+
case result
|
118
|
+
in [false, value]
|
119
|
+
["Failed", value]
|
120
|
+
in [true, value]
|
121
|
+
["Success result", value]
|
122
|
+
else
|
123
|
+
raise "Unexpected Result"
|
124
|
+
end
|
125
|
+
expect(x).to contain_exactly("Failed", hash_including(:message))
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe "Chain" do
|
131
|
+
context "success" do
|
132
|
+
specify "pattern matching with keys" do
|
133
|
+
x =
|
134
|
+
case TeckelChainPatternMatchingTest::Chain.call(name: "Bob", age: 23)
|
135
|
+
in { success: false, step: :befriend, value: value }
|
136
|
+
["Failed", value]
|
137
|
+
in { success: true, value: value }
|
138
|
+
["Success result", value]
|
139
|
+
else
|
140
|
+
raise "Unexpected Result"
|
141
|
+
end
|
142
|
+
expect(x).to contain_exactly("Success result", hash_including(:friend, :user))
|
143
|
+
end
|
144
|
+
|
145
|
+
specify "pattern matching array" do
|
146
|
+
x =
|
147
|
+
case TeckelChainPatternMatchingTest::Chain.call(name: "Bob", age: 23)
|
148
|
+
in [false, :befriend, value]
|
149
|
+
"Failed in befriend with #{value}"
|
150
|
+
in [true, _, value]
|
151
|
+
"Success result"
|
152
|
+
end
|
153
|
+
expect(x).to eq("Success result")
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
context "failure" do
|
158
|
+
specify "pattern matching with keys" do
|
159
|
+
result =
|
160
|
+
TeckelChainPatternMatchingTest::Chain.
|
161
|
+
with(befriend: :fail).
|
162
|
+
call(name: "bob", age: 23)
|
163
|
+
|
164
|
+
x =
|
165
|
+
case result
|
166
|
+
in { success: false, step: :befriend, value: value }
|
167
|
+
"Failed in befriend with #{value}"
|
168
|
+
in { success: true, value: value }
|
169
|
+
"Success result"
|
170
|
+
end
|
171
|
+
expect(x).to eq("Failed in befriend with #{ {message: "Did not find a friend."} }")
|
172
|
+
end
|
173
|
+
|
174
|
+
specify "pattern matching array" do
|
175
|
+
result =
|
176
|
+
TeckelChainPatternMatchingTest::Chain.
|
177
|
+
with(befriend: :fail).
|
178
|
+
call(name: "Bob", age: 23)
|
179
|
+
|
180
|
+
x =
|
181
|
+
case result
|
182
|
+
in [false, :befriend, value]
|
183
|
+
"Failed in befriend with #{value}"
|
184
|
+
in [true, value]
|
185
|
+
"Success result"
|
186
|
+
end
|
187
|
+
expect(x).to eq("Failed in befriend with #{ {message: "Did not find a friend."} }")
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
Warning[:experimental] = @warning
|
data/spec/result_spec.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'support/dry_base'
|
4
|
+
require 'support/fake_models'
|
5
|
+
|
6
|
+
module TeckelResultTest
|
7
|
+
class MissingResultImplementation
|
8
|
+
include Teckel::Result
|
9
|
+
def initialize(value, success); end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
RSpec.describe Teckel::Result do
|
14
|
+
describe "missing initialize" do
|
15
|
+
specify do
|
16
|
+
result = TeckelResultTest::MissingResultImplementation["value", true]
|
17
|
+
expect { result.successful? }.to raise_error(NotImplementedError)
|
18
|
+
expect { result.failure? }.to raise_error(NotImplementedError)
|
19
|
+
expect { result.value }.to raise_error(NotImplementedError)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
if ENV['COVERAGE'] == 'true'
|
5
|
+
require 'simplecov'
|
6
|
+
SimpleCov.start do
|
7
|
+
add_filter %r{^/spec/}
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
require "teckel"
|
12
|
+
|
13
|
+
RSpec.configure do |config|
|
14
|
+
# Enable flags like --only-failures and --next-failure
|
15
|
+
config.example_status_persistence_file_path = ".rspec_status"
|
16
|
+
|
17
|
+
# Disable RSpec exposing methods globally on `Module` and `main`
|
18
|
+
config.disable_monkey_patching!
|
19
|
+
|
20
|
+
config.formatter = config.files_to_run.size > 1 ? :progress : :documentation
|
21
|
+
|
22
|
+
config.expect_with :rspec do |c|
|
23
|
+
c.syntax = :expect
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class User
|
4
|
+
def initialize(name:, age:)
|
5
|
+
@name, @age = name, age
|
6
|
+
end
|
7
|
+
attr_reader :name, :age
|
8
|
+
|
9
|
+
def save
|
10
|
+
!underage?
|
11
|
+
end
|
12
|
+
|
13
|
+
def errors
|
14
|
+
underage? ? [{ age: "underage" }] : nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def underage?
|
18
|
+
@age <= 18
|
19
|
+
end
|
20
|
+
end
|
data/spec/teckel_spec.rb
ADDED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: teckel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Schulze
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-11-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -24,26 +24,6 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '2.0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: dry-struct
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: 1.1.1
|
34
|
-
- - "<"
|
35
|
-
- !ruby/object:Gem::Version
|
36
|
-
version: '2'
|
37
|
-
type: :development
|
38
|
-
prerelease: false
|
39
|
-
version_requirements: !ruby/object:Gem::Requirement
|
40
|
-
requirements:
|
41
|
-
- - ">="
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
version: 1.1.1
|
44
|
-
- - "<"
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
version: '2'
|
47
27
|
- !ruby/object:Gem::Dependency
|
48
28
|
name: rake
|
49
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,38 +88,55 @@ executables: []
|
|
108
88
|
extensions: []
|
109
89
|
extra_rdoc_files: []
|
110
90
|
files:
|
111
|
-
- ".github/workflows/ci.yml"
|
112
|
-
- ".github/workflows/pages.yml"
|
113
|
-
- ".gitignore"
|
114
|
-
- ".rspec"
|
115
|
-
- ".rubocop.yml"
|
116
|
-
- ".ruby-version"
|
117
91
|
- ".yardopts"
|
118
92
|
- CHANGELOG.md
|
119
|
-
- DEVELOPMENT.md
|
120
|
-
- Gemfile
|
121
|
-
- Gemfile.lock
|
122
93
|
- LICENSE
|
94
|
+
- LICENSE_LOGO
|
123
95
|
- README.md
|
124
|
-
- Rakefile
|
125
|
-
- bin/console
|
126
|
-
- bin/rake
|
127
|
-
- bin/rspec
|
128
|
-
- bin/rubocop
|
129
|
-
- bin/setup
|
130
96
|
- lib/teckel.rb
|
131
97
|
- lib/teckel/chain.rb
|
98
|
+
- lib/teckel/chain/config.rb
|
99
|
+
- lib/teckel/chain/result.rb
|
100
|
+
- lib/teckel/chain/runner.rb
|
101
|
+
- lib/teckel/chain/step.rb
|
132
102
|
- lib/teckel/config.rb
|
103
|
+
- lib/teckel/contracts.rb
|
133
104
|
- lib/teckel/operation.rb
|
134
|
-
- lib/teckel/operation/
|
105
|
+
- lib/teckel/operation/config.rb
|
106
|
+
- lib/teckel/operation/result.rb
|
107
|
+
- lib/teckel/operation/runner.rb
|
135
108
|
- lib/teckel/result.rb
|
136
109
|
- lib/teckel/version.rb
|
137
|
-
-
|
138
|
-
|
110
|
+
- spec/chain/default_settings_spec.rb
|
111
|
+
- spec/chain/inheritance_spec.rb
|
112
|
+
- spec/chain/none_input_spec.rb
|
113
|
+
- spec/chain/results_spec.rb
|
114
|
+
- spec/chain_around_hook_spec.rb
|
115
|
+
- spec/chain_spec.rb
|
116
|
+
- spec/config_spec.rb
|
117
|
+
- spec/doctest_helper.rb
|
118
|
+
- spec/operation/contract_trace_spec.rb
|
119
|
+
- spec/operation/default_settings_spec.rb
|
120
|
+
- spec/operation/inheritance_spec.rb
|
121
|
+
- spec/operation/result_spec.rb
|
122
|
+
- spec/operation/results_spec.rb
|
123
|
+
- spec/operation_spec.rb
|
124
|
+
- spec/rb27/pattern_matching_spec.rb
|
125
|
+
- spec/result_spec.rb
|
126
|
+
- spec/spec_helper.rb
|
127
|
+
- spec/support/dry_base.rb
|
128
|
+
- spec/support/fake_db.rb
|
129
|
+
- spec/support/fake_models.rb
|
130
|
+
- spec/teckel_spec.rb
|
131
|
+
homepage: https://github.com/fnordfish/teckel
|
139
132
|
licenses:
|
140
133
|
- Apache-2.0
|
141
|
-
metadata:
|
142
|
-
|
134
|
+
metadata:
|
135
|
+
changelog_uri: https://github.com/github.com/fnordfish/blob/master/CHANGELOG.md
|
136
|
+
source_code_uri: https://github.com/github.com/fnordfish
|
137
|
+
bug_tracker_uri: https://github.com/github.com/fnordfish/issues
|
138
|
+
documentation_uri: https://www.rubydoc.info/gems/teckel/0.6.0
|
139
|
+
post_install_message:
|
143
140
|
rdoc_options: []
|
144
141
|
require_paths:
|
145
142
|
- lib
|
@@ -147,7 +144,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
147
144
|
requirements:
|
148
145
|
- - ">="
|
149
146
|
- !ruby/object:Gem::Version
|
150
|
-
version:
|
147
|
+
version: 2.4.0
|
151
148
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
152
149
|
requirements:
|
153
150
|
- - ">="
|
@@ -155,7 +152,28 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
155
152
|
version: '0'
|
156
153
|
requirements: []
|
157
154
|
rubygems_version: 3.0.3
|
158
|
-
signing_key:
|
155
|
+
signing_key:
|
159
156
|
specification_version: 4
|
160
157
|
summary: Operations with enforced in/out/err data structures
|
161
|
-
test_files:
|
158
|
+
test_files:
|
159
|
+
- spec/chain/default_settings_spec.rb
|
160
|
+
- spec/chain/inheritance_spec.rb
|
161
|
+
- spec/chain/none_input_spec.rb
|
162
|
+
- spec/chain/results_spec.rb
|
163
|
+
- spec/chain_around_hook_spec.rb
|
164
|
+
- spec/chain_spec.rb
|
165
|
+
- spec/config_spec.rb
|
166
|
+
- spec/doctest_helper.rb
|
167
|
+
- spec/operation/contract_trace_spec.rb
|
168
|
+
- spec/operation/default_settings_spec.rb
|
169
|
+
- spec/operation/inheritance_spec.rb
|
170
|
+
- spec/operation/result_spec.rb
|
171
|
+
- spec/operation/results_spec.rb
|
172
|
+
- spec/operation_spec.rb
|
173
|
+
- spec/rb27/pattern_matching_spec.rb
|
174
|
+
- spec/result_spec.rb
|
175
|
+
- spec/spec_helper.rb
|
176
|
+
- spec/support/dry_base.rb
|
177
|
+
- spec/support/fake_db.rb
|
178
|
+
- spec/support/fake_models.rb
|
179
|
+
- spec/teckel_spec.rb
|