Class: Foobara::Value::Processor
- Inherits:
-
Object
- Object
- Foobara::Value::Processor
show all
- Includes:
- IsManifestable, Manifestable
- Defined in:
- foobara-0.0.110/projects/value/src/processor.rb,
foobara-0.0.110/projects/value/src/processor/multi.rb,
foobara-0.0.110/projects/value/src/processor/runner.rb,
foobara-0.0.110/projects/value/src/processor/casting.rb,
foobara-0.0.110/projects/value/src/processor/pipeline.rb,
foobara-0.0.110/projects/value/src/processor/selection.rb
Defined Under Namespace
Modules: Priority
Classes: Casting, Multi, Pipeline, Runner, Selection
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
#foobara_domain, #foobara_organization, #scoped_clear_caches
Methods included from Concern
foobara_class_methods_module_for, foobara_concern?, included
Constructor Details
#initialize(*args) ⇒ Processor
Returns a new instance of Processor.
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 147
def initialize(*args)
unless Foobara::Namespace.current == Foobara
self.created_in_namespace = Foobara::Namespace.current
end
expected_arg_count = requires_declaration_data? ? 1 : 0
expected_arg_count += 1 if requires_parent_declaration_data?
unless expected_arg_count == args.count
raise ArgumentError, "#{name} expected #{expected_arg_count} received #{args.count}"
end
if requires_declaration_data?
self.declaration_data = args.shift
end
if requires_parent_declaration_data?
self.parent_declaration_data = args.first
end
end
|
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args, **opts) ⇒ Object
351
352
353
354
355
356
357
358
359
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 351
def method_missing(method, *args, **opts)
if method == symbol
declaration_data
else
super
end
end
|
Instance Attribute Details
#created_in_namespace ⇒ Object
171
172
173
174
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 171
def created_in_namespace
@created_in_namespace ||= GlobalDomain
end
|
#declaration_data ⇒ Object
Returns the value of attribute declaration_data.
144
145
146
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 144
def declaration_data
@declaration_data
end
|
#parent_declaration_data ⇒ Object
Returns the value of attribute parent_declaration_data.
144
145
146
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 144
def parent_declaration_data
@parent_declaration_data
end
|
Class Method Details
.default_declaration_data ⇒ Object
24
25
26
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 24
def default_declaration_data
true
end
|
.error_class ⇒ Object
119
120
121
122
123
124
125
126
127
128
129
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 119
def error_class
return @error_class if defined?(@error_class)
unless error_classes.size == 1
raise "Expected exactly one error class to be defined for #{name} but has #{error_classes.size}"
end
@error_class = error_classes.first
end
|
.error_classes ⇒ Object
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 95
def error_classes
@error_classes ||= begin
error_klasses = Util.constant_values(self, extends: Foobara::Error)
error_klasses2 = if is_a?(Foobara::Namespace::IsNamespace)
foobara_all_error(mode: Namespace::LookupMode::DIRECT)
end
if error_klasses.sort_by(&:name) != error_klasses2.sort_by(&:name)
raise "Expected #{error_klasses} to equal #{error_klasses2} for #{name}"
end
if superclass < Processor
error_klasses2 += superclass.error_classes
end
error_klasses2
end
end
|
.foobara_manifest ⇒ Object
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 28
def foobara_manifest
to_include = TypeDeclarations.foobara_manifest_context_to_include
errors = error_classes.map do |error_class|
if to_include
to_include << error_class
end
error_class.foobara_manifest_reference
end
manifest = super.merge(
name: processor_name,
processor_type: :processor
)
unless errors.empty?
manifest[:error_classes] = errors.sort
end
manifest
end
|
.instance ⇒ Object
83
84
85
86
87
88
89
90
91
92
93
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 83
def instance
@instance ||= begin
if requires_parent_declaration_data?
raise "Cannot treat processors dependent on parent declaration data as singletons"
end
requires_declaration_data? ? new(default_declaration_data) : new
end
end
|
.new_with_agnostic_args(**rest) ⇒ Object
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 50
def new_with_agnostic_args(**rest)
allowed_keys = %i[declaration_data parent_declaration_data]
invalid_keys = rest.keys - allowed_keys
unless invalid_keys.empty?
raise ArgumentError, "Invalid keys: #{invalid_keys.join(", ")} expected one of #{allowed_keys.join(", ")}"
end
args = []
if requires_declaration_data?
args << if rest.key?(:declaration_data)
rest[:declaration_data]
else
default_declaration_data
end
end
if requires_parent_declaration_data?
args << rest[:parent_declaration_data] if requires_parent_declaration_data?
end
if args.empty? || args == [default_declaration_data]
instance
else
new(*args)
end
end
|
.processor_name ⇒ Object
20
21
22
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 20
def processor_name
name || "Anonymous"
end
|
.requires_declaration_data? ⇒ Boolean
135
136
137
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 135
def requires_declaration_data?
true
end
|
.requires_parent_declaration_data? ⇒ Boolean
139
140
141
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 139
def requires_parent_declaration_data?
false
end
|
.symbol ⇒ Object
131
132
133
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 131
def symbol
@symbol ||= Util.non_full_name_underscore(self)&.gsub(/_(processor|transformer|validator)$/, "")&.to_sym
end
|
Instance Method Details
#always_applicable? ⇒ Boolean
This means it’s applicable regardless of value to transform. Override if different behavior is needed.
216
217
218
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 216
def always_applicable?
!!declaration_data
end
|
#applicable?(_value) ⇒ Boolean
A transformer with no declaration data or with declaration data of false is considered to be not applicable. Override this wherever different behavior is needed.
211
212
213
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 211
def applicable?(_value)
always_applicable?
end
|
#attribute_name ⇒ Object
TODO: this is a bit problematic. Maybe eliminate this instead of assuming it’s generally useful
276
277
278
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 276
def attribute_name
nil
end
|
#build_error(value = nil, error_class: self.error_class, symbol: error_class.symbol, message: error_message(value), context: error_context(value), path: error_path) ⇒ Object
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 246
def build_error(
value = nil,
error_class: self.error_class,
symbol: error_class.symbol,
message: error_message(value),
context: error_context(value),
path: error_path,
**
)
unless error_classes.include?(error_class)
raise "invalid error"
end
error_class.new(
path:,
message:,
context:,
symbol:,
**
)
end
|
#dup_processor(**opts) ⇒ Object
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 285
def dup_processor(**opts)
valid_opts = %i[declaration_data parent_declaration_data]
invalid_opts = opts.keys - valid_opts
unless invalid_opts.empty?
raise ArgumentError, "Invalid opts #{invalid_opts.inspect} expected only #{valid_opts.inspect}"
end
declaration_data = if opts.key?(:declaration_data)
opts[:declaration_data]
else
self.declaration_data
end
parent_declaration_data = if opts.key?(:parent_declaration_data)
opts[:parent_declaration_data]
else
self.parent_declaration_data
end
self.class.new_with_agnostic_args(declaration_data:, parent_declaration_data:)
end
|
#error_context(_value) ⇒ Object
197
198
199
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 197
def error_context(_value)
error_class.context
end
|
#error_message(_value) ⇒ Object
TODO: probably actually better to pass it through to the error class method. Bring that back.
193
194
195
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 193
def error_message(_value)
error_class.message
end
|
#error_path ⇒ Object
TODO: does this make sense to have something called attribute_name here??
271
272
273
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 271
def error_path
Util.array(attribute_name)
end
|
#foobara_manifest ⇒ Object
TODO: is this in the wrong place? Should this be an extension?
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 324
def foobara_manifest
to_include = TypeDeclarations.foobara_manifest_context_to_include
possible_errors = self.possible_errors.map do |possible_error|
[possible_error.key.to_s, possible_error.foobara_manifest]
end
manifest = super.dup
if scoped_category == :processor
if to_include
to_include << self.class
end
manifest[:processor_class] = self.class.foobara_manifest_reference
end
if requires_declaration_data?
manifest[:declaration_data] = declaration_data
end
unless possible_errors.empty?
manifest[:possible_errors] = possible_errors.sort.to_h
end
manifest
end
|
#inspect ⇒ Object
310
311
312
313
314
315
316
317
318
319
320
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 310
def inspect
s = super
if s.size > 400
s = "#{s[0..400]}..."
end
s
end
|
#name ⇒ Object
176
177
178
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 176
def name
self.class.processor_name
end
|
#possible_errors ⇒ Object
201
202
203
204
205
206
207
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 201
def possible_errors
Foobara::Namespace.use created_in_namespace do
error_classes.map do |error_class|
PossibleError.new(error_class, processor: self)
end
end
end
|
#priority ⇒ Object
Helps control when it runs in a pipeline
281
282
283
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 281
def priority
Priority::MEDIUM
end
|
#process_outcome(old_outcome) ⇒ Object
230
231
232
233
234
235
236
237
238
239
240
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 230
def process_outcome(old_outcome)
return old_outcome if old_outcome.fatal?
value = old_outcome.result
return old_outcome unless applicable?(value)
process_value(value).tap do |outcome|
outcome.add_errors(old_outcome.errors)
end
end
|
#process_outcome!(old_outcome) ⇒ Object
242
243
244
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 242
def process_outcome!(old_outcome)
process_outcome(old_outcome).result!
end
|
#process_value(_value) ⇒ Object
220
221
222
223
224
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 220
def process_value(_value)
raise "subclass responsibility"
end
|
#process_value!(value) ⇒ Object
226
227
228
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 226
def process_value!(value)
process_value(value).result!
end
|
#respond_to_missing?(method, private = false) ⇒ Boolean
361
362
363
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 361
def respond_to_missing?(method, private = false)
method == symbol || super
end
|
#runner(value) ⇒ Object
Whoa, forgot this existed. Shouldn’t we use this more?
188
189
190
|
# File 'foobara-0.0.110/projects/value/src/processor.rb', line 188
def runner(value)
self.class::Runner.new(self, value)
end
|