trailblazer-context 0.1.4 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f888d046e1096b02494a7a5fede3827027321d7553d6a01fb5f7ac2dc9fb43cc
4
- data.tar.gz: 67f3bd4537ea2671a94ac3a74c55ed2f49ed9e9b58169af8eb2e1767fbc0416b
3
+ metadata.gz: fec7a9c801fedda32fee29585bf8108b6a730980fe826df22d00cd7f0b6c8d1b
4
+ data.tar.gz: 6a39db80e891a99c802c1262b26434389869fc2b367c34cfffb5923acdd574b4
5
5
  SHA512:
6
- metadata.gz: 950342604fd800574b188606453e5dbe2b685fe8bb49c8b4c042d27c4beb91be298c2a4a0e07cc509164b6c5ebc0987785e631f487179dbecffacfb180a11ca3
7
- data.tar.gz: f8fafddb80a3441a623c0db104776919313ff99f4eea0d2c0aa8826c00ba0fb89319294e0c3f892db11061825d41f67e9d2d68637768ce67be984533c1d92230
6
+ metadata.gz: cdfce2ccb6119793c8971e70d0161f8b330b5941f07c7b06467713f3a3ebe42ce2563bcc9c0259bc412fbb12c2264586dde4414456d24f7d3eb2b2c4eec65fc7
7
+ data.tar.gz: 8f34a42f0b7a245586e86a45482e5d797d40edf9c6164cb149fd11de4bdbfe750b067d69a19eebdd747631df85bd40ce0789b2ce65c050c9309f87bed398795d
data/CHANGES.md CHANGED
@@ -1,3 +1,13 @@
1
+ # 0.2.0
2
+
3
+ * Added `Context::IndifferentAccess`.
4
+ * Added `Context::Aliasing`.
5
+ * `Context.for_circuit` is not the authorative builder for creating a context.
6
+
7
+ # 0.1.5
8
+
9
+ * `Context.build` allows quickly building a Context without requiring the circuit interface.
10
+
1
11
  # 0.1.4
2
12
 
3
13
  * Fix the `IndifferentAccess` name lookup. Since we can't convert all keys to symbols internally (not every options structure has `collect`) we need to have a lookup chain.
@@ -14,10 +14,22 @@ module Trailblazer
14
14
  # only public creator: Build
15
15
  # :data object:
16
16
  class Context
17
- # NOTE: in the future, we might look up the Context to use in the ctx.
18
- # The options we pass in here to be forward-compatible.
19
- def self.for(wrapped_options, (ctx, flow_options), circuit_options)
20
- implementation.new(wrapped_options, {})
17
+ # NOTE: In the future, we might look up the Context to use in the ctx.
18
+ # The demanding signature is for forward-compat.
19
+ # @private
20
+ def self.for(wrapped_options, (ctx, flow_options), circuit_options) # TODO: remove
21
+ implementation.build(wrapped_options, {}, [ctx, flow_options], circuit_options)
22
+ end
23
+
24
+ def self.for_circuit(wrapped_options, mutable_options, (ctx, flow_options), circuit_options)
25
+ context_class = flow_options[:context_class] || implementation # Context::IndifferentAccess
26
+
27
+ context_class.build(wrapped_options, mutable_options, [ctx, flow_options], circuit_options)
28
+ end
29
+
30
+ # @public
31
+ def self.build(wrapped_options, *)
32
+ new(wrapped_options)
21
33
  end
22
34
 
23
35
  # I hate globals, but currently this is the only easy way for setting the implementation.
@@ -25,7 +37,7 @@ module Trailblazer
25
37
  IndifferentAccess
26
38
  end
27
39
 
28
- def initialize(wrapped_options, mutable_options)
40
+ def initialize(wrapped_options, mutable_options, *)
29
41
  @wrapped_options = wrapped_options
30
42
  @mutable_options = mutable_options
31
43
  # TODO: wrapped_options should be optimized for lookups here since
@@ -0,0 +1,36 @@
1
+ module Trailblazer
2
+ class Context
3
+ module Aliasing
4
+ def initialize(wrapped_options, mutable_options, context_alias: {}, **)
5
+ super(wrapped_options, mutable_options)
6
+
7
+ @aliases = context_alias.invert
8
+ end
9
+
10
+ def [](key)
11
+ return super unless aka = @aliases[key] # yepp, nil/false won't work
12
+ super(aka)
13
+ end
14
+
15
+ def key?(key)
16
+ return super unless aka = @aliases[key] # yepp, nil/false won't work
17
+ super(aka)
18
+ end
19
+
20
+ # @private ?
21
+ def merge(hash)
22
+ original, mutable_options = decompose
23
+
24
+ self.class.new(
25
+ original,
26
+ mutable_options.merge(hash),
27
+ context_alias: @aliases.invert # DISCUSS: maybe we can speed up by remembering the original options?
28
+ )
29
+ end
30
+
31
+ def to_hash
32
+ super.merge(Hash[@aliases.collect { |aka, k| key?(k) ? [aka, self[k]] : nil }.compact]) # FIXME: performance!
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,18 +1,35 @@
1
+ require "trailblazer/context/aliasing"
2
+
1
3
  module Trailblazer
