teckel 0.8.0 → 0.9.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.
@@ -51,13 +51,13 @@ module Teckel
51
51
  end
52
52
 
53
53
  # @!attribute [r] value
54
- # @return [Mixed] the value/payload
54
+ # @return [Object] the value/payload
55
55
  attr_reader :value
56
56
 
57
57
  # Get the error/failure value
58
- # @yield [Mixed] If a block is given and this is not a failure result, the value is yielded to the block
59
- # @param default [Mixed] return this default value if it's not a failure result
60
- # @return [Mixed] the value/payload
58
+ # @yield [Object] If a block is given and this is not a failure result, the value is yielded to the block
59
+ # @param default [Object] return this default value if it's not a failure result
60
+ # @return [Object] the value/payload
61
61
  def failure(default = nil, &block)
62
62
  return value unless @successful
63
63
  return yield(value) if block
@@ -66,9 +66,9 @@ module Teckel
66
66
  end
67
67
 
68
68
  # Get the success value
69
- # @yield [Mixed] If a block is given and this is not a success result, the value is yielded to the block
70
- # @param default [Mixed] return this default value if it's not a success result
71
- # @return [Mixed] the value/payload
69
+ # @yield [Object] If a block is given and this is not a success result, the value is yielded to the block
70
+ # @param default [Object] return this default value if it's not a success result
71
+ # @return [Object] the value/payload
72
72
  def success(default = nil, &block)
73
73
  return value if @successful
74
74
  return yield(value) if block
@@ -85,7 +85,7 @@ module Teckel
85
85
  value
86
86
  end
87
87
 
88
- alias :new :[]
88
+ alias_method :new, :[]
89
89
  end
90
90
  end
91
91
  end
@@ -8,7 +8,7 @@ module Teckel
8
8
  # @!visibility protected
9
9
  class Runner
10
10
  # @!visibility private
11
- UNDEFINED = Object.new.freeze
11
+ UNDEFINED = Teckel::UNDEFINED
12
12
 
13
13
  def initialize(operation, settings = UNDEFINED)
14
14
  @operation, @settings = operation, settings
@@ -59,11 +59,11 @@ module Teckel
59
59
  module Operation
60
60
  module ClassMethods
61
61
  # @!visibility private
62
- UNDEFINED = Object.new
62
+ UNDEFINED = Teckel::UNDEFINED
63
63
 
64
64
  # Invoke the Operation
65
65
  #
66
- # @param input Any form of input your {Teckel::Operation::Config#input input} class can handle via the given
66
+ # @param input [Object,nil] Any form of input your {Teckel::Operation::Config#input input} class can handle via the given
67
67
  # {Teckel::Operation::Config#input_constructor input_constructor}
68
68
  # @return Either An instance of your defined {Teckel::Operation::Config#error error} class or
69
69
  # {Teckel::Operation::Config#output output} class
@@ -111,7 +111,7 @@ module Teckel
111
111
  def with(settings)
112
112
  runable(settings_constructor.call(settings))
113
113
  end
114
- alias :set :with
114
+ alias_method :set, :with
115
115
 
116
116
  # Constructs a Runner instance for {call} and {with}.
117
117
  #
@@ -205,8 +205,8 @@ module Teckel
205
205
 
206
206
  def self.included(receiver)
207
207
  receiver.class_eval do
208
- extend Config
209
- extend ClassMethods
208
+ extend Config
209
+ extend ClassMethods
210
210
  include InstanceMethods
211
211
  end
212
212
  end
data/lib/teckel/result.rb CHANGED
@@ -37,7 +37,7 @@ module Teckel
37
37
  end
38
38
 
39
39
  # @!attribute [r] value
40
- # @return [Mixed] the value/payload
40
+ # @return [Object] the value/payload
41
41
  def value
42
42
  raise NotImplementedError, "Result object does not implement `value`"
43
43
  end
@@ -56,7 +56,7 @@ module Teckel
56
56
 
57
57
  def self.included(receiver)
58
58
  receiver.class_eval do
59
- extend ClassMethods
59
+ extend ClassMethods
60
60
  include InstanceMethods
61
61
  end
62
62
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Teckel
4
- VERSION = "0.8.0"
4
+ # @return [String]
5
+ VERSION = "0.9.0"
5
6
  end
data/lib/teckel.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "teckel/version"
3
+ require_relative "teckel/version"
4
4
 
5
5
  module Teckel
6
6
  # Base error class for this lib
@@ -13,6 +13,9 @@ module Teckel
13
13
  class MissingConfigError < Teckel::Error; end
14
14
 
