trailblazer-context 0.3.3 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: {}
|