2
4
  class Context
3
5
  class IndifferentAccess < Context
4
- def [](name)
5
- # TODO: well...
6
- @mutable_options.key?(name.to_sym) and return @mutable_options[name.to_sym]
7
- @mutable_options.key?(name.to_s) and return @mutable_options[name.to_s]
8
- @wrapped_options.key?(name.to_sym) and return @wrapped_options[name.to_sym]
9
- @wrapped_options[name.to_s]
6
+ module InstanceMethods
7
+ def [](name)
8
+ # TODO: well...
9
+ @mutable_options.key?(name.to_sym) and return @mutable_options[name.to_sym]
10
+ @mutable_options.key?(name.to_s) and return @mutable_options[name.to_s]
11
+ @wrapped_options.key?(name.to_sym) and return @wrapped_options[name.to_sym]
12
+ @wrapped_options[name.to_s]
13
+ end
14
+
15
+ def self.build(wrapped_options, mutable_options, (ctx, flow_options), circuit_options)
16
+ new(wrapped_options, mutable_options, flow_options)
17
+ end
10
18
  end
19
+ include InstanceMethods
11
20
 
12
21
  def key?(name)
13
22
  super(name.to_sym) || super(name.to_s)
14
23
  end
15
24
 
25
+ include Aliasing # FIXME
26
+
27
+ # This also builds IndifferentAccess::Aliasing.
28
+ # The {#build} method is designed to take all args from {for_circuit} and then
29
+ # translate that to the constructor.
30
+ def self.build(wrapped_options, mutable_options, (ctx, flow_options), circuit_options)
31
+ new(wrapped_options, mutable_options, **flow_options)
32
+ end
16
33
  end
17
34
  end
18
35
  end
@@ -1,5 +1,5 @@
1
1
  module Trailblazer
2
2
  class Context
3
- VERSION = "0.1.4"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
@@ -27,13 +27,13 @@ module Trailblazer
27
27
  # Note that both #evaluate_callable and #evaluate_method drop most of the args.
28
28
  # If you need those, override this class.
29
29
  # @private
30
- def self.evaluate_callable(proc, *args, **flow_options, &block)
30
+ def self.evaluate_callable(proc, *args, **circuit_options, &block)
31
31
  call!(proc, *args, &block)
32
32
  end
33
33
 
34
34
  # Make the context's instance method a "lambda" and reuse #call!.
35
35
  # @private
36
- def self.evaluate_method(proc, *args, exec_context: raise("No :exec_context given."), **flow_options, &block)
36
+ def self.evaluate_method(proc, *args, exec_context: raise("No :exec_context given."), **circuit_options, &block)
37
37
  call!(exec_context.method(proc), *args, &block)
38
38
  end
39
39
 
data/test/context_test.rb CHANGED
@@ -75,7 +75,7 @@ class ContextWithIndifferentAccessTest < Minitest::Spec
75
75
 
76
76
  immutable = {model: Object, "policy" => Hash}
77
77
 
78
- ctx = Trailblazer::Context.for(immutable, [immutable, flow_options], circuit_options)
78
+ ctx = Trailblazer::Context.for_circuit(immutable, {}, [immutable, flow_options], circuit_options)
79
79
 
80
80
  ctx[:model].must_equal Object
81
81
  ctx["model"].must_equal Object
@@ -92,7 +92,7 @@ class ContextWithIndifferentAccessTest < Minitest::Spec
92
92
  ctx.key?(:"contract.default").must_equal true
93
93
 
94
94
  # context in context
95
- ctx2 = Trailblazer::Context.for(ctx, [ctx, flow_options], circuit_options)
95
+ ctx2 = Trailblazer::Context.for_circuit(ctx, {}, [ctx, flow_options], circuit_options)
96
96
 
97
97
  ctx2[:model].must_equal Object
98
98
  ctx2["model"].must_equal Object
@@ -120,6 +120,94 @@ class ContextWithIndifferentAccessTest < Minitest::Spec
120
120
  ctx3.key?("result").must_equal true
