foobara 0.0.118 → 0.0.120
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 +18 -0
- data/projects/command_connectors/src/command_connector.rb +15 -4
- data/projects/command_connectors/src/command_registry.rb +9 -3
- data/projects/command_connectors/src/serializers/aggregate_serializer.rb +2 -2
- data/projects/command_connectors/src/serializers/entities_to_primary_keys_serializer.rb +2 -2
- data/projects/command_connectors/src/transformed_command.rb +151 -80
- data/projects/detached_entity/src/concerns/equality.rb +2 -0
- data/projects/model/src/sensitive_type_removers/model.rb +22 -5
- data/projects/model/src/sensitive_value_removers/model.rb +5 -1
- data/projects/namespace/src/is_namespace.rb +6 -0
- data/projects/namespace/src/namespace_helpers.rb +30 -3
- data/projects/persistence/src/entity_base/transaction/concerns/entity_callback_handling.rb +2 -0
- data/projects/persistence/src/entity_base/transaction_table/concerns/queries.rb +2 -3
- data/projects/persistence/src/entity_base/transaction_table/concerns/record_tracking.rb +2 -2
- data/projects/persistence/src/entity_base/transaction_table.rb +38 -13
- data/projects/type_declarations/lib/foobara/type_declarations.rb +3 -0
- data/projects/type_declarations/src/attributes_transformers/only.rb +12 -0
- data/projects/type_declarations/src/attributes_transformers/reject.rb +12 -0
- data/projects/type_declarations/src/attributes_transformers.rb +11 -0
- data/projects/type_declarations/src/remove_sensitive_values_transformer.rb +25 -11
- data/projects/type_declarations/src/typed_transformer.rb +1 -1
- data/projects/value/src/processor.rb +6 -0
- data/projects/weak_object_set/src/weak_object_set.rb +164 -93
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: df43aec79b46e3e71fd064c6482bdd5dd6e0af495987d6cea1cdf97311460e91
|
4
|
+
data.tar.gz: 800093b7a126bbca27fa300c4df50b568b329c762ad7a2c68925f4a3d5690090
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6305514bda86178efb70d09cd8ff8d46e404f0407b50189833b9939230cf716a80049afca17ea5071599bfb71f4cd45a660ade570b6bfcec063190e9b3a02096
|
7
|
+
data.tar.gz: 84705a7ff3bd306c13e7cdf5e81a3a960b0e769df51dacf38859a003da408926133c434d9d03ba2a58b70e57946b58d8355da338a0e780cab34f35a3e84df97c
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
# [0.0.120] - 2025-05-11
|
2
|
+
|
3
|
+
- Fix a race condition in persistence
|
4
|
+
- Fix various problems preventing sensitive/private types from being properly removed
|
5
|
+
in exposed types
|
6
|
+
|
7
|
+
# [0.0.119] - 2025-05-08
|
8
|
+
|
9
|
+
- Make anonymous transformers more deterministic in manifests
|
10
|
+
- Remove delegates and private attributes from exposed models
|
11
|
+
- Make sure delegated attributes make it out through aggregate serializers
|
12
|
+
|
13
|
+
# [0.0.118] - 2025-05-07
|
14
|
+
|
15
|
+
- Fix bug preventing allow_nil from being used with entities
|
16
|
+
- Fix bugs with .all and .load
|
17
|
+
- Fix bug with possible error class lookups for tuple types
|
18
|
+
|
1
19
|
# [0.0.117] - 2025-05-05
|
2
20
|
|
3
21
|
- Make sure we do not apply an authenticator unless it is applicable
|
@@ -454,6 +454,13 @@ module Foobara
|
|
454
454
|
end
|
455
455
|
|
456
456
|
def foobara_manifest
|
457
|
+
Namespace.use command_registry do
|
458
|
+
foobara_manifest_in_current_namespace
|
459
|
+
end
|
460
|
+
end
|
461
|
+
|
462
|
+
# TODO: try to break this giant method up
|
463
|
+
def foobara_manifest_in_current_namespace
|
457
464
|
process_delayed_connections
|
458
465
|
|
459
466
|
to_include = Set.new
|
@@ -506,16 +513,20 @@ module Foobara
|
|
506
513
|
else
|
507
514
|
domain_name = o.foobara_domain.scoped_full_name
|
508
515
|
|
509
|
-
unless command_registry.foobara_registered?(domain_name)
|
516
|
+
unless command_registry.foobara_registered?(domain_name, mode: Namespace::LookupMode::ABSOLUTE)
|
510
517
|
command_registry.build_and_register_exposed_domain(domain_name)
|
511
518
|
|
512
519
|
# Since we don't know which other domains/orgs creating this domain might have created,
|
513
520
|
# we will just add them all to be included just in case
|
514
|
-
command_registry.foobara_all_domain
|
521
|
+
command_registry.foobara_all_domain(
|
522
|
+
mode: Namespace::LookupMode::ABSOLUTE
|
523
|
+
).each do |exposed_domain|
|
515
524
|
additional_to_include << exposed_domain
|
516
525
|
end
|
517
526
|
|
518
|
-
command_registry.foobara_all_organization
|
527
|
+
command_registry.foobara_all_organization(
|
528
|
+
mode: Namespace::LookupMode::ABSOLUTE
|
529
|
+
).each do |exposed_organization|
|
519
530
|
additional_to_include << exposed_organization
|
520
531
|
end
|
521
532
|
end
|
@@ -612,7 +623,7 @@ module Foobara
|
|
612
623
|
def all_exposed_commands
|
613
624
|
process_delayed_connections
|
614
625
|
|
615
|
-
command_registry.foobara_all_command
|
626
|
+
command_registry.foobara_all_command(mode: Namespace::LookupMode::ABSOLUTE)
|
616
627
|
end
|
617
628
|
end
|
618
629
|
end
|
@@ -24,6 +24,8 @@ module Foobara
|
|
24
24
|
end
|
25
25
|
|
26
26
|
foobara_add_category_for_instance_of(:command, ExposedCommand)
|
27
|
+
|
28
|
+
foobara_depends_on_namespaces << Namespace.global
|
27
29
|
end
|
28
30
|
|
29
31
|
def register(command_class, **)
|
@@ -32,7 +34,8 @@ module Foobara
|
|
32
34
|
|
33
35
|
def create_exposed_command(command_class, **)
|
34
36
|
full_domain_name = command_class.domain.scoped_full_name
|
35
|
-
exposed_domain = foobara_lookup_domain(full_domain_name) ||
|
37
|
+
exposed_domain = foobara_lookup_domain(full_domain_name, mode: Namespace::LookupMode::ABSOLUTE) ||
|
38
|
+
build_and_register_exposed_domain(full_domain_name)
|
36
39
|
|
37
40
|
exposed_command = create_exposed_command_without_domain(command_class, **)
|
38
41
|
|
@@ -75,8 +78,11 @@ module Foobara
|
|
75
78
|
end
|
76
79
|
|
77
80
|
full_organization_name = domain_module.foobara_full_organization_name
|
78
|
-
|
79
|
-
|
81
|
+
|
82
|
+
exposed_organization = foobara_lookup_organization(
|
83
|
+
full_organization_name,
|
84
|
+
mode: Namespace::LookupMode::ABSOLUTE
|
85
|
+
) || build_and_register_exposed_organization(full_organization_name)
|
80
86
|
|
81
87
|
exposed_domain = Module.new
|
82
88
|
exposed_domain.foobara_namespace!
|
@@ -11,9 +11,9 @@ module Foobara
|
|
11
11
|
object.class.load(object)
|
12
12
|
end
|
13
13
|
|
14
|
-
transform(object.
|
14
|
+
transform(object.attributes_with_delegates)
|
15
15
|
when Model
|
16
|
-
transform(object.
|
16
|
+
transform(object.attributes_with_delegates)
|
17
17
|
when Array
|
18
18
|
object.map { |element| transform(element) }
|
19
19
|
when Hash
|
@@ -14,10 +14,10 @@ module Foobara
|
|
14
14
|
if detached_to_primary_key?
|
15
15
|
object.primary_key
|
16
16
|
else
|
17
|
-
object.
|
17
|
+
object.attributes_with_delegates
|
18
18
|
end
|
19
19
|
when Model
|
20
|
-
object.
|
20
|
+
object.attributes_with_delegates
|
21
21
|
when ::Array
|
22
22
|
object.map { |element| serialize(element) }
|
23
23
|
when ::Hash
|
@@ -3,12 +3,12 @@ module Foobara
|
|
3
3
|
# TODO: move this to command connectors project
|
4
4
|
class TransformedCommand
|
5
5
|
class << self
|
6
|
+
# TODO: handle errors_transformers!
|
7
|
+
attr_writer :result_transformers, :inputs_transformers
|
6
8
|
attr_accessor :command_class,
|
7
9
|
:command_name,
|
8
10
|
:full_command_name,
|
9
11
|
:capture_unknown_error,
|
10
|
-
:inputs_transformers,
|
11
|
-
:result_transformers,
|
12
12
|
:errors_transformers,
|
13
13
|
:pre_commit_transformers,
|
14
14
|
# TODO: get at least these serializers out of here...
|
@@ -20,7 +20,9 @@ module Foobara
|
|
20
20
|
:request_mutators,
|
21
21
|
:allowed_rule,
|
22
22
|
:requires_authentication,
|
23
|
-
:authenticator
|
23
|
+
:authenticator,
|
24
|
+
:subclassed_in_namespace,
|
25
|
+
:suffix
|
24
26
|
|
25
27
|
def subclass(
|
26
28
|
command_class,
|
@@ -40,21 +42,6 @@ module Foobara
|
|
40
42
|
suffix: nil,
|
41
43
|
capture_unknown_error: false
|
42
44
|
)
|
43
|
-
result_type = command_class.result_type
|
44
|
-
|
45
|
-
if result_type&.has_sensitive_types?
|
46
|
-
remover_class = Foobara::TypeDeclarations.sensitive_value_remover_class_for_type(result_type)
|
47
|
-
|
48
|
-
remover = Namespace.use scoped_namespace do
|
49
|
-
transformed_result_type = result_type_from_transformers(result_type, result_transformers)
|
50
|
-
remover_class.new(from: transformed_result_type).tap do |r|
|
51
|
-
r.scoped_path = ["SensitiveValueRemover", *transformed_result_type.scoped_full_path]
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
result_transformers = [*result_transformers, remover]
|
56
|
-
end
|
57
|
-
|
58
45
|
Class.new(self).tap do |klass|
|
59
46
|
klass.command_class = command_class
|
60
47
|
klass.command_name = command_name
|
@@ -70,6 +57,8 @@ module Foobara
|
|
70
57
|
klass.allowed_rule = allowed_rule
|
71
58
|
klass.requires_authentication = requires_authentication
|
72
59
|
klass.authenticator = authenticator
|
60
|
+
klass.subclassed_in_namespace = scoped_namespace
|
61
|
+
klass.suffix = suffix
|
73
62
|
end
|
74
63
|
end
|
75
64
|
|
@@ -78,51 +67,125 @@ module Foobara
|
|
78
67
|
:organization,
|
79
68
|
to: :command_class
|
80
69
|
|
81
|
-
def
|
82
|
-
return @
|
70
|
+
def result_transformers
|
71
|
+
return @result_transformers if @considered_sensitive_value_remover
|
83
72
|
|
84
|
-
@
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
73
|
+
@considered_sensitive_value_remover = true
|
74
|
+
|
75
|
+
result_type = command_class.result_type
|
76
|
+
|
77
|
+
result_transformers.reverse.each do |transformer|
|
78
|
+
if transformer.is_a?(TypeDeclarations::TypedTransformer) ||
|
79
|
+
(transformer.is_a?(Class) && transformer < TypeDeclarations::TypedTransformer)
|
80
|
+
new_type = transformer.to_type
|
81
|
+
if new_type
|
82
|
+
result_type = new_type
|
83
|
+
break
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
if result_type&.has_sensitive_types?
|
89
|
+
remover_class = Foobara::TypeDeclarations.sensitive_value_remover_class_for_type(result_type)
|
90
|
+
|
91
|
+
remover = Namespace.use subclassed_in_namespace do
|
92
|
+
path = if result_type.scoped_path_set?
|
93
|
+
result_type.scoped_full_path
|
94
|
+
else
|
95
|
+
[*command_class.scoped_path, *suffix, "Result"]
|
96
|
+
end
|
97
|
+
|
98
|
+
remover_class.new(from: result_type).tap do |r|
|
99
|
+
r.scoped_path = ["SensitiveValueRemover", *path]
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
@result_transformers = [*@result_transformers, remover]
|
104
|
+
end
|
105
|
+
|
106
|
+
@result_transformers
|
107
|
+
end
|
108
|
+
|
109
|
+
def inputs_transformers
|
110
|
+
return @inputs_transformers if @considered_inputs_sensitive_value_remover
|
111
|
+
|
112
|
+
@considered_inputs_sensitive_value_remover = true
|
113
|
+
|
114
|
+
inputs_type = command_class.inputs_type
|
115
|
+
|
116
|
+
@inputs_transformers = transformers_to_processors(@inputs_transformers, inputs_type, direction: :to)
|
117
|
+
|
118
|
+
@inputs_transformers.each do |transformer|
|
119
|
+
if transformer.is_a?(TypeDeclarations::TypedTransformer)
|
120
|
+
new_type = transformer.from_type
|
121
|
+
if new_type
|
122
|
+
inputs_type = new_type
|
123
|
+
break
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
@inputs_transformers
|
129
|
+
end
|
130
|
+
|
131
|
+
def inputs_type_for_manifest
|
132
|
+
return @inputs_type_for_manifest if defined?(@inputs_type_for_manifest)
|
133
|
+
|
134
|
+
@inputs_type_for_manifest = if inputs_type&.has_sensitive_types?
|
135
|
+
remover_class = Foobara::TypeDeclarations.sensitive_value_remover_class_for_type(
|
136
|
+
inputs_type
|
137
|
+
)
|
138
|
+
|
139
|
+
Namespace.use subclassed_in_namespace do
|
140
|
+
remover_class.new(to: inputs_type).from_type
|
141
|
+
end
|
142
|
+
else
|
143
|
+
inputs_type
|
144
|
+
end
|
105
145
|
end
|
106
146
|
|
107
|
-
def
|
108
|
-
|
109
|
-
|
147
|
+
def inputs_type_from_transformers
|
148
|
+
return @inputs_type_from_transformers if defined?(@inputs_type_from_transformers)
|
149
|
+
|
150
|
+
@inputs_type_from_transformers = if inputs_transformer
|
151
|
+
if inputs_transformer.is_a?(Value::Processor::Pipeline)
|
152
|
+
inputs_transformer.processors.each do |transformer|
|
153
|
+
if transformer.is_a?(TypeDeclarations::TypedTransformer)
|
154
|
+
from_type = transformer.from_type
|
155
|
+
if from_type
|
156
|
+
@inputs_type_from_transformers = from_type
|
157
|
+
return from_type
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
command_class.inputs_type
|
163
|
+
else
|
164
|
+
if inputs_transformer.is_a?(TypeDeclarations::TypedTransformer)
|
165
|
+
inputs_transformer.from_type
|
166
|
+
end || command_class.inputs_type
|
167
|
+
end
|
168
|
+
else
|
169
|
+
command_class.inputs_type
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def result_type_from_transformers
|
174
|
+
result_transformers.reverse.each do |transformer|
|
175
|
+
if transformer.is_a?(TypeDeclarations::TypedTransformer) ||
|
176
|
+
(transformer.is_a?(Class) && transformer < TypeDeclarations::TypedTransformer)
|
110
177
|
new_type = transformer.to_type
|
111
178
|
return new_type if new_type
|
112
179
|
end
|
113
180
|
end
|
114
181
|
|
115
|
-
result_type
|
182
|
+
command_class.result_type
|
116
183
|
end
|
117
184
|
|
118
185
|
def result_type
|
119
|
-
|
120
|
-
end
|
186
|
+
return @result_type if defined?(@result_type)
|
121
187
|
|
122
|
-
|
123
|
-
return @result_type_for_manifest if defined?(@result_type_for_manifest)
|
124
|
-
|
125
|
-
mutated_result_type = result_type
|
188
|
+
mutated_result_type = result_type_from_transformers
|
126
189
|
|
127
190
|
mutators = if response_mutators.size == 1
|
128
191
|
[response_mutator]
|
@@ -134,25 +197,25 @@ module Foobara
|
|
134
197
|
mutated_result_type = mutator.result_type_from(mutated_result_type)
|
135
198
|
end
|
136
199
|
|
137
|
-
@
|
200
|
+
@result_type = mutated_result_type
|
138
201
|
end
|
139
202
|
|
140
|
-
def
|
141
|
-
return @
|
203
|
+
def inputs_type
|
204
|
+
return @inputs_type if defined?(@inputs_type)
|
142
205
|
|
143
|
-
mutated_inputs_type =
|
206
|
+
mutated_inputs_type = inputs_type_from_transformers
|
144
207
|
|
145
208
|
mutators = if request_mutators.size == 1
|
146
209
|
[request_mutator]
|
147
210
|
else
|
148
|
-
request_mutator&.processors
|
211
|
+
request_mutator&.processors
|
149
212
|
end
|
150
213
|
|
151
214
|
mutators&.each do |mutator|
|
152
215
|
mutated_inputs_type = mutator.inputs_type_from(mutated_inputs_type)
|
153
216
|
end
|
154
217
|
|
155
|
-
@
|
218
|
+
@inputs_type = mutated_inputs_type
|
156
219
|
end
|
157
220
|
|
158
221
|
def error_context_type_map
|
@@ -204,12 +267,12 @@ module Foobara
|
|
204
267
|
|
205
268
|
def inputs_types_depended_on
|
206
269
|
TypeDeclarations.with_manifest_context(remove_sensitive: false) do
|
207
|
-
|
270
|
+
inputs_type&.types_depended_on || []
|
208
271
|
end
|
209
272
|
end
|
210
273
|
|
211
274
|
def result_types_depended_on
|
212
|
-
type_proc = -> {
|
275
|
+
type_proc = -> { result_type&.types_depended_on || [] }
|
213
276
|
|
214
277
|
if TypeDeclarations.manifest_context_set?(:remove_sensitive)
|
215
278
|
type_proc.call
|
@@ -224,21 +287,21 @@ module Foobara
|
|
224
287
|
# TODO: memoize this
|
225
288
|
# TODO: this should not delegate to command since transformers are in play
|
226
289
|
|
227
|
-
|
290
|
+
types_proc = proc do
|
291
|
+
type = inputs_type_for_manifest
|
292
|
+
|
293
|
+
if type
|
294
|
+
if type.registered?
|
295
|
+
# TODO: if we ever change from attributes-only inputs type
|
296
|
+
# then this will be handy
|
297
|
+
# :nocov:
|
298
|
+
types |= [type]
|
299
|
+
# :nocov:
|
300
|
+
end
|
228
301
|
|
229
|
-
|
230
|
-
if type.registered?
|
231
|
-
# TODO: if we ever change from attributes-only inputs type
|
232
|
-
# then this will be handy
|
233
|
-
# :nocov:
|
234
|
-
types |= [type]
|
235
|
-
# :nocov:
|
302
|
+
types |= type.types_depended_on
|
236
303
|
end
|
237
304
|
|
238
|
-
types |= type.types_depended_on
|
239
|
-
end
|
240
|
-
|
241
|
-
types_proc = proc do
|
242
305
|
type = result_type
|
243
306
|
|
244
307
|
if type
|
@@ -312,17 +375,19 @@ module Foobara
|
|
312
375
|
result_types_depended_on = self.result_types_depended_on.map(&:foobara_manifest_reference)
|
313
376
|
result_types_depended_on = result_types_depended_on.sort
|
314
377
|
|
315
|
-
|
316
|
-
|
317
|
-
|
378
|
+
bit_bucket = Set.new
|
379
|
+
manifest = TypeDeclarations.with_manifest_context(to_include: bit_bucket) do
|
380
|
+
command_class.foobara_manifest
|
381
|
+
end
|
382
|
+
|
383
|
+
# TODO: handle errors_types_depended_on!
|
384
|
+
manifest.merge(
|
318
385
|
Util.remove_blank(
|
319
386
|
inputs_types_depended_on:,
|
320
387
|
result_types_depended_on:,
|
321
388
|
types_depended_on: types,
|
322
|
-
inputs_type:
|
323
|
-
|
324
|
-
end,
|
325
|
-
result_type: result_type_for_manifest&.reference_or_declaration_data,
|
389
|
+
inputs_type: inputs_type_for_manifest&.reference_or_declaration_data,
|
390
|
+
result_type: result_type&.reference_or_declaration_data,
|
326
391
|
possible_errors: possible_errors_manifest,
|
327
392
|
capture_unknown_error:,
|
328
393
|
inputs_transformers:,
|
@@ -397,13 +462,16 @@ module Foobara
|
|
397
462
|
def response_mutator
|
398
463
|
return @response_mutator if defined?(@response_mutator)
|
399
464
|
|
465
|
+
# A hack: this will give the SensitiveValueRemover a chance to be injected
|
466
|
+
result_transformers
|
467
|
+
|
400
468
|
if response_mutators.empty?
|
401
469
|
@response_mutator = nil
|
402
470
|
return
|
403
471
|
end
|
404
472
|
|
405
473
|
@response_mutator = begin
|
406
|
-
transformers = transformers_to_processors(response_mutators,
|
474
|
+
transformers = transformers_to_processors(response_mutators, result_type_from_transformers, direction: :from)
|
407
475
|
|
408
476
|
if transformers.size == 1
|
409
477
|
transformers.first
|
@@ -416,13 +484,16 @@ module Foobara
|
|
416
484
|
def request_mutator
|
417
485
|
return @request_mutator if defined?(@request_mutator)
|
418
486
|
|
487
|
+
# HACK: to give SensitiveValueRemover a chance to be injected
|
488
|
+
inputs_transformer
|
489
|
+
|
419
490
|
if request_mutators.empty?
|
420
491
|
@request_mutator = nil
|
421
492
|
return
|
422
493
|
end
|
423
494
|
|
424
495
|
@request_mutator = begin
|
425
|
-
transformers = transformers_to_processors(request_mutators,
|
496
|
+
transformers = transformers_to_processors(request_mutators, inputs_type_from_transformers, direction: :to)
|
426
497
|
|
427
498
|
if transformers.size == 1
|
428
499
|
transformers.first
|
@@ -9,13 +9,30 @@ module Foobara
|
|
9
9
|
def transform(strict_type_declaration)
|
10
10
|
old_attributes_declaration = strict_type_declaration[:attributes_declaration]
|
11
11
|
|
12
|
-
new_attributes_declaration =
|
12
|
+
new_attributes_declaration = old_attributes_declaration
|
13
13
|
|
14
|
-
if
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
if strict_type_declaration.key?(:private)
|
15
|
+
new_attributes_declaration = TypeDeclarations::Attributes.reject(
|
16
|
+
old_attributes_declaration,
|
17
|
+
strict_type_declaration[:private]
|
18
|
+
)
|
18
19
|
end
|
20
|
+
|
21
|
+
new_attributes_declaration = remove_sensitive_types(new_attributes_declaration)
|
22
|
+
|
23
|
+
if new_attributes_declaration != old_attributes_declaration
|
24
|
+
strict_type_declaration = strict_type_declaration.merge(attributes_declaration: new_attributes_declaration)
|
25
|
+
end
|
26
|
+
|
27
|
+
if strict_type_declaration.key?(:delegates)
|
28
|
+
strict_type_declaration = strict_type_declaration.except(:delegates)
|
29
|
+
end
|
30
|
+
|
31
|
+
if strict_type_declaration.key?(:private)
|
32
|
+
strict_type_declaration = strict_type_declaration.except(:private)
|
33
|
+
end
|
34
|
+
|
35
|
+
strict_type_declaration
|
19
36
|
end
|
20
37
|
end
|
21
38
|
end
|
@@ -5,7 +5,11 @@ module Foobara
|
|
5
5
|
def transform(record)
|
6
6
|
attributes_type = from_type.element_types
|
7
7
|
|
8
|
-
sanitized_attributes, _changed = sanitize_value(attributes_type, record.
|
8
|
+
sanitized_attributes, _changed = sanitize_value(attributes_type, record.attributes_with_delegates)
|
9
|
+
|
10
|
+
if from_type.declaration_data.key?(:private)
|
11
|
+
sanitized_attributes = sanitized_attributes.except(*from_type.declaration_data[:private])
|
12
|
+
end
|
9
13
|
|
10
14
|
Namespace.use(to_type.created_in_namespace) do
|
11
15
|
to_type.target_class.send(build_method, sanitized_attributes)
|
@@ -19,7 +19,14 @@ module Foobara
|
|
19
19
|
subclass.extend ::Foobara::Scoped
|
20
20
|
|
21
21
|
NamespaceHelpers.foobara_autoset_namespace(subclass, default_namespace: scoped_default_namespace)
|
22
|
-
|
22
|
+
|
23
|
+
if !subclass.respond_to?(:will_set_scoped_path?) || !subclass.will_set_scoped_path?
|
24
|
+
NamespaceHelpers.foobara_autoset_scoped_path(
|
25
|
+
subclass,
|
26
|
+
set_namespace: true,
|
27
|
+
namespace_default: scoped_default_namespace
|
28
|
+
)
|
29
|
+
end
|
23
30
|
|
24
31
|
subclass.extend ::Foobara::Namespace::IsNamespace
|
25
32
|
end
|
@@ -35,6 +42,8 @@ module Foobara
|
|
35
42
|
|
36
43
|
subclass.extend ::Foobara::Scoped
|
37
44
|
|
45
|
+
return if subclass.respond_to?(:will_set_scoped_path?) && subclass.will_set_scoped_path?
|
46
|
+
|
38
47
|
NamespaceHelpers.foobara_autoset_namespace(subclass, default_namespace: scoped_default_namespace)
|
39
48
|
NamespaceHelpers.foobara_autoset_scoped_path(subclass)
|
40
49
|
|
@@ -161,7 +170,12 @@ module Foobara
|
|
161
170
|
mod.scoped_namespace = default_namespace if default_namespace
|
162
171
|
end
|
163
172
|
|
164
|
-
def
|
173
|
+
def anon_sequence(class_name)
|
174
|
+
@anon_sequences ||= {}
|
175
|
+
@anon_sequences.key?(class_name) ? @anon_sequences[class_name] += 1 : @anon_sequences[class_name] = 1
|
176
|
+
end
|
177
|
+
|
178
|
+
def foobara_autoset_scoped_path(mod, make_top_level: false, set_namespace: false, namespace_default: nil)
|
165
179
|
return if mod.scoped_path_set?
|
166
180
|
|
167
181
|
mod_name = mod.name
|
@@ -174,7 +188,13 @@ module Foobara
|
|
174
188
|
super_name = parent.scoped_path_set? ? parent.scoped_full_name : parent.name
|
175
189
|
end until super_name
|
176
190
|
|
177
|
-
|
191
|
+
short_name = if mod.respond_to?(:symbol) && mod.symbol
|
192
|
+
mod.symbol.to_s
|
193
|
+
else
|
194
|
+
"Anon#{NamespaceHelpers.anon_sequence(super_name)}"
|
195
|
+
end
|
196
|
+
|
197
|
+
mod_name = [super_name, short_name].join("::")
|
178
198
|
end
|
179
199
|
|
180
200
|
scoped_path = mod_name.split("::")
|
@@ -183,6 +203,8 @@ module Foobara
|
|
183
203
|
|
184
204
|
next_mod = Object
|
185
205
|
|
206
|
+
parent = namespace_default
|
207
|
+
|
186
208
|
while next_mod
|
187
209
|
path_part = scoped_path.shift
|
188
210
|
|
@@ -192,6 +214,7 @@ module Foobara
|
|
192
214
|
|
193
215
|
if next_mod.is_a?(IsNamespace) && next_mod != mod && !make_top_level
|
194
216
|
adjusted_scoped_path = []
|
217
|
+
parent = next_mod
|
195
218
|
next
|
196
219
|
end
|
197
220
|
|
@@ -201,6 +224,10 @@ module Foobara
|
|
201
224
|
mod.scoped_path_autoset = true
|
202
225
|
mod.scoped_path = adjusted_scoped_path
|
203
226
|
|
227
|
+
if set_namespace
|
228
|
+
mod.scoped_namespace = parent
|
229
|
+
end
|
230
|
+
|
204
231
|
if mod.is_a?(IsNamespace)
|
205
232
|
update_children_with_new_parent(mod)
|
206
233
|
end
|
@@ -114,6 +114,7 @@ module Foobara
|
|
114
114
|
|
115
115
|
Entity.after_initialized_created do |record:, **|
|
116
116
|
transaction = Persistence.current_transaction(record)
|
117
|
+
|
117
118
|
unless transaction
|
118
119
|
raise NoCurrentTransactionError,
|
119
120
|
"Cannot initialize #{record} because there's no current transaction"
|
@@ -131,6 +132,7 @@ module Foobara
|
|
131
132
|
|
132
133
|
Entity.after_initialized_thunk do |record:, **|
|
133
134
|
transaction = Persistence.current_transaction(record)
|
135
|
+
|
134
136
|
unless transaction
|
135
137
|
# :nocov:
|
136
138
|
raise NoCurrentTransactionError,
|
@@ -21,9 +21,8 @@ module Foobara
|
|
21
21
|
attributes = normalize_attributes(attributes)
|
22
22
|
primary_key = primary_key_for_attributes(attributes)
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
record = tracked_records.find_by_key(primary_key)
|
25
|
+
if record
|
27
26
|
next if record.hard_deleted?
|
28
27
|
next if created?(record)
|
29
28
|
|
@@ -34,7 +34,7 @@ module Foobara
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def created(record)
|
37
|
-
|
37
|
+
tracked(record)
|
38
38
|
mark_created(record)
|
39
39
|
end
|
40
40
|
|
@@ -64,7 +64,7 @@ module Foobara
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def updated(record)
|
67
|
-
|
67
|
+
tracked(record)
|
68
68
|
|
69
69
|
# TODO: is this check redundant? Maybe have the entity explode directly instead?
|
70
70
|
if hard_deleted?(record)
|
@@ -65,16 +65,29 @@ module Foobara
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def load(entity_or_record_id)
|
68
|
-
if entity_or_record_id.
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
end
|
74
|
-
|
75
|
-
entity = tracked_records[entity_or_record_id]
|
68
|
+
if entity_or_record_id.nil?
|
69
|
+
# :nocov:
|
70
|
+
raise "Expected a record or record primary key but received nil"
|
71
|
+
# :nocov:
|
72
|
+
end
|
76
73
|
|
77
|
-
|
74
|
+
if entity_or_record_id.is_a?(Entity)
|
75
|
+
entity = if entity_or_record_id.persisted?
|
76
|
+
unless entity_or_record_id.primary_key
|
77
|
+
# :nocov:
|
78
|
+
raise "Did not expect a record to be persisted but have no primary key"
|
79
|
+
# :nocov:
|
80
|
+
end
|
81
|
+
|
82
|
+
tracked_records.find_by_key(entity_or_record_id.primary_key)
|
83
|
+
else
|
84
|
+
# :nocov:
|
85
|
+
raise "Cannot load an unpersisted record!"
|
86
|
+
# :nocov:
|
87
|
+
end
|
88
|
+
|
89
|
+
if entity &&
|
90
|
+
(!entity.equal?(entity_or_record_id) || entity.object_id != entity_or_record_id.object_id)
|
78
91
|
# :nocov:
|
79
92
|
raise "This transaction is already tracking a different entity with the same primary key." \
|
80
93
|
"Try passing in the primary key instead of constructing an unloaded entity to pass in."
|
@@ -151,7 +164,19 @@ module Foobara
|
|
151
164
|
next
|
152
165
|
end
|
153
166
|
|
154
|
-
entity =
|
167
|
+
entity = if entity_or_record_id.persisted?
|
168
|
+
unless entity_or_record_id.primary_key
|
169
|
+
# :nocov:
|
170
|
+
raise "Did not expect a record to be persisted but have no primary key"
|
171
|
+
# :nocov:
|
172
|
+
end
|
173
|
+
|
174
|
+
tracked_records.find_by_key(entity_or_record_id.primary_key)
|
175
|
+
else
|
176
|
+
# :nocov:
|
177
|
+
raise "Cannot load an unpersisted record!"
|
178
|
+
# :nocov:
|
179
|
+
end
|
155
180
|
|
156
181
|
if entity && !entity.equal?(entity_or_record_id)
|
157
182
|
# :nocov:
|
@@ -440,7 +465,7 @@ module Foobara
|
|
440
465
|
end
|
441
466
|
|
442
467
|
def track_loaded(entity)
|
443
|
-
|
468
|
+
tracked(entity)
|
444
469
|
end
|
445
470
|
|
446
471
|
def hard_delete_all!
|
@@ -527,7 +552,7 @@ module Foobara
|
|
527
552
|
|
528
553
|
# we need to update finding the tracked object by key and removing/reading it seems to be the simplest
|
529
554
|
# way to accomplish that at the moment
|
530
|
-
|
555
|
+
tracked(record)
|
531
556
|
|
532
557
|
record.is_persisted = record.is_loaded = true
|
533
558
|
record.is_created = false
|
@@ -547,7 +572,7 @@ module Foobara
|
|
547
572
|
|
548
573
|
# we need to update finding the tracked object by key and removing/reading it seems to be the simplest
|
549
574
|
# way to accomplish that at the moment
|
550
|
-
|
575
|
+
tracked(record)
|
551
576
|
|
552
577
|
record.is_persisted = record.is_loaded = true
|
553
578
|
record.is_created = false
|
@@ -73,6 +73,9 @@ module Foobara
|
|
73
73
|
register_sensitive_value_remover(attributes_handler, SensitiveValueRemovers::Attributes)
|
74
74
|
register_sensitive_type_remover(SensitiveTypeRemovers::Array.new(array_handler))
|
75
75
|
register_sensitive_value_remover(array_handler, SensitiveValueRemovers::Array)
|
76
|
+
|
77
|
+
Foobara::AttributesTransformers::Reject.foobara_unregister_all
|
78
|
+
Foobara::AttributesTransformers::Only.foobara_unregister_all
|
76
79
|
end
|
77
80
|
|
78
81
|
def install!
|
@@ -5,6 +5,10 @@ module Foobara
|
|
5
5
|
transformer_class = Class.new(Only)
|
6
6
|
transformer_class.only_attributes = attribute_names
|
7
7
|
|
8
|
+
Namespace::NamespaceHelpers.foobara_autoset_scoped_path(transformer_class, set_namespace: true)
|
9
|
+
transformer_class.foobara_parent_namespace = transformer_class.scoped_namespace
|
10
|
+
transformer_class.scoped_namespace.foobara_register(transformer_class)
|
11
|
+
|
8
12
|
transformer_class
|
9
13
|
end
|
10
14
|
end
|
@@ -12,6 +16,14 @@ module Foobara
|
|
12
16
|
class Only < AttributesTransformers
|
13
17
|
class << self
|
14
18
|
attr_accessor :only_attributes
|
19
|
+
|
20
|
+
def symbol
|
21
|
+
only_attributes&.sort&.join("_")&.to_sym
|
22
|
+
end
|
23
|
+
|
24
|
+
def will_set_scoped_path?
|
25
|
+
true
|
26
|
+
end
|
15
27
|
end
|
16
28
|
|
17
29
|
def to_type_declaration
|
@@ -5,6 +5,10 @@ module Foobara
|
|
5
5
|
transformer_class = Class.new(Reject)
|
6
6
|
transformer_class.reject_attributes = attribute_names
|
7
7
|
|
8
|
+
Namespace::NamespaceHelpers.foobara_autoset_scoped_path(transformer_class, set_namespace: true)
|
9
|
+
transformer_class.foobara_parent_namespace = transformer_class.scoped_namespace
|
10
|
+
transformer_class.scoped_namespace.foobara_register(transformer_class)
|
11
|
+
|
8
12
|
transformer_class
|
9
13
|
end
|
10
14
|
end
|
@@ -12,6 +16,14 @@ module Foobara
|
|
12
16
|
class Reject < AttributesTransformers
|
13
17
|
class << self
|
14
18
|
attr_accessor :reject_attributes
|
19
|
+
|
20
|
+
def symbol
|
21
|
+
reject_attributes&.sort&.join("_")&.to_sym
|
22
|
+
end
|
23
|
+
|
24
|
+
def will_set_scoped_path?
|
25
|
+
true
|
26
|
+
end
|
15
27
|
end
|
16
28
|
|
17
29
|
def to_type_declaration
|
@@ -5,20 +5,30 @@ module Foobara
|
|
5
5
|
class RemoveSensitiveValuesTransformer < TypedTransformer
|
6
6
|
def from(...)
|
7
7
|
super.tap do
|
8
|
-
|
8
|
+
create_all_association_types_in_current_namespace(from_type)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def to(...)
|
13
|
+
super.tap do
|
14
|
+
create_all_association_types_in_current_namespace(to_type)
|
15
|
+
end
|
16
|
+
end
|
9
17
|
|
10
|
-
|
11
|
-
|
12
|
-
next unless entity_type.has_sensitive_types?
|
18
|
+
def create_all_association_types_in_current_namespace(type)
|
19
|
+
associations = Foobara::DetachedEntity.construct_deep_associations(type)
|
13
20
|
|
14
|
-
|
15
|
-
|
21
|
+
associations&.values&.reverse&.each do |entity_type|
|
22
|
+
next if entity_type.sensitive?
|
23
|
+
next unless entity_type.has_sensitive_types?
|
16
24
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
25
|
+
declaration = entity_type.declaration_data
|
26
|
+
sanitized_type_declaration = TypeDeclarations.remove_sensitive_types(declaration)
|
27
|
+
|
28
|
+
# We want to make sure that any types that change due to having sensitive types
|
29
|
+
# has a corresponding registered type in the command registry domain if needed
|
30
|
+
# TODO: this all feels so messy and brittle.
|
31
|
+
Domain.current.foobara_type_from_declaration(sanitized_type_declaration)
|
22
32
|
end
|
23
33
|
end
|
24
34
|
|
@@ -26,6 +36,10 @@ module Foobara
|
|
26
36
|
TypeDeclarations.remove_sensitive_types(from_type.declaration_data)
|
27
37
|
end
|
28
38
|
|
39
|
+
def from_type_declaration
|
40
|
+
TypeDeclarations.remove_sensitive_types(to_type.declaration_data)
|
41
|
+
end
|
42
|
+
|
29
43
|
def transform(_value)
|
30
44
|
# :nocov:
|
31
45
|
raise "subclass responsibility"
|
@@ -73,7 +73,7 @@ module Foobara
|
|
73
73
|
self.to to
|
74
74
|
end
|
75
75
|
|
76
|
-
# we want to force these to be created now in the current
|
76
|
+
# we want to force these to be created now in the current namespace if they are declarations
|
77
77
|
from_type
|
78
78
|
to_type
|
79
79
|
end
|
@@ -324,6 +324,12 @@ module Foobara
|
|
324
324
|
def foobara_manifest
|
325
325
|
to_include = TypeDeclarations.foobara_manifest_context_to_include
|
326
326
|
|
327
|
+
unless scoped_path_set?
|
328
|
+
if self.class.scoped_path_set?
|
329
|
+
self.scoped_path = self.class.scoped_path
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
327
333
|
possible_errors = self.possible_errors.map do |possible_error|
|
328
334
|
[possible_error.key.to_s, possible_error.foobara_manifest]
|
329
335
|
end
|
@@ -1,52 +1,98 @@
|
|
1
|
+
require "monitor"
|
2
|
+
|
1
3
|
module Foobara
|
4
|
+
# TODO: a possible optimization: have a certain number of records before the Weakref approach kicks in
|
5
|
+
# that way we don't just immediately clear out useful information without any actual memory burden
|
2
6
|
class WeakObjectSet
|
7
|
+
class InvalidWtf < StandardError; end
|
8
|
+
|
3
9
|
class GarbageCleaner
|
4
|
-
|
5
|
-
@objects = objects
|
6
|
-
@key_to_object_id = key_to_object_id
|
7
|
-
@object_id_to_key = object_id_to_key
|
8
|
-
end
|
10
|
+
attr_accessor :weak_object_set, :deactivated, :queue, :cleanup_thread
|
9
11
|
|
10
|
-
def
|
11
|
-
|
12
|
-
|
13
|
-
@objects.delete(object_id)
|
12
|
+
def initialize(weak_object_set, queue)
|
13
|
+
self.queue = queue
|
14
|
+
self.weak_object_set = weak_object_set
|
14
15
|
|
15
|
-
|
16
|
+
start_cleanup_thread
|
17
|
+
end
|
16
18
|
|
17
|
-
|
18
|
-
|
19
|
+
def cleanup_proc
|
20
|
+
@cleanup_proc ||= begin
|
21
|
+
queue = self.queue
|
22
|
+
|
23
|
+
->(object_id) do
|
24
|
+
unless deactivated?
|
25
|
+
begin
|
26
|
+
queue.push(object_id)
|
27
|
+
rescue ClosedQueueError
|
28
|
+
# :nocov:
|
29
|
+
deactivate
|
30
|
+
# :nocov:
|
31
|
+
end
|
19
32
|
end
|
20
33
|
end
|
21
|
-
|
34
|
+
end
|
22
35
|
end
|
23
36
|
|
24
|
-
def
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
37
|
+
def start_cleanup_thread
|
38
|
+
self.cleanup_thread = Thread.new do
|
39
|
+
loop do
|
40
|
+
object_id = queue.pop
|
41
|
+
if object_id
|
42
|
+
weak_object_set.delete(object_id)
|
43
|
+
elsif queue.closed?
|
44
|
+
self.queue = nil
|
45
|
+
break
|
46
|
+
else
|
47
|
+
# :nocov:
|
48
|
+
raise "Unexpected nil value in the queue"
|
49
|
+
# :nocov:
|
50
|
+
end
|
51
|
+
end
|
29
52
|
end
|
53
|
+
end
|
30
54
|
|
55
|
+
def track(object)
|
31
56
|
ObjectSpace.define_finalizer(object, cleanup_proc)
|
32
57
|
end
|
33
58
|
|
34
59
|
def deactivate
|
35
|
-
|
60
|
+
self.deactivated = true
|
61
|
+
queue.close
|
62
|
+
cleanup_thread.join # just doing this for test suite/simplecov
|
63
|
+
end
|
64
|
+
|
65
|
+
def deactivated?
|
66
|
+
deactivated
|
36
67
|
end
|
37
68
|
end
|
38
69
|
|
39
70
|
include Enumerable
|
40
71
|
|
72
|
+
attr_accessor :monitor, :key_method, :key_to_object_id, :object_id_to_key, :objects
|
73
|
+
attr_writer :garbage_cleaner
|
74
|
+
|
41
75
|
def initialize(key_method = nil)
|
42
|
-
|
76
|
+
self.key_method = key_method
|
77
|
+
self.monitor = Monitor.new
|
78
|
+
clear
|
43
79
|
end
|
44
80
|
|
45
81
|
def [](object_or_object_id)
|
46
|
-
|
82
|
+
monitor.synchronize do
|
83
|
+
ref = ref_for(object_or_object_id)
|
47
84
|
|
48
|
-
|
49
|
-
|
85
|
+
object = begin
|
86
|
+
ref&.__getobj__
|
87
|
+
rescue WeakRef::RefError
|
88
|
+
# :nocov:
|
89
|
+
nil
|
90
|
+
# :nocov:
|
91
|
+
end
|
92
|
+
|
93
|
+
if ref&.weakref_alive?
|
94
|
+
object
|
95
|
+
end
|
50
96
|
end
|
51
97
|
end
|
52
98
|
|
@@ -61,121 +107,146 @@ module Foobara
|
|
61
107
|
end
|
62
108
|
|
63
109
|
def each
|
64
|
-
|
65
|
-
|
66
|
-
|
110
|
+
monitor.synchronize do
|
111
|
+
objects.each_value do |ref|
|
112
|
+
object = begin
|
113
|
+
ref.__getobj__
|
114
|
+
rescue WeakRef::RefError
|
115
|
+
nil
|
116
|
+
end
|
117
|
+
|
118
|
+
if ref.weakref_alive?
|
119
|
+
yield object
|
120
|
+
end
|
67
121
|
end
|
68
122
|
end
|
69
123
|
end
|
70
124
|
|
71
|
-
def objects
|
72
|
-
@objects ||= {}
|
73
|
-
end
|
74
|
-
|
75
125
|
def size
|
76
126
|
count
|
77
127
|
end
|
78
128
|
|
79
129
|
def empty?
|
80
|
-
|
130
|
+
monitor.synchronize do
|
131
|
+
objects.empty? || objects.values.none?(&:weakref_alive?)
|
132
|
+
end
|
81
133
|
end
|
82
134
|
|
83
|
-
def
|
84
|
-
@
|
85
|
-
|
135
|
+
def garbage_cleaner
|
136
|
+
@garbage_cleaner ||= begin
|
137
|
+
queue = Queue.new
|
86
138
|
|
87
|
-
|
88
|
-
@object_id_to_key ||= {}
|
89
|
-
end
|
139
|
+
gc = GarbageCleaner.new(self, queue)
|
90
140
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
141
|
+
ObjectSpace.define_finalizer gc do
|
142
|
+
# :nocov:
|
143
|
+
queue.close
|
144
|
+
# :nocov:
|
145
|
+
end
|
146
|
+
|
147
|
+
gc
|
148
|
+
end
|
97
149
|
end
|
98
150
|
|
99
151
|
def <<(object)
|
100
152
|
object_id = object.object_id
|
101
153
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
154
|
+
monitor.synchronize do
|
155
|
+
existing_object = self[object_id]
|
156
|
+
|
157
|
+
if existing_object
|
158
|
+
if key_method
|
159
|
+
key = object.send(key_method)
|
160
|
+
old_key = object_id_to_key[object_id]
|
106
161
|
|
107
|
-
|
108
|
-
|
162
|
+
if key != old_key
|
163
|
+
key_to_object_id.delete(old_key)
|
164
|
+
|
165
|
+
if key
|
166
|
+
key_to_object_id[key] = object_id
|
167
|
+
object_id_to_key[object_id] = key
|
168
|
+
else
|
169
|
+
object_id_to_key.delete(object_id)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
else
|
174
|
+
garbage_cleaner.track(object)
|
175
|
+
|
176
|
+
if key_method
|
177
|
+
key = object.send(key_method)
|
109
178
|
|
110
179
|
if key
|
180
|
+
existing_record_object_id = key_to_object_id[key]
|
181
|
+
|
182
|
+
if existing_record_object_id
|
183
|
+
# Sometimes this path is hit in the test suite and sometimes not, depending on
|
184
|
+
# non-deterministic behavior of the garbage collector
|
185
|
+
# :nocov:
|
186
|
+
delete(existing_record_object_id)
|
187
|
+
# :nocov:
|
188
|
+
end
|
189
|
+
|
111
190
|
key_to_object_id[key] = object_id
|
112
191
|
object_id_to_key[object_id] = key
|
113
|
-
else
|
114
|
-
object_id_to_key.delete(object_id)
|
115
192
|
end
|
116
193
|
end
|
117
|
-
end
|
118
|
-
else
|
119
|
-
garbage_cleaner.track(object)
|
120
|
-
|
121
|
-
objects[object_id] = WeakRef.new(object)
|
122
194
|
|
123
|
-
|
124
|
-
key = object.send(@key_method)
|
195
|
+
objects[object_id] = WeakRef.new(object)
|
125
196
|
|
126
|
-
|
127
|
-
key_to_object_id[key] = object_id
|
128
|
-
object_id_to_key[object_id] = key
|
129
|
-
end
|
197
|
+
object
|
130
198
|
end
|
131
|
-
|
132
|
-
object
|
133
199
|
end
|
134
200
|
end
|
135
201
|
|
136
|
-
def
|
137
|
-
|
138
|
-
|
202
|
+
def delete(object_or_object_id)
|
203
|
+
object_id = if object_or_object_id.is_a?(::Integer)
|
204
|
+
object_or_object_id
|
205
|
+
else
|
206
|
+
object_or_object_id.object_id
|
207
|
+
end
|
139
208
|
|
140
|
-
|
141
|
-
|
142
|
-
|
209
|
+
monitor.synchronize do
|
210
|
+
if key_method
|
211
|
+
key = object_id_to_key.delete(object_id)
|
143
212
|
|
144
|
-
|
145
|
-
|
213
|
+
if key
|
214
|
+
key_to_object_id.delete(key)
|
215
|
+
end
|
146
216
|
end
|
147
|
-
end
|
148
|
-
|
149
|
-
objects.delete(object)
|
150
|
-
end
|
151
217
|
|
152
|
-
|
153
|
-
unless @key_method
|
154
|
-
# :nocov:
|
155
|
-
raise "Cannot check by key if there was no key_method given."
|
156
|
-
# :nocov:
|
218
|
+
objects.delete(object_id)
|
157
219
|
end
|
158
|
-
|
159
|
-
objects[key_to_object_id[key]]&.weakref_alive?
|
160
220
|
end
|
161
221
|
|
162
222
|
def find_by_key(key)
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
223
|
+
monitor.synchronize do
|
224
|
+
unless key_method
|
225
|
+
# :nocov:
|
226
|
+
raise "Cannot find by key if there was no key_method given."
|
227
|
+
# :nocov:
|
228
|
+
end
|
168
229
|
|
169
|
-
|
230
|
+
object_id = key_to_object_id[key]
|
170
231
|
|
171
|
-
|
172
|
-
|
232
|
+
if object_id
|
233
|
+
self[object_id]
|
234
|
+
end
|
173
235
|
end
|
174
236
|
end
|
175
237
|
|
176
238
|
def clear
|
177
|
-
|
178
|
-
|
239
|
+
monitor.synchronize do
|
240
|
+
garbage_cleaner.deactivate
|
241
|
+
|
242
|
+
self.garbage_cleaner = nil
|
243
|
+
self.objects = {}
|
244
|
+
|
245
|
+
if key_method
|
246
|
+
self.key_to_object_id = {}
|
247
|
+
self.object_id_to_key = {}
|
248
|
+
end
|
249
|
+
end
|
179
250
|
end
|
180
251
|
end
|
181
252
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foobara
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.120
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Miles Georgi
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-05-
|
10
|
+
date: 2025-05-11 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: bigdecimal
|
@@ -396,6 +396,7 @@ files:
|
|
396
396
|
- projects/state_machine/src/validations.rb
|
397
397
|
- projects/type_declarations/lib/foobara/type_declarations.rb
|
398
398
|
- projects/type_declarations/src/attributes.rb
|
399
|
+
- projects/type_declarations/src/attributes_transformers.rb
|
399
400
|
- projects/type_declarations/src/attributes_transformers/only.rb
|
400
401
|
- projects/type_declarations/src/attributes_transformers/reject.rb
|
401
402
|
- projects/type_declarations/src/caster.rb
|