teckel 0.1.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|