15
15
  DEFAULT_CONSTRUCTOR = :[]
16
+
17
+ # @!visibility private
18
+ UNDEFINED = Object.new.freeze
16
19
  end
17
20
 
18
21
  require_relative "teckel/config"
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: teckel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Schulze
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2021-09-28 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: bundler
@@ -66,6 +65,20 @@ dependencies:
66
65
  - - ">="
67
66
  - !ruby/object:Gem::Version
68
67
  version: '0'
68
+ - !ruby/object:Gem::Dependency
69
+ name: standard
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
69
82
  - !ruby/object:Gem::Dependency
70
83
  name: yard
71
84
  requirement: !ruby/object:Gem::Requirement
@@ -121,29 +134,6 @@ files:
121
134
  - lib/teckel/operation/runner.rb
122
135
  - lib/teckel/result.rb
123
136
  - lib/teckel/version.rb
124
- - spec/chain/around_hook_spec.rb
125
- - spec/chain/default_settings_spec.rb
126
- - spec/chain/inheritance_spec.rb
127
- - spec/chain/none_input_spec.rb
128
- - spec/chain/results_spec.rb
129
- - spec/chain_spec.rb
130
- - spec/config_spec.rb
131
- - spec/doctest_helper.rb
132
- - spec/operation/config_spec.rb
133
- - spec/operation/contract_trace_spec.rb
134
- - spec/operation/default_settings_spec.rb
135
- - spec/operation/fail_on_input_spec.rb
136
- - spec/operation/inheritance_spec.rb
137
- - spec/operation/result_spec.rb
138
- - spec/operation/results_spec.rb
139
- - spec/operation_spec.rb
140
- - spec/rb27/pattern_matching_spec.rb
141
- - spec/result_spec.rb
142
- - spec/spec_helper.rb
143
- - spec/support/dry_base.rb
144
- - spec/support/fake_db.rb
145
- - spec/support/fake_models.rb
146
- - spec/teckel_spec.rb
147
137
  homepage: https://github.com/fnordfish/teckel
148
138
  licenses:
149
139
  - Apache-2.0
@@ -151,9 +141,8 @@ metadata:
151
141
  changelog_uri: https://github.com/fnordfish/teckel/blob/main/CHANGELOG.md
152
142
  source_code_uri: https://github.com/fnordfish/teckel
153
143
  bug_tracker_uri: https://github.com/fnordfish/teckel/issues
154
- documentation_uri: https://www.rubydoc.info/gems/teckel/0.8.0
144
+ documentation_uri: https://www.rubydoc.info/gems/teckel/0.9.0
155
145
  user_docs_uri: https://fnordfish.github.io/teckel/
156
- post_install_message:
157
146
  rdoc_options: []
158
147
  require_paths:
159
148
  - lib
@@ -168,31 +157,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
168
157
  - !ruby/object:Gem::Version
169
158
  version: '0'
170
159
  requirements: []
171
- rubygems_version: 3.2.15
172
- signing_key:
160
+ rubygems_version: 3.6.9
173
161
  specification_version: 4
174
162
  summary: Operations with enforced in/out/err data structures