121
121
  ctx3.key?(:result).must_equal true
122
122
  end
123
+
124
+ it "Aliasable" do
125
+ flow_options = {context_alias: {"contract.default" => :contract, "result.default"=>:result, "trace.stack" => :stack}}
126
+ circuit_options = {}
127
+
128
+ immutable = {model: Object, "policy" => Hash}
129
+
130
+ ctx = Trailblazer::Context.for_circuit(immutable, {}, [immutable, flow_options], circuit_options)
131
+
132
+ ctx[:model].must_equal Object
133
+ ctx["model"].must_equal Object
134
+ ctx[:policy].must_equal Hash
135
+ ctx["policy"].must_equal Hash
136
+
137
+ ctx["contract.default"] = Module
138
+ ctx["contract.default"].must_equal Module
139
+ ctx[:"contract.default"].must_equal Module
140
+
141
+ # alias
142
+ ctx[:result].must_equal nil
143
+ ctx["result"].must_equal nil
144
+
145
+ ctx[:contract].must_equal Module
146
+
147
+ ctx[:stack].must_equal nil
148
+
149
+ # Set an aliased property via setter
150
+ ctx["trace.stack"] = Object
151
+ ctx[:stack].must_equal Object
152
+ ctx["trace.stack"].must_equal Object
153
+
154
+ # key?
155
+ ctx.key?("____contract.default").must_equal false
156
+ ctx.key?("contract.default").must_equal true
157
+ ctx.key?(:"contract.default").must_equal true
158
+ ctx.key?(:contract).must_equal true
159
+ ctx.key?(:result).must_equal false
160
+ ctx.key?(:stack).must_equal true
161
+ ctx.key?("trace.stack").must_equal true
162
+ ctx.key?(:"trace.stack").must_equal true
163
+
164
+ # to_hash
165
+ ctx.to_hash.must_equal(:model=>Object, :policy=>Hash, :"contract.default"=>Module, :"trace.stack"=>Object, :contract=>Module, :stack=>Object)
166
+
167
+ # context in context
168
+ ctx2 = Trailblazer::Context.for_circuit(ctx, {}, [ctx, flow_options], circuit_options)
169
+
170
+ ctx2.key?("____contract.default").must_equal false
171
+ ctx2.key?("contract.default").must_equal true
172
+ ctx2.key?(:"contract.default").must_equal true
173
+ ctx2.key?(:contract).must_equal true
174
+ ctx2.key?(:result).must_equal false
175
+ ctx2.key?("result.default").must_equal false
176
+ ctx2.key?(:stack).must_equal true
177
+ ctx2.key?("trace.stack").must_equal true
178
+ ctx2.key?(:"trace.stack").must_equal true
179
+
180
+ # Set aliased in new context via setter
181
+ ctx2["result.default"] = Class
182
+
183
+ ctx2[:result].must_equal Class
184
+ ctx2[:"result.default"].must_equal Class
185
+
186
+ ctx2.key?("result.default").must_equal true
187
+ ctx2.key?(:"result.default").must_equal true
188
+ ctx2.key?(:result).must_equal true
189
+
190
+ # todo: TEST flow_options={context_class: SomethingElse}
191
+ end
192
+
193
+ it ".build provides default args" do
194
+ immutable = {model: Object, "policy.default" => Hash}
195
+
196
+ # {Aliasing#initialize}
197
+ ctx = Trailblazer::Context::IndifferentAccess.new(immutable, {}, context_alias: {"policy.default" => :policy})
198
+
199
+ ctx[:model].must_equal Object
200
+ ctx["model"].must_equal Object
201
+ ctx[:policy].must_equal Hash
202
+
203
+ ctx2 = ctx.merge(result: :success)
204
+
205
+
206
+ ctx2[:model].must_equal Object
207
+ ctx2["model"].must_equal Object
208
+ ctx2[:policy].must_equal Hash
209
+ ctx2[:result].must_equal :success
210
+ end
123
211
  end
124
212
 
125
213
  # TODO: test overriding Context.implementation.
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.1.4
4
+ version: 0.2.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: 2019-07-18 00:00:00.000000000 Z
11
+ date: 2019-09-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -86,6 +86,7 @@ files:
86
86
  - lib/trailblazer-context.rb
87
87
  - lib/trailblazer/container_chain.rb
88
88
  - lib/trailblazer/context.rb
89
+ - lib/trailblazer/context/aliasing.rb
89
90
  - lib/trailblazer/context/indifferent_access.rb
90
91
  - lib/trailblazer/context/version.rb
91
92
  - lib/trailblazer/option.rb