trailblazer-activity-dsl-linear 1.0.0 → 1.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 +4 -4
- data/.github/workflows/ci.yml +2 -3
- data/CHANGES.md +100 -0
- data/Gemfile +7 -4
- data/Rakefile +1 -1
- data/lib/trailblazer/activity/dsl/linear/feature/merge.rb +2 -2
- data/lib/trailblazer/activity/dsl/linear/feature/patch.rb +9 -5
- data/lib/trailblazer/activity/dsl/linear/feature/variable_mapping/dsl.rb +241 -156
- data/lib/trailblazer/activity/dsl/linear/feature/variable_mapping/runtime.rb +276 -0
- data/lib/trailblazer/activity/dsl/linear/feature/variable_mapping.rb +70 -226
- data/lib/trailblazer/activity/dsl/linear/helper/path.rb +37 -18
- data/lib/trailblazer/activity/dsl/linear/helper.rb +38 -17
- data/lib/trailblazer/activity/dsl/linear/normalizer/extensions.rb +63 -0
- data/lib/trailblazer/activity/dsl/linear/normalizer/inherit.rb +90 -0
- data/lib/trailblazer/activity/dsl/linear/normalizer/output_tuples.rb +160 -0
- data/lib/trailblazer/activity/dsl/linear/normalizer/terminus.rb +26 -29
- data/lib/trailblazer/activity/dsl/linear/normalizer.rb +99 -160
- data/lib/trailblazer/activity/dsl/linear/sequence/builder.rb +3 -2
- data/lib/trailblazer/activity/dsl/linear/sequence/compiler.rb +21 -17
- data/lib/trailblazer/activity/dsl/linear/sequence/search.rb +2 -8
- data/lib/trailblazer/activity/dsl/linear/strategy.rb +56 -17
- data/lib/trailblazer/activity/dsl/linear/version.rb +1 -1
- data/lib/trailblazer/activity/dsl/linear.rb +13 -1
- data/lib/trailblazer/activity/fast_track.rb +96 -67
- data/lib/trailblazer/activity/path.rb +35 -53
- data/lib/trailblazer/activity/railway.rb +63 -65
- data/trailblazer-activity-dsl-linear.gemspec +8 -8
- metadata +27 -18
- data/lib/trailblazer/activity/dsl/linear/feature/variable_mapping/inherit.rb +0 -38
@@ -10,44 +10,19 @@ module Trailblazer
|
|
10
10
|
module DSL
|
11
11
|
module_function
|
12
12
|
|
13
|
-
# Compute pipeline for {:input} option.
|
14
|
-
def pipe_for_mono_input(input: [], inject: [], in_filters: [], output: [], **)
|
15
|
-
has_input = Array(input).any?
|
16
|
-
has_mono_options = has_input || Array(inject).any? || Array(output).any? # :input, :inject and :output are "mono options".
|
17
|
-
has_composable_options = in_filters.any? # DISCUSS: why are we not testing Inject()?
|
18
|
-
|
19
|
-
if has_mono_options && has_composable_options
|
20
|
-
warn "[Trailblazer] You are mixing `:input` and `In() => ...`. `In()` and Inject () options are ignored and `:input` wins: #{input} #{inject} #{output} <> #{in_filters} / "
|
21
|
-
end
|
22
|
-
|
23
|
-
pipeline = initial_input_pipeline(add_default_ctx: !has_input)
|
24
|
-
pipeline = add_steps_for_input_option(pipeline, input: input)
|
25
|
-
pipeline = add_steps_for_inject_option(pipeline, inject: inject)
|
26
|
-
|
27
|
-
return pipeline, has_mono_options, has_composable_options
|
28
|
-
end
|
29
|
-
|
30
13
|
# Compute pipeline for In() and Inject().
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
inject_filters = DSL::Inject.filters_for_injects(inject_filters) # {Inject() => ...} the pure user input gets translated into AddVariable aggregate steps.
|
35
|
-
in_filters = DSL::Tuple.filters_from_options(in_filters)
|
36
|
-
|
37
|
-
# With only injections defined, we do not filter out anything, we use the original ctx
|
38
|
-
# and _add_ defaulting for injected variables.
|
39
|
-
pipeline = add_filter_steps(initial_input_pipeline, in_filters)
|
40
|
-
pipeline = add_filter_steps(pipeline, inject_filters, path_prefix: "inject")
|
14
|
+
def pipe_for_composable_input(in_filters: [], initial_input_pipeline: initial_input_pipeline_for(in_filters), **)
|
15
|
+
in_filters = DSL::Tuple.filters_from_options(in_filters)
|
16
|
+
_pipeline = add_filter_steps(initial_input_pipeline, in_filters)
|
41
17
|
end
|
42
18
|
|
43
19
|
# initial pipleline depending on whether or not we got any In() filters.
|
44
20
|
def initial_input_pipeline_for(in_filters)
|
45
|
-
is_inject_only =
|
21
|
+
is_inject_only = in_filters.find { |k, v| k.is_a?(VariableMapping::DSL::In) }.nil?
|
46
22
|
|
47
23
|
initial_input_pipeline(add_default_ctx: is_inject_only)
|
48
24
|
end
|
49
25
|
|
50
|
-
|
51
26
|
# Adds the default_ctx step as per option {:add_default_ctx}
|
52
27
|
def initial_input_pipeline(add_default_ctx: false)
|
53
28
|
# No In() or {:input}. Use default ctx, which is the original ctxx.
|
@@ -55,11 +30,10 @@ module Trailblazer
|
|
55
30
|
default_ctx_row =
|
56
31
|
add_default_ctx ? Activity::TaskWrap::Pipeline.Row(*default_input_ctx_config) : nil
|
57
32
|
|
58
|
-
|
33
|
+
Activity::TaskWrap::Pipeline.new(
|
59
34
|
[
|
60
|
-
Activity::TaskWrap::Pipeline.Row("input.init_hash", VariableMapping.method(:initial_aggregate)), # very first step
|
61
35
|
default_ctx_row,
|
62
|
-
Activity::TaskWrap::Pipeline.Row("input.scope",
|
36
|
+
Activity::TaskWrap::Pipeline.Row("input.scope", VariableMapping.method(:scope)), # last step
|
63
37
|
].compact
|
64
38
|
)
|
65
39
|
end
|
@@ -68,38 +42,14 @@ module Trailblazer
|
|
68
42
|
["input.default_input", VariableMapping.method(:default_input_ctx)]
|
69
43
|
end
|
70
44
|
|
71
|
-
|
45
|
+
# Handle {:input} and {:inject} option, the "old" interface.
|
72
46
|
def add_steps_for_input_option(pipeline, input:)
|
73
|
-
tuple = DSL.In(
|
47
|
+
tuple = DSL.In() # simulate {In() => input}
|
74
48
|
input_filter = DSL::Tuple.filters_from_options([[tuple, input]])
|
75
49
|
|
76
50
|
add_filter_steps(pipeline, input_filter)
|
77
51
|
end
|
78
52
|
|
79
|
-
|
80
|
-
def pipe_for_mono_output(output_with_outer_ctx: false, output: [], out_filters: [], **)
|
81
|
-
# No Out(), no {:output} will result in a default_output_ctx step.
|
82
|
-
has_output = Array(output).any?
|
83
|
-
has_mono_options = has_output
|
84
|
-
has_composable_options = Array(out_filters).any?
|
85
|
-
|
86
|
-
if has_mono_options && has_composable_options
|
87
|
-
warn "[Trailblazer] You are mixing `:output` and `Out() => ...`. `Out()` options are ignored and `:output` wins."
|
88
|
-
end
|
89
|
-
|
90
|
-
pipeline = initial_output_pipeline(add_default_ctx: !has_output)
|
91
|
-
pipeline = add_steps_for_output_option(pipeline, output: output, output_with_outer_ctx: output_with_outer_ctx)
|
92
|
-
|
93
|
-
return pipeline, has_mono_options, has_composable_options
|
94
|
-
end
|
95
|
-
|
96
|
-
def add_steps_for_output_option(pipeline, output:, output_with_outer_ctx:)
|
97
|
-
tuple = DSL.Out(name: ":output", with_outer_ctx: output_with_outer_ctx) # simulate {Out() => output}
|
98
|
-
output_filter = DSL::Tuple.filters_from_options([[tuple, output]])
|
99
|
-
|
100
|
-
add_filter_steps(pipeline, output_filter, prepend_to: "output.merge_with_original", path_prefix: "output")
|
101
|
-
end
|
102
|
-
|
103
53
|
def pipe_for_composable_output(out_filters: [], initial_output_pipeline: initial_output_pipeline(add_default_ctx: Array(out_filters).empty?), **)
|
104
54
|
out_filters = DSL::Tuple.filters_from_options(out_filters)
|
105
55
|
|
@@ -112,7 +62,6 @@ module Trailblazer
|
|
112
62
|
|
113
63
|
Activity::TaskWrap::Pipeline.new(
|
114
64
|
[
|
115
|
-
Activity::TaskWrap::Pipeline.Row("output.init_hash", VariableMapping.method(:initial_aggregate)), # very first step
|
116
65
|
default_ctx_row,
|
117
66
|
Activity::TaskWrap::Pipeline.Row("output.merge_with_original", VariableMapping.method(:merge_with_original)), # last step
|
118
67
|
].compact
|
@@ -123,14 +72,6 @@ module Trailblazer
|
|
123
72
|
["output.default_output", VariableMapping.method(:default_output_ctx)]
|
124
73
|
end
|
125
74
|
|
126
|
-
def add_steps_for_inject_option(pipeline, inject:)
|
127
|
-
injects = inject.collect { |name| name.is_a?(Symbol) ? [DSL.Inject(), [name]] : [DSL.Inject(), name] }
|
128
|
-
|
129
|
-
tuples = DSL::Inject.filters_for_injects(injects) # DISCUSS: should we add passthrough/defaulting here at Inject()-time?
|
130
|
-
|
131
|
-
add_filter_steps(pipeline, tuples, path_prefix: "inject")
|
132
|
-
end
|
133
|
-
|
134
75
|
def add_filter_steps(pipeline, rows, prepend_to: "input.scope", path_prefix: "input")
|
135
76
|
rows = add_variables_steps_for_filters(rows, path_prefix: path_prefix)
|
136
77
|
|
@@ -141,53 +82,14 @@ module Trailblazer
|
|
141
82
|
Activity::Adds.apply_adds(pipeline, adds)
|
142
83
|
end
|
143
84
|
|
144
|
-
|
85
|
+
# Returns array of step rows ("sequence").
|
145
86
|
# @param filters [Array] List of {Filter} objects
|
146
87
|
def add_variables_steps_for_filters(filters, path_prefix:)
|
147
88
|
filters.collect do |filter|
|
148
|
-
["#{path_prefix}.add_variables.#{filter.name}", filter
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
|
153
|
-
# Filter code
|
154
|
-
# Converting user options to callable filters.
|
155
|
-
|
156
|
-
# @param [Array, Hash, Proc] User option coming from the DSL, like {[:model]}
|
157
|
-
#
|
158
|
-
# Returns a "filter interface" callable that's invoked in {AddVariables}:
|
159
|
-
# filter.(new_ctx, ..., keyword_arguments: new_ctx.to_hash, **circuit_options)
|
160
|
-
def self.build_filter(user_filter)
|
161
|
-
Trailblazer::Option(filter_for(user_filter))
|
162
|
-
end
|
163
|
-
|
164
|
-
# Convert a user option such as {[:model]} to a filter.
|
165
|
-
#
|
166
|
-
# Returns a filter proc to be called in an Option.
|
167
|
-
# @private
|
168
|
-
def self.filter_for(filter)
|
169
|
-
if filter.is_a?(::Array) || filter.is_a?(::Hash)
|
170
|
-
filter_from_dsl(filter)
|
171
|
-
else
|
172
|
-
filter
|
89
|
+
["#{path_prefix}.add_variables.#{filter.name}", filter] # FIXME: config name sucks, of course, if we want to allow inserting etc.
|
173
90
|
end
|
174
91
|
end
|
175
92
|
|
176
|
-
# The returned filter compiles a new hash for Scoped/Unscoped that only contains
|
177
|
-
# the desired i/o variables.
|
178
|
-
#
|
179
|
-
# Filter expects a "filter interface" {(ctx, **)}.
|
180
|
-
def self.filter_from_dsl(map)
|
181
|
-
hsh = DSL.hash_for(map)
|
182
|
-
|
183
|
-
->(incoming_ctx, **kwargs) { Hash[hsh.collect { |from_name, to_name| [to_name, incoming_ctx[from_name]] }] }
|
184
|
-
end
|
185
|
-
|
186
|
-
def self.hash_for(ary)
|
187
|
-
return ary if ary.instance_of?(::Hash)
|
188
|
-
Hash[ary.collect { |name| [name, name] }]
|
189
|
-
end
|
190
|
-
|
191
93
|
# Keeps user's DSL configuration for a particular io-pipe step.
|
192
94
|
# Implements the interface for the actual I/O code and is DSL code happening in the normalizer.
|
193
95
|
# The actual I/O code expects {DSL::In} and {DSL::Out} objects to generate the two io-pipes.
|
@@ -195,84 +97,267 @@ module Trailblazer
|
|
195
97
|
# If a user needs to inject their own private iop step they can create this data structure with desired values here.
|
196
98
|
# This is also the reason why a lot of options computation such as {:with_outer_ctx} happens here and not in the IO code.
|
197
99
|
|
198
|
-
class Tuple
|
199
|
-
def
|
200
|
-
|
100
|
+
class Tuple
|
101
|
+
def initialize(variable_name, add_variables_class, filters_builder, add_variables_class_for_callable = nil, insert_args: nil, **options)
|
102
|
+
@options =
|
103
|
+
{
|
104
|
+
variable_name: variable_name,
|
105
|
+
add_variables_class: add_variables_class,
|
106
|
+
filters_builder: filters_builder,
|
107
|
+
insert_args: insert_args,
|
108
|
+
|
109
|
+
add_variables_class_for_callable: add_variables_class_for_callable,
|
110
|
+
|
111
|
+
**options
|
112
|
+
}
|
201
113
|
end
|
202
114
|
|
115
|
+
def to_h
|
116
|
+
@options
|
117
|
+
end
|
118
|
+
|
119
|
+
def self.filters_from_options(tuples_to_user_filters)
|
120
|
+
tuples_to_user_filters.flat_map { |tuple, user_filter| tuple.(user_filter) }
|
121
|
+
end
|
203
122
|
|
204
123
|
# @return [Filter] Filter instance that keeps {name} and {aggregate_step}.
|
205
124
|
def call(user_filter)
|
206
|
-
|
207
|
-
aggregate_step = add_variables_class.new(filter, user_filter)
|
208
|
-
|
209
|
-
VariableMapping::Filter.new(aggregate_step, filter, name, add_variables_class)
|
125
|
+
@options[:filters_builder].(user_filter, **to_h)
|
210
126
|
end
|
211
127
|
end # TODO: implement {:insert_args}
|
212
128
|
|
213
129
|
# In, Out and Inject are objects instantiated when using the DSL, for instance {In() => [:model]}.
|
214
|
-
class In < Tuple
|
215
|
-
|
130
|
+
class In < Tuple
|
131
|
+
class FiltersBuilder
|
132
|
+
def self.call(user_filter, add_variables_class:, add_variables_class_for_callable:, type: :In, **options)
|
133
|
+
# In()/Out() => {:user => :current_user}
|
134
|
+
if user_filter.is_a?(Hash)
|
135
|
+
# For In(): build {SetVariable} filters.
|
136
|
+
# For Out(): build {SetVariable::Output} filters.
|
137
|
+
return Filter.build_filters_for_hash(user_filter, add_variables_class: add_variables_class) do |options, from_name, to_name|
|
138
|
+
options.merge(
|
139
|
+
name: Filter.name_for(type, "#{from_name.inspect}>#{to_name.inspect}"),
|
140
|
+
read_name: from_name,
|
141
|
+
write_name: to_name,
|
142
|
+
)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# In()/Out() => [:current_user]
|
147
|
+
if user_filter.is_a?(Array)
|
148
|
+
user_filter = Filter.hash_for(user_filter)
|
149
|
+
|
150
|
+
return Filter.build_filters_for_hash(user_filter, add_variables_class: add_variables_class) do |options, from_name, _|
|
151
|
+
options.merge(
|
152
|
+
name: Filter.name_for(type, from_name.inspect),
|
153
|
+
write_name: from_name,
|
154
|
+
read_name: from_name,
|
155
|
+
)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
# callable, producing a hash!
|
160
|
+
build_for_option(
|
161
|
+
user_filter,
|
162
|
+
name: Filter.name_for(type, user_filter.object_id, :add_variables),
|
163
|
+
write_name: nil,
|
164
|
+
read_name: nil,
|
165
|
+
add_variables_class: add_variables_class_for_callable, # for example, {AddVariables::Output}
|
166
|
+
**options
|
167
|
+
)
|
168
|
+
# TODO: remove {add_variables_class_for_callable} and make everything SetVariable.
|
169
|
+
end # call
|
170
|
+
|
171
|
+
# Simply invoke user's filter.
|
172
|
+
# Use this for filters without condition and default.
|
173
|
+
def self.build_for_option(user_filter, **options)
|
174
|
+
filter = Activity::Circuit.Step(user_filter, option: true)
|
175
|
+
|
176
|
+
[
|
177
|
+
Filter.build(
|
178
|
+
filter: filter,
|
179
|
+
user_filter: user_filter,
|
180
|
+
**options
|
181
|
+
)
|
182
|
+
]
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end # In
|
186
|
+
|
187
|
+
class Out < Tuple
|
188
|
+
class FiltersBuilder
|
189
|
+
def self.call(user_filter, with_outer_ctx:, **options)
|
190
|
+
if with_outer_ctx
|
191
|
+
callable = user_filter # FIXME: :instance_method
|
192
|
+
call_method = callable.respond_to?(:arity) ? callable : callable.method(:call)
|
193
|
+
|
194
|
+
options =
|
195
|
+
# TODO: remove {if} and only leave {else}.
|
196
|
+
if call_method.arity == 3
|
197
|
+
Activity::Deprecate.warn Linear::Deprecate.dsl_caller_location,
|
198
|
+
"The positional argument `outer_ctx` is deprecated, please use the `:outer_ctx` keyword argument.\n#{VariableMapping.deprecation_link}"
|
199
|
+
|
200
|
+
options.merge(
|
201
|
+
filter: Trailblazer::Option(user_filter),
|
202
|
+
add_variables_class_for_callable: AddVariables::Output::WithOuterContext_Deprecated, # old positional arg
|
203
|
+
)
|
204
|
+
else
|
205
|
+
options.merge(
|
206
|
+
add_variables_class_for_callable: AddVariables::Output::WithOuterContext,
|
207
|
+
)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
In::FiltersBuilder.(user_filter, type: :Out, **options)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end # Out
|
216
215
|
|
217
|
-
def self.In(
|
218
|
-
In.new(
|
216
|
+
def self.In(variable_name = nil, add_variables_class: SetVariable, filter_builder: In::FiltersBuilder, add_variables_class_for_callable: AddVariables)
|
217
|
+
In.new(variable_name, add_variables_class, filter_builder, add_variables_class_for_callable)
|
219
218
|
end
|
220
219
|
|
221
220
|
# Builder for a DSL Output() object.
|
222
|
-
def self.Out(
|
223
|
-
add_variables_class =
|
224
|
-
add_variables_class =
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
221
|
+
def self.Out(variable_name = nil, add_variables_class: SetVariable::Output, with_outer_ctx: false, delete: false, filter_builder: Out::FiltersBuilder, read_from_aggregate: false, add_variables_class_for_callable: AddVariables::Output)
|
222
|
+
add_variables_class = SetVariable::Output::Delete if delete
|
223
|
+
add_variables_class = SetVariable::ReadFromAggregate if read_from_aggregate
|
224
|
+
|
225
|
+
Out.new(
|
226
|
+
variable_name,
|
227
|
+
add_variables_class,
|
228
|
+
filter_builder,
|
229
|
+
add_variables_class_for_callable,
|
230
|
+
with_outer_ctx: with_outer_ctx,
|
231
|
+
)
|
229
232
|
end
|
230
233
|
|
231
|
-
|
232
|
-
|
234
|
+
# Used in the DSL by you.
|
235
|
+
def self.Inject(variable_name = nil, override: false, **)
|
236
|
+
Inject.new(
|
237
|
+
variable_name,
|
238
|
+
nil, # add_variables_class # DISCUSS: do we really want that here?
|
239
|
+
Inject::FiltersBuilder,
|
240
|
+
nil,
|
241
|
+
override: override,
|
242
|
+
)
|
233
243
|
end
|
234
244
|
|
235
245
|
# This class is supposed to hold configuration options for Inject().
|
236
|
-
class Inject
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
246
|
+
class Inject < Tuple
|
247
|
+
class FiltersBuilder
|
248
|
+
# Called via {Tuple#call}
|
249
|
+
def self.call(user_filter, add_variables_class:, variable_name:, **options)
|
250
|
+
# Build {SetVariable::Default}
|
251
|
+
if user_filter.is_a?(Hash) # TODO: deprecate in favor if {Inject(:variable_name)}!
|
252
|
+
return Filter.build_filters_for_hash(user_filter, add_variables_class: SetVariable::Default) do |options, from_name, user_proc|
|
253
|
+
options_with_condition_for_defaulted(
|
254
|
+
**options,
|
255
|
+
user_filter: user_proc,
|
256
|
+
write_name: from_name,
|
257
|
+
read_name: from_name,
|
258
|
+
)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
# Build {SetVariable::Conditioned}
|
263
|
+
if user_filter.is_a?(Array)
|
264
|
+
user_filter = Filter.hash_for(user_filter)
|
265
|
+
|
266
|
+
return Filter.build_filters_for_hash(user_filter, add_variables_class: SetVariable::Conditioned) do |options, from_name, _|
|
267
|
+
options_with_condition(
|
268
|
+
**options,
|
269
|
+
write_name: from_name,
|
270
|
+
read_name: from_name,
|
271
|
+
user_filter: user_filter, # FIXME: this is not really helpful, it's something like [:field, :injects]
|
272
|
+
)
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
if options[:override]
|
277
|
+
return In::FiltersBuilder.build_for_option(
|
278
|
+
user_filter,
|
279
|
+
name: Filter.name_for(:Inject, variable_name, :add_variables),
|
280
|
+
write_name: variable_name,
|
281
|
+
read_name: nil,
|
282
|
+
add_variables_class: SetVariable,
|
283
|
+
**options
|
284
|
+
)
|
285
|
+
end
|
286
|
+
|
287
|
+
# Build {SetVariable::Default}
|
288
|
+
# {user_filter} is one of the following
|
289
|
+
# :instance_method
|
290
|
+
options = options_with_condition_for_defaulted(
|
291
|
+
**options,
|
292
|
+
write_name: variable_name,
|
293
|
+
read_name: variable_name,
|
294
|
+
user_filter: user_filter,
|
295
|
+
)
|
296
|
+
|
297
|
+
[
|
298
|
+
Filter.build_for_reading(add_variables_class: SetVariable::Default, **options)
|
299
|
+
]
|
300
|
+
end # call
|
301
|
+
|
302
|
+
def self.options_with_condition(user_filter:, write_name:, name_specifier: nil, **options)
|
303
|
+
{
|
304
|
+
name: Filter.name_for(:Inject, write_name.inspect, name_specifier),
|
305
|
+
**options,
|
306
|
+
condition: VariablePresent.new(variable_name: write_name),
|
307
|
+
write_name: write_name,
|
308
|
+
user_filter: user_filter,
|
309
|
+
}
|
310
|
+
end
|
244
311
|
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
312
|
+
def self.options_with_condition_for_defaulted(user_filter:, **options)
|
313
|
+
default_filter = Activity::Circuit.Step(user_filter, option: true) # this is passed into {SetVariable.new}.
|
314
|
+
|
315
|
+
options_with_condition(
|
316
|
+
**options,
|
317
|
+
user_filter: user_filter,
|
318
|
+
name_specifier: :default,
|
319
|
+
default_filter: default_filter,
|
320
|
+
)
|
321
|
+
end
|
322
|
+
end # FiltersBuilder
|
323
|
+
end # Inject
|
324
|
+
|
325
|
+
# DISCUSS: generic, again
|
326
|
+
module Filter
|
327
|
+
def self.build(add_variables_class:, **options)
|
328
|
+
add_variables_class.new(
|
329
|
+
**options,
|
330
|
+
)
|
251
331
|
end
|
252
332
|
|
253
|
-
|
254
|
-
|
255
|
-
user_filter.collect do |name|
|
256
|
-
inject_filter = ->(original_ctx, **) { original_ctx.key?(name) ? {name => original_ctx[name]} : {} } # FIXME: make me an {Inject::} method.
|
333
|
+
def self.build_for_reading(read_name:, **options)
|
334
|
+
circuit_step_filter = VariableFromCtx.new(variable_name: read_name) # Activity::Circuit.Step(filter, option: true) # this is passed into {SetVariable.new}.
|
257
335
|
|
258
|
-
|
259
|
-
|
336
|
+
build(
|
337
|
+
filter: circuit_step_filter,
|
338
|
+
**options
|
339
|
+
)
|
260
340
|
end
|
261
341
|
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
inject_filter = ->(original_ctx, **kws) { original_ctx.key?(name) ? {name => original_ctx[name]} : {name => defaulting_filter.(original_ctx, **kws)} }
|
342
|
+
def self.build_filters_for_hash(user_filter, **options)
|
343
|
+
user_filter.collect do |from_name, to_name|
|
344
|
+
options = yield(options, from_name, to_name)
|
266
345
|
|
267
|
-
|
346
|
+
Filter.build_for_reading(
|
347
|
+
user_filter: user_filter,
|
348
|
+
**options,
|
349
|
+
)
|
268
350
|
end
|
269
351
|
end
|
270
352
|
|
271
|
-
def self.
|
272
|
-
|
353
|
+
def self.hash_for(ary)
|
354
|
+
ary.collect { |name| [name, name] }.to_h
|
273
355
|
end
|
274
|
-
end
|
275
356
|
|
357
|
+
def self.name_for(type, name, specifier = nil)
|
358
|
+
[type, specifier].compact.join(".") + "{#{name}}"
|
359
|
+
end
|
360
|
+
end # Filter
|
276
361
|
end # DSL
|
277
362
|
end
|
278
363
|
end
|