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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 278837bbeb41d58a08abe15cfa239e7c2d0030cf4d4d7de19e98f0982fd70ea1
4
- data.tar.gz: 1dffd41a315387722858cf987a4289211cc8ea537664c98b5042539fcee11e6a
3
+ metadata.gz: 68c328cb817dbf1889d8e4619afa0b950786a839d8685c145ac9cda543b63c5b
4
+ data.tar.gz: 3bbe468cf341ebb429715983c3ea284b02251eedfe0084b6225252fbf5240e4b
5
5
  SHA512:
6
- metadata.gz: 553c3dd7b3d9ff2ed9493c4a0d44369d1f6f4442ab9b53679e6e1147f7e052d98974273fa38466056e377e2de03fdd662f8e12d28b99cfde99d1074c5d4aa9e3
7
- data.tar.gz: abfddac36f7d1a789f45018d3a79e98f5443e4934a29513f80d728453e5c12cf10e85bd8f061eead6b96006c3f0df85a26a2a80c9184524255b9e7b7a197504c
6
+ metadata.gz: 0001ec043007eec13ac0ce4c836f406a4fbfcfee8c759fb85c2059d0fffce774423d8986f504a9b0fc36c31e4d0bd75673a02f2d1e9f92b1229f95af3115f029
7
+ data.tar.gz: 85848da20e2f7639183f4cefc2095294f183f3217927b8ed573ba307ed122871549f1a5409d3369e767a896f8a64c18af598e30fbf10bc33de3918e546e2c6dd
data/.travis.yml CHANGED
@@ -3,6 +3,7 @@ before_install: gem install bundler
3
3
  cache: bundler
4
4
  rvm:
5
5
  - ruby-head
6
+ - 3.0
6
7
  - 2.7
7
8
  - 2.6
8
9
  - 2.5
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
@@ -1,5 +1,4 @@
1
1
  source "https://rubygems.org"
2
2
  gemspec
3
3
 
4
- gem "benchmark-ips"
5
4
  gem "minitest-line"
@@ -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
@@ -1,5 +1,5 @@
1
1
  module Trailblazer
2
2
  module Context
3
- VERSION = "0.3.3"
3
+ VERSION = "0.4.0"
4
4
  end
5
5
  end
@@ -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
- proc.(*args, &block)
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, **, &block)
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."), **, &block)
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(call_implementation, proc)
29
+ def self.build(proc)
28
30
  if proc.is_a? Symbol
29
- ->(*args, &block) { call_implementation.evaluate_method(proc, *args, &block) }
31
+ ->(*args, **kws, &block) { Option.evaluate_method(proc, *args, **kws, &block) }
30
32
  else
31
- ->(*args, &block) { call_implementation.evaluate_callable(proc, *args, &block) }
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.build(KW, proc)
61
- end
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(Option, proc)
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, {exec_context: step}, &block), block
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, {}, &block), block
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, {exec_context: nil}, &block), block
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
- _(result).must_equal([1, 2, [3, 4]])
83
- _(positionals).must_equal [1, 2, 3, 4]
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
@@ -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 = "http://trailblazer.to/gems/workflow"
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.3.3
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-23 00:00:00.000000000 Z
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: http://trailblazer.to/gems/workflow
99
+ homepage: https://trailblazer.to/
100
100
  licenses:
101
101
  - MIT
102
102
  metadata: {}