teckel 0.1.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +114 -0
  3. data/LICENSE_LOGO +4 -0
  4. data/README.md +22 -14
  5. data/lib/teckel.rb +11 -2
  6. data/lib/teckel/chain.rb +47 -152
  7. data/lib/teckel/chain/config.rb +246 -0
  8. data/lib/teckel/chain/result.rb +38 -0
  9. data/lib/teckel/chain/runner.rb +62 -0
  10. data/lib/teckel/chain/step.rb +18 -0
  11. data/lib/teckel/config.rb +41 -52
  12. data/lib/teckel/contracts.rb +19 -0
  13. data/lib/teckel/operation.rb +108 -253
  14. data/lib/teckel/operation/config.rb +396 -0
  15. data/lib/teckel/operation/result.rb +92 -0
  16. data/lib/teckel/operation/runner.rb +75 -0
  17. data/lib/teckel/result.rb +52 -53
  18. data/lib/teckel/version.rb +1 -1
  19. data/spec/chain/default_settings_spec.rb +39 -0
  20. data/spec/chain/inheritance_spec.rb +116 -0
  21. data/spec/chain/none_input_spec.rb +36 -0
  22. data/spec/chain/results_spec.rb +53 -0
  23. data/spec/chain_around_hook_spec.rb +100 -0
  24. data/spec/chain_spec.rb +180 -0
  25. data/spec/config_spec.rb +26 -0
  26. data/spec/doctest_helper.rb +7 -0
  27. data/spec/operation/contract_trace_spec.rb +116 -0
  28. data/spec/operation/default_settings_spec.rb +94 -0
  29. data/spec/operation/inheritance_spec.rb +94 -0
  30. data/spec/operation/result_spec.rb +34 -0
  31. data/spec/operation/results_spec.rb +117 -0
  32. data/spec/operation_spec.rb +483 -0
  33. data/spec/rb27/pattern_matching_spec.rb +193 -0
  34. data/spec/result_spec.rb +22 -0
  35. data/spec/spec_helper.rb +25 -0
  36. data/spec/support/dry_base.rb +8 -0
  37. data/spec/support/fake_db.rb +12 -0
  38. data/spec/support/fake_models.rb +20 -0
  39. data/spec/teckel_spec.rb +7 -0
  40. metadata +64 -46
  41. data/.github/workflows/ci.yml +0 -67
  42. data/.github/workflows/pages.yml +0 -50
  43. data/.gitignore +0 -13
  44. data/.rspec +0 -3
  45. data/.rubocop.yml +0 -12
  46. data/.ruby-version +0 -1
  47. data/DEVELOPMENT.md +0 -28
  48. data/Gemfile +0 -8
  49. data/Gemfile.lock +0 -71
  50. data/Rakefile +0 -30
  51. data/bin/console +0 -15
  52. data/bin/rake +0 -29
  53. data/bin/rspec +0 -29
  54. data/bin/rubocop +0 -18
  55. data/bin/setup +0 -8
  56. data/lib/teckel/operation/results.rb +0 -71
  57. 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
@@ -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
@@ -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,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry-types'
4
+ require 'dry-struct'
5
+
6
+ module Types
7
+ include Dry.Types()
8
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FakeDB
4
+ Rollback = Class.new(RuntimeError)
5
+
6
+ def self.transaction
7
+ yield
8
+ rescue Rollback
9
+ # doing rollback ...
10
+ raise
11
+ end
12
+ 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
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Teckel do
4
+ it "has a version number" do
5
+ expect(Teckel::VERSION).not_to be nil
6
+ end
7
+ end
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.1.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-01-02 00:00:00.000000000 Z
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/results.rb
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
- - teckel.gemspec
138
- homepage: https://github.com/dotless-de/teckel
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
- post_install_message:
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: '0'
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