foobara 0.1.7 → 0.1.8
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/CHANGELOG.md +5 -0
- data/projects/callback/src/block/concerns/block_parameter_not_allowed.rb +3 -3
- data/projects/callback/src/block/concerns/type.rb +2 -0
- data/projects/callback/src/block.rb +4 -2
- data/projects/entity/src/extensions/builtin_types/entity/casters/record_from_closed_transaction.rb +26 -0
- data/projects/entity/src/extensions/builtin_types/entity/casters/record_from_current_transaction.rb +22 -0
- data/projects/entity/src/extensions/type_declarations/handlers/extend_entity_type_declaration/to_type_transformer.rb +2 -3
- data/projects/types/src/type.rb +106 -28
- data/projects/value/src/processor/casting.rb +21 -39
- data/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 497323362ef9b9bcf4a7d17cb9400b84701e73dc464f3ff318e6a52b6ee3bbf6
|
4
|
+
data.tar.gz: ee7bc81ea47e850b90e569c4295bd914832c3604277790edd6db153e143515a6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: acc9a5fed9bdfa6f7c19d74652b6c2bf770a24c17880968dc476289d2231ea51b906c538ee3d10dc65365c74d9d97f9f747ae3c97400789ce30e60babc9ca6b2
|
7
|
+
data.tar.gz: 03225ae2b838efc6816fe072b0f94ea6193552bb1253159aaa749ec471c18d4ea821c399cba711f6f6246cf1c38686d398bb4cd5c6385daebf91014a3ab88436
|
data/CHANGELOG.md
CHANGED
@@ -3,15 +3,15 @@ module Foobara
|
|
3
3
|
class Block
|
4
4
|
module Concerns
|
5
5
|
module BlockParameterNotAllowed
|
6
|
+
class BlockParameterNotAllowedError < StandardError; end
|
7
|
+
|
6
8
|
private
|
7
9
|
|
8
10
|
def validate_original_block!
|
9
11
|
super
|
10
12
|
|
11
13
|
if takes_block?
|
12
|
-
#
|
13
|
-
raise ArgumentError, "#{type} callback is not allowed to accept a block"
|
14
|
-
# :nocov:
|
14
|
+
raise BlockParameterNotAllowedError, "#{type} callback is not allowed to accept a block"
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
@@ -6,6 +6,8 @@ module Foobara
|
|
6
6
|
include Concern
|
7
7
|
|
8
8
|
module ClassMethods
|
9
|
+
# TODO: consider renaming this to symbol? Could be confused with Foobara::Type concept
|
10
|
+
# Returns things like :before, :after, :around, :error to indicate what type of callback it is
|
9
11
|
def type
|
10
12
|
@type ||= Util.non_full_name_underscore(self)&.gsub(/_block$/, "")&.to_sym
|
11
13
|
end
|
@@ -26,7 +26,9 @@ module Foobara
|
|
26
26
|
validate_original_block!
|
27
27
|
end
|
28
28
|
|
29
|
-
|
29
|
+
def type
|
30
|
+
self.class.type
|
31
|
+
end
|
30
32
|
|
31
33
|
def call(...)
|
32
34
|
to_proc.call(...)
|
@@ -48,7 +50,7 @@ module Foobara
|
|
48
50
|
end
|
49
51
|
|
50
52
|
def takes_block?
|
51
|
-
@takes_block ||= original_block.parameters.last&.first&.==(:block)
|
53
|
+
@takes_block ||= original_block.parameters.last&.first&.==(:block) || false
|
52
54
|
end
|
53
55
|
|
54
56
|
def has_one_or_zero_positional_args?
|
data/projects/entity/src/extensions/builtin_types/entity/casters/record_from_closed_transaction.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative "primary_key"
|
2
|
+
|
3
|
+
module Foobara
|
4
|
+
module BuiltinTypes
|
5
|
+
module Entity
|
6
|
+
module Casters
|
7
|
+
class RecordFromClosedTransaction < PrimaryKey
|
8
|
+
def applicable?(value)
|
9
|
+
if value.is_a?(entity_class) && value.persisted?
|
10
|
+
tx = value.class.entity_base.current_transaction
|
11
|
+
|
12
|
+
if tx&.currently_open?
|
13
|
+
# TODO: might be safer/more performant to store the transaction on the record?
|
14
|
+
!value.class.entity_base.current_transaction.tracking?(value)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def transform(record)
|
20
|
+
super(record.primary_key)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/projects/entity/src/extensions/builtin_types/entity/casters/record_from_current_transaction.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative "primary_key"
|
2
|
+
|
3
|
+
module Foobara
|
4
|
+
module BuiltinTypes
|
5
|
+
module Entity
|
6
|
+
module Casters
|
7
|
+
class RecordFromCurrentTransaction < PrimaryKey
|
8
|
+
def applicable?(value)
|
9
|
+
if value.is_a?(entity_class)
|
10
|
+
tx = entity_class.entity_base.current_transaction
|
11
|
+
!tx&.currently_open? || tx.tracking?(value)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def transform(record)
|
16
|
+
record
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -7,12 +7,11 @@ module Foobara
|
|
7
7
|
super.tap do |outcome|
|
8
8
|
if outcome.success?
|
9
9
|
type = outcome.result
|
10
|
+
type.cast_even_if_instance_of_target_type = true
|
10
11
|
entity_class = type.target_class
|
11
12
|
|
12
13
|
unless entity_class.can_be_created_through_casting?
|
13
|
-
type.
|
14
|
-
caster.is_a?(Foobara::BuiltinTypes::Entity::Casters::Hash)
|
15
|
-
end
|
14
|
+
type.remove_caster_instances_of(Foobara::BuiltinTypes::Entity::Casters::Hash)
|
16
15
|
end
|
17
16
|
end
|
18
17
|
end
|
data/projects/types/src/type.rb
CHANGED
@@ -15,20 +15,21 @@ module Foobara
|
|
15
15
|
end
|
16
16
|
|
17
17
|
attr_accessor :base_type,
|
18
|
-
:casters,
|
19
|
-
:transformers,
|
20
|
-
:validators,
|
21
|
-
:element_processors,
|
22
18
|
:structure_count,
|
23
19
|
:is_builtin,
|
24
20
|
:name,
|
25
|
-
:target_classes,
|
26
21
|
:description,
|
27
22
|
:sensitive,
|
28
|
-
:sensitive_exposed
|
29
|
-
:processor_classes_requiring_type
|
23
|
+
:sensitive_exposed
|
30
24
|
|
31
|
-
attr_reader :type_symbol
|
25
|
+
attr_reader :type_symbol,
|
26
|
+
:casters,
|
27
|
+
:transformers,
|
28
|
+
:validators,
|
29
|
+
:target_classes,
|
30
|
+
:processor_classes_requiring_type,
|
31
|
+
:element_processors,
|
32
|
+
:cast_even_if_instance_of_target_type
|
32
33
|
|
33
34
|
attr_writer :element_types,
|
34
35
|
:element_type
|
@@ -168,9 +169,34 @@ module Foobara
|
|
168
169
|
category.delete_if { |p| p.symbol == symbol }
|
169
170
|
|
170
171
|
category << processor
|
172
|
+
clear_caches
|
171
173
|
end
|
172
174
|
end
|
173
175
|
|
176
|
+
def clear_caches
|
177
|
+
[
|
178
|
+
:@value_validator,
|
179
|
+
:@processors,
|
180
|
+
:@value_caster,
|
181
|
+
:@value_transformer,
|
182
|
+
:@element_processor,
|
183
|
+
:@possible_errors,
|
184
|
+
:@processors_without_casters
|
185
|
+
].each do |instance_variable|
|
186
|
+
if instance_variable_defined?(instance_variable)
|
187
|
+
remove_instance_variable(instance_variable)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def remove_caster_instances_of(klass)
|
193
|
+
self.casters = casters.reject do |caster|
|
194
|
+
caster.is_a?(klass)
|
195
|
+
end
|
196
|
+
|
197
|
+
clear_caches
|
198
|
+
end
|
199
|
+
|
174
200
|
def remove_processor_by_symbol(symbol)
|
175
201
|
[
|
176
202
|
casters,
|
@@ -184,6 +210,7 @@ module Foobara
|
|
184
210
|
end
|
185
211
|
supported_processor_classes&.each { |processor_hash| processor_hash.delete(symbol) }
|
186
212
|
processor_classes_requiring_type&.delete_if { |p| p.symbol == symbol }
|
213
|
+
clear_caches
|
187
214
|
end
|
188
215
|
|
189
216
|
def each_processor_class_requiring_type(&block)
|
@@ -218,6 +245,8 @@ module Foobara
|
|
218
245
|
end
|
219
246
|
end
|
220
247
|
end
|
248
|
+
|
249
|
+
clear_caches
|
221
250
|
end
|
222
251
|
|
223
252
|
def target_class
|
@@ -299,11 +328,52 @@ module Foobara
|
|
299
328
|
base_type&.extends_type?(type)
|
300
329
|
end
|
301
330
|
|
331
|
+
def processors=(...)
|
332
|
+
clear_caches
|
333
|
+
super
|
334
|
+
end
|
335
|
+
|
302
336
|
def type_symbol=(type_symbol)
|
303
337
|
@scoped_path ||= type_symbol.to_s.split("::")
|
338
|
+
clear_caches
|
304
339
|
@type_symbol = type_symbol.to_sym
|
305
340
|
end
|
306
341
|
|
342
|
+
def cast_even_if_instance_of_target_type=(flag)
|
343
|
+
clear_caches
|
344
|
+
@cast_even_if_instance_of_target_type = flag
|
345
|
+
end
|
346
|
+
|
347
|
+
def casters=(processors)
|
348
|
+
clear_caches
|
349
|
+
@casters = processors
|
350
|
+
end
|
351
|
+
|
352
|
+
def transformers=(processors)
|
353
|
+
clear_caches
|
354
|
+
@transformers = processors
|
355
|
+
end
|
356
|
+
|
357
|
+
def validators=(processors)
|
358
|
+
clear_caches
|
359
|
+
@validators = processors
|
360
|
+
end
|
361
|
+
|
362
|
+
def target_classes=(processors)
|
363
|
+
clear_caches
|
364
|
+
@target_classes = processors
|
365
|
+
end
|
366
|
+
|
367
|
+
def processor_classes_requiring_type=(processors)
|
368
|
+
clear_caches
|
369
|
+
@processor_classes_requiring_type = processors
|
370
|
+
end
|
371
|
+
|
372
|
+
def element_processors=(processors)
|
373
|
+
clear_caches
|
374
|
+
@element_processors = processors
|
375
|
+
end
|
376
|
+
|
307
377
|
def full_type_symbol
|
308
378
|
return @full_type_symbol if defined?(@full_type_symbol)
|
309
379
|
|
@@ -313,17 +383,16 @@ module Foobara
|
|
313
383
|
end
|
314
384
|
|
315
385
|
def processors
|
316
|
-
[
|
386
|
+
@processors ||= [
|
317
387
|
value_caster,
|
318
388
|
value_transformer,
|
319
389
|
value_validator,
|
320
390
|
element_processor
|
321
|
-
].compact
|
391
|
+
].compact.sort_by(&:priority)
|
322
392
|
end
|
323
393
|
|
324
394
|
def value_caster
|
325
|
-
|
326
|
-
# return @value_caster if defined?(@value_caster)
|
395
|
+
return @value_caster if defined?(@value_caster)
|
327
396
|
|
328
397
|
# We make this exception for :duck because it will match any instance of
|
329
398
|
# Object but AllowNil will match nil which is also an instance of Object.
|
@@ -335,16 +404,19 @@ module Foobara
|
|
335
404
|
true
|
336
405
|
end
|
337
406
|
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
407
|
+
Namespace.use created_in_namespace do
|
408
|
+
@value_caster = Value::Processor::Casting.new(
|
409
|
+
{ cast_to: reference_or_declaration_data },
|
410
|
+
casters:,
|
411
|
+
target_classes:,
|
412
|
+
enforce_unique:,
|
413
|
+
cast_even_if_instance_of_target_type:
|
414
|
+
)
|
415
|
+
end
|
344
416
|
end
|
345
417
|
|
346
418
|
def applicable?(value)
|
347
|
-
value_caster.can_cast?(value)
|
419
|
+
!value_caster.needs_cast?(value) || value_caster.can_cast?(value)
|
348
420
|
end
|
349
421
|
|
350
422
|
foobara_delegate :needs_cast?, to: :value_caster
|
@@ -362,24 +434,30 @@ module Foobara
|
|
362
434
|
# method in the instance of the processor as needed. This means it can't really memoize stuff. Should we create
|
363
435
|
# an instance of something from the instance of the processor and then ask it questions?? TODO: try this
|
364
436
|
def value_transformer
|
365
|
-
|
366
|
-
|
367
|
-
|
437
|
+
return @value_transformer if defined?(@value_transformer)
|
438
|
+
|
439
|
+
@value_transformer = if transformers && !transformers.empty?
|
440
|
+
Value::Processor::Pipeline.new(processors: transformers)
|
441
|
+
end
|
368
442
|
end
|
369
443
|
|
370
444
|
# TODO: figure out how to safely memoize stuff so like this for performance reasons
|
371
445
|
# A good way, but potentially a decent amount of work, is to have a class that takes value to its initialize
|
372
446
|
# method.
|
373
447
|
def value_validator
|
374
|
-
|
375
|
-
|
376
|
-
|
448
|
+
return @value_validator if defined?(@value_validator)
|
449
|
+
|
450
|
+
@value_validator = if validators && !validators.empty?
|
451
|
+
Value::Processor::Pipeline.new(processors: validators)
|
452
|
+
end
|
377
453
|
end
|
378
454
|
|
379
455
|
def element_processor
|
380
|
-
|
381
|
-
|
382
|
-
|
456
|
+
return @element_processor if defined?(@element_processor)
|
457
|
+
|
458
|
+
@element_processor = if element_processors && !element_processors.empty?
|
459
|
+
Value::Processor::Pipeline.new(processors: element_processors)
|
460
|
+
end
|
383
461
|
end
|
384
462
|
|
385
463
|
# TODO: some way of memoizing these values? Would need to introduce a new class that takes the value to its
|
@@ -37,57 +37,34 @@ module Foobara
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
attr_accessor :target_classes
|
40
|
+
attr_accessor :target_classes, :cast_even_if_instance_of_target_type
|
41
41
|
|
42
|
-
def initialize(*, casters:, target_classes: nil, **)
|
42
|
+
def initialize(*, casters:, target_classes: nil, cast_even_if_instance_of_target_type: nil, **)
|
43
43
|
self.target_classes = Util.array(target_classes)
|
44
44
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
45
|
+
if cast_even_if_instance_of_target_type
|
46
|
+
self.cast_even_if_instance_of_target_type = true
|
47
|
+
end
|
48
|
+
|
49
|
+
super(*, processors: casters, **)
|
50
|
+
end
|
49
51
|
|
50
|
-
|
52
|
+
def process_value(value)
|
53
|
+
if cast_even_if_instance_of_target_type || needs_cast?(value)
|
54
|
+
super
|
55
|
+
else
|
56
|
+
Outcome.success(value)
|
57
|
+
end
|
51
58
|
end
|
52
59
|
|
53
60
|
def needs_cast?(value)
|
54
|
-
|
61
|
+
target_classes.none? { |klass| value.is_a?(klass) }
|
55
62
|
end
|
56
63
|
|
57
64
|
def can_cast?(value)
|
58
65
|
processors.any? { |processor| processor.applicable?(value) }
|
59
66
|
end
|
60
67
|
|
61
|
-
def does_not_need_cast_processor
|
62
|
-
return @does_not_need_cast_processor if defined?(@does_not_need_cast_processor)
|
63
|
-
|
64
|
-
errorified_name = target_classes.map do |c|
|
65
|
-
if c.name
|
66
|
-
c.name
|
67
|
-
elsif c.respond_to?(:foobara_name)
|
68
|
-
c.foobara_name
|
69
|
-
else
|
70
|
-
# TODO: test this code path
|
71
|
-
# :nocov:
|
72
|
-
"Anon"
|
73
|
-
# :nocov:
|
74
|
-
end
|
75
|
-
end.map { |name| name.split("::").last }.sort.join("Or")
|
76
|
-
|
77
|
-
class_name = "NoCastNeededIfIsA#{errorified_name}"
|
78
|
-
|
79
|
-
@does_not_need_cast_processor = if target_classes && !target_classes.empty?
|
80
|
-
Caster.subclass(
|
81
|
-
name: class_name,
|
82
|
-
applicable?: ->(value) {
|
83
|
-
target_classes.any? { |target_class| value.is_a?(target_class) }
|
84
|
-
},
|
85
|
-
applies_message: "be a #{target_classes.map(&:name).join(" or ")}",
|
86
|
-
cast: ->(value) { value }
|
87
|
-
).instance
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
68
|
def error_message(value)
|
92
69
|
type = declaration_data[:cast_to]
|
93
70
|
|
@@ -101,7 +78,12 @@ module Foobara
|
|
101
78
|
end
|
102
79
|
|
103
80
|
def applies_message
|
104
|
-
Util.to_or_sentence(
|
81
|
+
Util.to_or_sentence(
|
82
|
+
[
|
83
|
+
"be a #{target_classes.map(&:name).join(" or ")}",
|
84
|
+
*processors.map(&:applies_message).flatten
|
85
|
+
]
|
86
|
+
)
|
105
87
|
end
|
106
88
|
|
107
89
|
def error_context(value)
|
data/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foobara
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Miles Georgi
|
@@ -304,6 +304,8 @@ files:
|
|
304
304
|
- projects/entity/src/extensions/builtin_types/entity.rb
|
305
305
|
- projects/entity/src/extensions/builtin_types/entity/casters/hash.rb
|
306
306
|
- projects/entity/src/extensions/builtin_types/entity/casters/primary_key.rb
|
307
|
+
- projects/entity/src/extensions/builtin_types/entity/casters/record_from_closed_transaction.rb
|
308
|
+
- projects/entity/src/extensions/builtin_types/entity/casters/record_from_current_transaction.rb
|
307
309
|
- projects/entity/src/extensions/builtin_types/entity/validators/model_instance_is_valid.rb
|
308
310
|
- projects/entity/src/extensions/type_declarations/handlers/extend_entity_type_declaration.rb
|
309
311
|
- projects/entity/src/extensions/type_declarations/handlers/extend_entity_type_declaration/attributes_handler_desugarizer.rb
|