175
- test_files:
176
- - spec/chain/around_hook_spec.rb
177
- - spec/chain/default_settings_spec.rb
178
- - spec/chain/inheritance_spec.rb
179
- - spec/chain/none_input_spec.rb
180
- - spec/chain/results_spec.rb
181
- - spec/chain_spec.rb
182
- - spec/config_spec.rb
183
- - spec/doctest_helper.rb
184
- - spec/operation/config_spec.rb
185
- - spec/operation/contract_trace_spec.rb
186
- - spec/operation/default_settings_spec.rb
187
- - spec/operation/fail_on_input_spec.rb
188
- - spec/operation/inheritance_spec.rb
189
- - spec/operation/result_spec.rb
190
- - spec/operation/results_spec.rb
191
- - spec/operation_spec.rb
192
- - spec/rb27/pattern_matching_spec.rb
193
- - spec/result_spec.rb
194
- - spec/spec_helper.rb
195
- - spec/support/dry_base.rb
196
- - spec/support/fake_db.rb
197
- - spec/support/fake_models.rb
198
- - spec/teckel_spec.rb
163
+ test_files: []
@@ -1,100 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'support/dry_base'
4
- require 'support/fake_db'
5
- require 'support/fake_models'
6
-
7
- module TeckelChainAroundHookTest
8
- class CreateUser
9
- include ::Teckel::Operation
10
-
11
- result!
12
-
13
- input Types::Hash.schema(name: Types::String, age: Types::Coercible::Integer.optional)
14
- output Types.Instance(User)
15
- error Types::Hash.schema(message: Types::String, errors: Types::Array.of(Types::Hash))
16
-
17
- def call(input)
18
- user = User.new(name: input[:name], age: input[:age])
19
- if user.save
20
- success!(user)
21
- else
22
- fail!(message: "Could not safe User", errors: user.errors)
23
- end
24
- end
25
- end
26
-
27
- class AddFriend
28
- include ::Teckel::Operation
29
-
30
- result!
31
-
32
- settings Struct.new(:fail_befriend)
33
-
34
- input Types.Instance(User)
35
- output Types::Hash.schema(user: Types.Instance(User), friend: Types.Instance(User))
36
- error Types::Hash.schema(message: Types::String)
37
-
38
- def call(user)
39
- if settings&.fail_befriend
40
- fail!(message: "Did not find a friend.")
41
- else
42
- success! user: user, friend: User.new(name: "A friend", age: 42)
43
- end
44
- end
45
- end
46
-
47
- @stack = []
48
- def self.stack
49
- @stack
50
- end
51
-
52
- class Chain
53
- include Teckel::Chain
54
-
55
- around ->(chain, input) {
56
- result = nil
57
- begin
58
- TeckelChainAroundHookTest.stack << :before
59
-
60
- FakeDB.transaction do
61
- result = chain.call(input)
62
- raise FakeDB::Rollback if result.failure?
63
- end
64
-
65
- TeckelChainAroundHookTest.stack << :after
66
- result
67
- rescue FakeDB::Rollback
68
- result
69
- end
70
- }
71
-
72
- step :create, CreateUser
73
- step :befriend, AddFriend
74
- end
75
- end
76
-
77
- RSpec.describe Teckel::Chain do
78
- before { TeckelChainAroundHookTest.stack.clear }
79
-
80
- context "success" do
81
- it "result matches" do
82
- result = TeckelChainAroundHookTest::Chain.call(name: "Bob", age: 23)
83
- expect(result.success).to include(user: kind_of(User), friend: kind_of(User))
84
- end
85
-
86
- it "runs around hook" do
87
- TeckelChainAroundHookTest::Chain.call(name: "Bob", age: 23)
88
- expect(TeckelChainAroundHookTest.stack).to eq([:before, :after])
89
- end
90
- end
91
-
92
- context "failure" do
93
- it "runs around hook" do
94
- TeckelChainAroundHookTest::Chain.
95
- with(befriend: :fail).
96
- call(name: "Bob", age: 23)
97
- expect(TeckelChainAroundHookTest.stack).to eq([:before])
98
- end
99
- end
100
- end
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module TeckelChainDefaultSettingsTest
4
- class MyOperation
5
- include Teckel::Operation
6
- result!
7
-
8
- settings Struct.new(:say, :other)
9
- settings_constructor ->(data) { settings.new(*data.values_at(*settings.members)) } # ruby 2.4 way for `keyword_init: true`
10
-
11
- input none
12
- output Hash
13
- error none
14
-
15
- def call(_)
16
- success! settings.to_h
17
- end
18
- end
19
-
20
- class Chain
21
- include Teckel::Chain
22
-
23
- default_settings!(a: { say: "Chain Default" })
24
-
25
- step :a, MyOperation
26
- end
27
- end
28
-
29
- RSpec.describe Teckel::Chain do
30
- specify "call chain without settings, uses default settings" do
31
- result = TeckelChainDefaultSettingsTest::Chain.call
32
- expect(result.success).to eq(say: "Chain Default", other: nil)
33
- end
34
-
35
- specify "call chain with explicit settings, overwrites defaults" do
36
- result = TeckelChainDefaultSettingsTest::Chain.with(a: { other: "What" }).call
37
- expect(result.success).to eq(say: nil, other: "What")
38
- end
39
- end
@@ -1,116 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'support/dry_base'
4
- require 'support/fake_models'
5
-
6
- module TeckelChainDefaultsViaBaseClass
7
- LOG = [] # rubocop:disable Style/MutableConstant
8
-
9
- class LoggingChain
10
- include Teckel::Chain
11
-
12
- around do |chain, input|
13
- require 'benchmark'
14
- result = nil
15
- LOG << Benchmark.measure { result = chain.call(input) }
16
- result
17
- end
18
-
19
- freeze
20
- end
21
-
22
- class OperationA
23
- include Teckel::Operation
24
-
25
- result!
26
-
27
- input none
28
- output Types::Integer
29
- error none
30
-
31
- def call(_)
32
- success! rand(1000)
33
- end
34
-
35
- finalize!
36
- end
37
-
38
- class OperationB
39
- include Teckel::Operation
40
-
41
- result!
42
-
43
- input none
44
- output Types::String
45
- error none
46
-
47
- def call(_)
48
- success! ("a".."z").to_a.sample
49
- end
50
-
51
- finalize!
52
- end
53
-
54
- class ChainA < LoggingChain
55
- step :roll, OperationA
56
-
57
- finalize!
58
- end
59
-
60
- class ChainB < LoggingChain
61
- step :say, OperationB
62
-
63
- finalize!
64
- end
65
-
66
- class ChainC < ChainB
67
- finalize!
68
- end
69
- end
70
-
71
- RSpec.describe Teckel::Chain do
72
- before do
73
- TeckelChainDefaultsViaBaseClass::LOG.clear
74
- end
75
-
76
- let(:base_chain) { TeckelChainDefaultsViaBaseClass::LoggingChain }
77
- let(:chain_a) { TeckelChainDefaultsViaBaseClass::ChainA }
78
- let(:chain_b) { TeckelChainDefaultsViaBaseClass::ChainB }
79
- let(:chain_c) { TeckelChainDefaultsViaBaseClass::ChainC }
80
-
81
- it "inherits config" do
82
- expect(chain_a.around)
83
- expect(chain_b.around)
84
-
85
- expect(base_chain.steps).to eq([])
86
- expect(chain_a.steps.size).to eq(1)
87
- expect(chain_b.steps.size).to eq(1)
88
- end
89
-
90
- it "runs chain a" do
91
- expect {
92
- result = chain_a.call
93
- expect(result.success).to be_a(Integer)
94
- }.to change {
95
- TeckelChainDefaultsViaBaseClass::LOG.size
96
- }.from(0).to(1)
97
- end
98
-
99
- it "runs chain b" do
100
- expect {
101
- result = chain_b.call
102
- expect(result.success).to be_a(String)
103
- }.to change {
104
- TeckelChainDefaultsViaBaseClass::LOG.size
105
- }.from(0).to(1)
106
- end
107
-
108
- it "inherits steps" do
109
- expect {
110
- result = chain_c.call
111
- expect(result.success).to be_a(String)
112
- }.to change {
113
- TeckelChainDefaultsViaBaseClass::LOG.size
114
- }.from(0).to(1)
115
- end
116
- end
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module TeckelChainNoneInputTest
4
- class MyOperation
5
- include Teckel::Operation
6
- result!
7
-
8
- settings Struct.new(:say)
9
-
10
- input none
11
- output String
12
- error none
13
-
14
- def call(_)
15
- success!(settings&.say || "Called")
16
- end
17
- end
18
-
19
- class Chain
20
- include Teckel::Chain
21
-
22
- step :a, MyOperation
23
- end
24
- end
25
-
26
- RSpec.describe Teckel::Chain do
27
- specify "call chain without input value" do
28
- result = TeckelChainNoneInputTest::Chain.call
29
- expect(result.success).to eq("Called")
30
- end
31
-
32
- specify "call chain runner without input value" do
33
- result = TeckelChainNoneInputTest::Chain.with(a: "What").call
34
- expect(result.success).to eq("What")
35
- end
36
- end
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'support/dry_base'
4
- require 'support/fake_models'
5
-
6
- module TeckelChainResultTest
7
- class Message
8
- include ::Teckel::Operation
9
-
10
- result!
11
-
12
- input Types::Hash.schema(message: Types::String)
13
- error none
14
- output Types::String
15
-
16
- def call(input)
17
- success! input[:message].upcase
18
- end
19
- end
20
-
21
- class Chain
22
- include Teckel::Chain
23
-
24
- step :message, Message
25
-
26
- class Result < Teckel::Operation::Result
27
- def initialize(value, success, step, opts = {})
28
- super(value, success)
29
- @step = step
30
- @opts = opts
31
- end
32
-
33
- class << self
34
- alias :[] :new # Alias the default constructor to :new
35
- end
36
-
37
- attr_reader :opts, :step
38
- end
39
-
40
- result_constructor ->(value, success, step) {
41
- result.new(value, success, step, time: Time.now.to_i)
42
- }
43
- end
44
- end
45
-
46
- RSpec.describe Teckel::Chain do
47
- specify do
48
- result = TeckelChainResultTest::Chain.call(message: "Hello World!")
49
- expect(result).to be_successful
50
- expect(result.success).to eq("HELLO WORLD!")
51
- expect(result.opts).to include(time: kind_of(Integer))
52
- end
53
- end