trailblazer-context 0.3.3 → 0.4.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/.travis.yml +1 -0
- data/CHANGES.md +19 -0
- data/Gemfile +0 -1
- data/lib/trailblazer/context.rb +3 -3
- data/lib/trailblazer/context/version.rb +1 -1
- data/lib/trailblazer/option.rb +15 -45
- data/test/context_test.rb +2 -2
- data/test/option_test.rb +31 -70
- data/trailblazer-context.gemspec +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 68c328cb817dbf1889d8e4619afa0b950786a839d8685c145ac9cda543b63c5b
|
4
|
+
data.tar.gz: 3bbe468cf341ebb429715983c3ea284b02251eedfe0084b6225252fbf5240e4b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0001ec043007eec13ac0ce4c836f406a4fbfcfee8c759fb85c2059d0fffce774423d8986f504a9b0fc36c31e4d0bd75673a02f2d1e9f92b1229f95af3115f029
|
7
|
+
data.tar.gz: 85848da20e2f7639183f4cefc2095294f183f3217927b8ed573ba307ed122871549f1a5409d3369e767a896f8a64c18af598e30fbf10bc33de3918e546e2c6dd
|
data/.travis.yml
CHANGED
data/CHANGES.md
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
# 0.4.0
|
2
|
+
|
3
|
+
* Ready for Ruby 3.0. :heart:
|
4
|
+
* Remove `Option::KW`, after many years it's been superseded by the original `Trailblazer::Option`.
|
5
|
+
|
6
|
+
To achieve an invocation such as
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
Option::KW(proc).(ctx, another_positional_arg, **circuit_options)
|
10
|
+
```
|
11
|
+
|
12
|
+
you can use the new `:keyword_arguments` options.
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
Option(proc).(ctx, another_positional_arg, keyword_arguments: ctx.to_hash, **circuit_options)
|
16
|
+
```
|
17
|
+
|
18
|
+
This way, no more guessing is happening about what positional arg is the actual `circuit_options`.
|
19
|
+
|
1
20
|
# 0.3.3
|
2
21
|
|
3
22
|
* Remove an unsolicited `puts`.
|
data/Gemfile
CHANGED
data/lib/trailblazer/context.rb
CHANGED
@@ -18,16 +18,16 @@ module Trailblazer
|
|
18
18
|
module_function
|
19
19
|
|
20
20
|
def for_circuit(wrapped_options, mutable_options, (_, flow_options), **)
|
21
|
-
build(wrapped_options, mutable_options, flow_options.fetch(:context_options))
|
21
|
+
build(wrapped_options, mutable_options, **flow_options.fetch(:context_options))
|
22
22
|
end
|
23
23
|
|
24
24
|
def build(wrapped_options, mutable_options, container_class:, **context_options)
|
25
|
-
container_class.new(wrapped_options, mutable_options, context_options)
|
25
|
+
container_class.new(wrapped_options, mutable_options, **context_options)
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
29
|
def self.Context(wrapped_options, mutable_options = {}, context_options = nil)
|
30
30
|
defaults = { container_class: Context::Container, replica_class: Context::Store::IndifferentAccess }
|
31
|
-
Context.build(wrapped_options, mutable_options, defaults.merge( Hash(context_options) ))
|
31
|
+
Context.build(wrapped_options, mutable_options, **defaults.merge( Hash(context_options) ))
|
32
32
|
end
|
33
33
|
end
|
data/lib/trailblazer/option.rb
CHANGED
@@ -3,75 +3,45 @@ module Trailblazer
|
|
3
3
|
# A call implementation invoking `proc.(*args)` and plainly forwarding all arguments.
|
4
4
|
# Override this for your own step strategy (see KW#call!).
|
5
5
|
# @private
|
6
|
-
def self.call!(proc, *args, &block)
|
7
|
-
|
6
|
+
def self.call!(proc, *args, keyword_arguments: {}, **, &block)
|
7
|
+
# {**keyword_arguments} gets removed automatically if it's an empty hash.
|
8
|
+
# DISCUSS: is this a good practice?
|
9
|
+
proc.(*args, **keyword_arguments, &block)
|
8
10
|
end
|
9
11
|
|
10
12
|
# Note that both #evaluate_callable and #evaluate_method drop most of the args.
|
11
13
|
# If you need those, override this class.
|
12
14
|
# @private
|
13
|
-
def self.evaluate_callable(proc, *args,
|
14
|
-
call!(proc, *args, &block)
|
15
|
+
def self.evaluate_callable(proc, *args, **options, &block)
|
16
|
+
call!(proc, *args, **options, &block)
|
15
17
|
end
|
16
18
|
|
17
19
|
# Make the context's instance method a "lambda" and reuse #call!.
|
18
20
|
# @private
|
19
|
-
def self.evaluate_method(proc, *args, exec_context: raise("No :exec_context given."),
|
20
|
-
call!(exec_context.method(proc), *args, &block)
|
21
|
+
def self.evaluate_method(proc, *args, exec_context: raise("No :exec_context given."), **options, &block)
|
22
|
+
call!(exec_context.method(proc), *args, **options, &block)
|
21
23
|
end
|
22
24
|
|
23
25
|
# Generic builder for a callable "option".
|
24
26
|
# @param call_implementation [Class, Module] implements the process of calling the proc
|
25
27
|
# while passing arguments/options to it in a specific style (e.g. kw args, step interface).
|
26
28
|
# @return [Proc] when called, this proc will evaluate its option (at run-time).
|
27
|
-
def self.build(
|
29
|
+
def self.build(proc)
|
28
30
|
if proc.is_a? Symbol
|
29
|
-
->(*args, &block) {
|
31
|
+
->(*args, **kws, &block) { Option.evaluate_method(proc, *args, **kws, &block) }
|
30
32
|
else
|
31
|
-
->(*args,
|
33
|
+
->(*args, **kws, &block) {
|
34
|
+
Option.evaluate_callable(proc, *args, **kws, &block) }
|
32
35
|
end
|
33
36
|
end
|
34
37
|
|
35
|
-
# Returns a {Proc} that, when called, invokes the `proc` argument with keyword arguments.
|
36
|
-
# This is known as "step (call) interface".
|
37
|
-
#
|
38
|
-
# This is commonly used by `Operation::step` to wrap the argument and make it
|
39
|
-
# callable in the circuit.
|
40
|
-
#
|
41
|
-
# my_proc = ->(options, **kws) { options["i got called"] = true }
|
42
|
-
# task = Trailblazer::Option::KW(my_proc)
|
43
|
-
# task.(options = {})
|
44
|
-
# options["i got called"] #=> true
|
45
|
-
#
|
46
|
-
# Alternatively, you can pass a symbol and an `:exec_context`.
|
47
|
-
#
|
48
|
-
# my_proc = :some_method
|
49
|
-
# task = Trailblazer::Option::KW(my_proc)
|
50
|
-
#
|
51
|
-
# class A
|
52
|
-
# def some_method(options, **kws)
|
53
|
-
# options["i got called"] = true
|
54
|
-
# end
|
55
|
-
# end
|
56
|
-
#
|
57
|
-
# task.(options = {}, exec_context: A.new)
|
58
|
-
# options["i got called"] #=> true
|
59
38
|
def self.KW(proc)
|
60
|
-
Option
|
61
|
-
|
62
|
-
|
63
|
-
# TODO: It would be cool if call! was typed and had `options SymbolizedHash` or something.
|
64
|
-
class KW < Option
|
65
|
-
# A different call implementation that calls `proc` with a "step interface".
|
66
|
-
# your_code.(options, **options)
|
67
|
-
# @private
|
68
|
-
def self.call!(proc, options, *)
|
69
|
-
proc.(options, **options.to_hash) # Step interface: (options, **)
|
70
|
-
end
|
39
|
+
raise "The `Option::KW()` method has been removed in trailblazer-context-0.4.
|
40
|
+
Please use `Option(task, keyword_arguments: {...})` instead. Check https://trailblazer.to/2.1/docs/trailblazer.html#trailblazer-context-option"
|
71
41
|
end
|
72
42
|
end
|
73
43
|
# @note This might go to trailblazer-args along with `Context` at some point.
|
74
44
|
def self.Option(proc)
|
75
|
-
Option.build(
|
45
|
+
Option.build(proc)
|
76
46
|
end
|
77
47
|
end
|
data/test/context_test.rb
CHANGED
@@ -250,7 +250,7 @@ class ContextWithIndifferentAccessTest < Minitest::Spec
|
|
250
250
|
immutable = { model: Object }
|
251
251
|
options = { container_class: MyContainer, replica_class: Trailblazer::Context::Store::IndifferentAccess }
|
252
252
|
|
253
|
-
ctx = Trailblazer::Context.build(immutable, {}, options)
|
253
|
+
ctx = Trailblazer::Context.build(immutable, {}, **options)
|
254
254
|
_(ctx.class).must_equal(MyContainer)
|
255
255
|
_(ctx.inspect).must_equal("#<MyContainer wrapped=#{immutable} mutable={}>")
|
256
256
|
|
@@ -277,7 +277,7 @@ class ContextWithIndifferentAccessTest < Minitest::Spec
|
|
277
277
|
immutable = { model: Object }
|
278
278
|
options = { container_class: Trailblazer::Context::Container, replica_class: MyReplica }
|
279
279
|
|
280
|
-
ctx = Trailblazer::Context.build(immutable, {}, options)
|
280
|
+
ctx = Trailblazer::Context.build(immutable, {}, **options)
|
281
281
|
ctx[:integer] = Integer
|
282
282
|
|
283
283
|
_(ctx[:integer]).must_equal(Integer)
|
data/test/option_test.rb
CHANGED
@@ -8,6 +8,22 @@ class OptionTest < Minitest::Spec
|
|
8
8
|
_(keywords.inspect).must_equal %({:a=>2, :b=>3})
|
9
9
|
end
|
10
10
|
|
11
|
+
# it "what" do
|
12
|
+
# ctx = {params: 1}
|
13
|
+
# tmp_options = {constant: Object, model: Module}
|
14
|
+
|
15
|
+
# builder = Class.new do
|
16
|
+
# def builder(ctx, constant:, model:, **)
|
17
|
+
# raise model.inspect
|
18
|
+
# end
|
19
|
+
# end.new
|
20
|
+
|
21
|
+
# circuit_options = {exec_context: builder}
|
22
|
+
|
23
|
+
# # Trailblazer::Option(:builder, ).(ctx, tmp_options, **circuit_options.merge(keyword_arguments: tmp_options)) # calls {def default_contract!(options, constant:, model:, **)}
|
24
|
+
# Trailblazer::Option(:builder, ).(ctx, **circuit_options.merge(keyword_arguments: tmp_options)) # calls {def default_contract!(options, constant:, model:, **)}
|
25
|
+
# end
|
26
|
+
|
11
27
|
describe "positional and kws" do
|
12
28
|
class Step
|
13
29
|
def with_positional_and_keywords(options, a: nil, **more_options, &block)
|
@@ -38,13 +54,13 @@ class OptionTest < Minitest::Spec
|
|
38
54
|
|
39
55
|
# positional = { a: 1 }
|
40
56
|
# keywords = { a: 2, b: 3 }
|
41
|
-
assert_result option.(positional, keywords, exec_context: step)
|
57
|
+
assert_result option.(positional, keyword_arguments: keywords, exec_context: step)
|
42
58
|
end
|
43
59
|
|
44
60
|
it "allows passing a block, too" do
|
45
61
|
step = Step.new
|
46
62
|
|
47
|
-
assert_result option.(positional, keywords,
|
63
|
+
assert_result option.(positional, keyword_arguments: keywords, exec_context: step, &block), block
|
48
64
|
end
|
49
65
|
end
|
50
66
|
|
@@ -52,15 +68,15 @@ class OptionTest < Minitest::Spec
|
|
52
68
|
let(:option) { Trailblazer::Option(WITH_POSITIONAL_AND_KEYWORDS) }
|
53
69
|
|
54
70
|
it "-> {} lambda" do
|
55
|
-
assert_result option.(positional, keywords
|
71
|
+
assert_result option.(positional, **{keyword_arguments: keywords})
|
56
72
|
end
|
57
73
|
|
58
74
|
it "allows passing a block, too" do
|
59
|
-
assert_result option.(positional, keywords
|
75
|
+
assert_result option.(positional, **{keyword_arguments: keywords}, &block), block
|
60
76
|
end
|
61
77
|
|
62
78
|
it "doesn't mind :exec_context" do
|
63
|
-
assert_result option.(positional, keywords, exec_context: "bogus")
|
79
|
+
assert_result option.(positional, keyword_arguments: keywords, exec_context: "bogus")
|
64
80
|
end
|
65
81
|
end
|
66
82
|
|
@@ -68,21 +84,27 @@ class OptionTest < Minitest::Spec
|
|
68
84
|
let(:option) { Trailblazer::Option(WithPositionalAndKeywords) }
|
69
85
|
|
70
86
|
it "passes through all args" do
|
71
|
-
assert_result option.(positional, keywords, exec_context: nil)
|
87
|
+
assert_result option.(positional, keyword_arguments: keywords, exec_context: nil)
|
72
88
|
end
|
73
89
|
|
74
90
|
it "allows passing a block, too" do
|
75
|
-
assert_result option.(positional, keywords,
|
91
|
+
assert_result option.(positional, keyword_arguments: keywords, exec_context: nil, &block), block
|
76
92
|
end
|
77
93
|
end
|
78
94
|
end
|
79
95
|
|
80
96
|
describe "positionals" do
|
81
97
|
def assert_result_pos(result)
|
82
|
-
|
83
|
-
|
98
|
+
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.7.0")
|
99
|
+
_(result).must_equal([1, 2, [3, 4]])
|
100
|
+
_(positionals).must_equal [1, 2, 3, 4]
|
101
|
+
else
|
102
|
+
_(result).must_equal([1, 2, [3, 4, {}]])
|
103
|
+
_(positionals).must_equal [1, 2, 3, 4]
|
104
|
+
end
|
84
105
|
end
|
85
106
|
|
107
|
+
# In Ruby < 3.0, {*args} will grab both positionals and keyword arguments.
|
86
108
|
class Step
|
87
109
|
def with_positionals(a, b, *args)
|
88
110
|
[a, b, args]
|
@@ -122,65 +144,4 @@ class OptionTest < Minitest::Spec
|
|
122
144
|
end
|
123
145
|
end
|
124
146
|
|
125
|
-
describe "Option::KW" do
|
126
|
-
def assert_result_kws(result)
|
127
|
-
_(result).must_equal([{a: 1, b: 2, c: 3}, 1, 2, {c: 3}])
|
128
|
-
end
|
129
|
-
|
130
|
-
class Step
|
131
|
-
def with_kws(options, a: nil, b: nil, **rest)
|
132
|
-
[options, a, b, rest]
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
module Task
|
137
|
-
def self.with_kws(options, a: nil, b: nil, **rest)
|
138
|
-
[options, a, b, rest]
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
WITH_KWS = ->(options, a: nil, b: nil, **rest) do
|
143
|
-
[options, a, b, rest]
|
144
|
-
end
|
145
|
-
|
146
|
-
class WithKWs
|
147
|
-
def self.call(options, a: nil, b: nil, **rest)
|
148
|
-
[options, a, b, rest]
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
let(:options) { {a: 1, b: 2, c: 3} }
|
153
|
-
|
154
|
-
it ":method" do
|
155
|
-
step = Step.new
|
156
|
-
|
157
|
-
option = Trailblazer::Option::KW(:with_kws)
|
158
|
-
|
159
|
-
assert_result_kws option.(options, exec_context: step)
|
160
|
-
end
|
161
|
-
|
162
|
-
it "Method instance" do
|
163
|
-
option = Trailblazer::Option::KW(Task.method(:with_kws))
|
164
|
-
|
165
|
-
assert_result_kws option.(options, {})
|
166
|
-
end
|
167
|
-
|
168
|
-
it "-> {} lambda" do
|
169
|
-
option = Trailblazer::Option::KW(WITH_KWS)
|
170
|
-
|
171
|
-
assert_result_kws option.(options, {})
|
172
|
-
end
|
173
|
-
|
174
|
-
it "lambda ignores :exec_context" do
|
175
|
-
option = Trailblazer::Option::KW(WITH_KWS)
|
176
|
-
|
177
|
-
assert_result_kws option.(options, exec_context: "something")
|
178
|
-
end
|
179
|
-
|
180
|
-
it "callable" do
|
181
|
-
option = Trailblazer::Option::KW(WithKWs)
|
182
|
-
|
183
|
-
assert_result_kws option.(options, {})
|
184
|
-
end
|
185
|
-
end
|
186
147
|
end
|
data/trailblazer-context.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
|
11
11
|
spec.summary = "Argument-specific data structures for Trailblazer."
|
12
12
|
spec.description = "Argument-specific data structures for Trailblazer such as Context, Option and ContainerChain."
|
13
|
-
spec.homepage = "
|
13
|
+
spec.homepage = "https://trailblazer.to/"
|
14
14
|
spec.licenses = ["MIT"]
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trailblazer-context
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Sutterer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-02-
|
11
|
+
date: 2021-02-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hashie
|
@@ -96,7 +96,7 @@ files:
|
|
96
96
|
- test/option_test.rb
|
97
97
|
- test/test_helper.rb
|
98
98
|
- trailblazer-context.gemspec
|
99
|
-
homepage:
|
99
|
+
homepage: https://trailblazer.to/
|
100
100
|
licenses:
|
101
101
|
- MIT
|
102
102
|
metadata: {}
|