foobara 0.0.92 → 0.0.94

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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/projects/command/src/command_pattern_implementation/concerns/reflection.rb +39 -18
  4. data/projects/command/src/transformed_command.rb +83 -40
  5. data/projects/command_connectors/src/command_connector/commands/describe.rb +1 -5
  6. data/projects/command_connectors/src/command_connector/request.rb +7 -1
  7. data/projects/command_connectors/src/command_connector/response.rb +7 -1
  8. data/projects/command_connectors/src/command_connector.rb +85 -74
  9. data/projects/command_connectors/src/command_registry/exposed_command.rb +3 -2
  10. data/projects/command_connectors/src/command_registry/exposed_domain.rb +10 -3
  11. data/projects/command_connectors/src/command_registry/exposed_organization.rb +2 -2
  12. data/projects/command_connectors/src/serializers/atomic_serializer.rb +1 -1
  13. data/projects/command_connectors/src/serializers/errors_serializer.rb +4 -2
  14. data/projects/command_connectors/src/transformers/load_delegated_attributes_entities_pre_commit_transformer.rb +40 -0
  15. data/projects/common/src/data_path.rb +16 -0
  16. data/projects/common/src/error.rb +10 -4
  17. data/projects/common/src/possible_error.rb +9 -3
  18. data/projects/detached_entity/src/concerns/associations.rb +26 -20
  19. data/projects/detached_entity/src/concerns/reflection.rb +3 -3
  20. data/projects/detached_entity/src/detached_entity_type.rb +8 -3
  21. data/projects/detached_entity/src/extensions/builtin_types/detached_entity/validators/{attributes_declaration.rb → model_instance_is_valid.rb} +1 -1
  22. data/projects/domain/src/domain_module_extension.rb +12 -4
  23. data/projects/domain/src/extensions/foobara.rb +31 -28
  24. data/projects/domain/src/is_manifestable.rb +6 -2
  25. data/projects/domain/src/organization_module_extension.rb +6 -2
  26. data/projects/entity/src/concerns/queries.rb +29 -31
  27. data/projects/entity/src/extensions/builtin_types/entity/validators/{attributes_declaration.rb → model_instance_is_valid.rb} +1 -1
  28. data/projects/model/src/concerns/reflection.rb +8 -2
  29. data/projects/model/src/concerns/types.rb +121 -23
  30. data/projects/model/src/extensions/builtin_types/model/supported_transformers/mutable.rb +1 -2
  31. data/projects/model/src/extensions/builtin_types/model/validators/{attributes_declaration.rb → model_instance_is_valid.rb} +1 -1
  32. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration/array_with_symbolic_elements.rb +29 -0
  33. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration/delegates_desugarizer.rb +39 -0
  34. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration/delegates_validator.rb +44 -0
  35. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration/move_private_from_element_types_to_root.rb +48 -0
  36. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration/symbolize_private.rb +34 -0
  37. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration/to_type_transformer.rb +34 -2
  38. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration/valid_attribute_names.rb +54 -0
  39. data/projects/model/src/model.rb +9 -0
  40. data/projects/model_attribute_helpers/src/attribute_helpers.rb +25 -4
  41. data/projects/namespace/src/is_namespace.rb +34 -15
  42. data/projects/persistence/src/entity_attributes_crud_driver.rb +25 -1
  43. data/projects/persistence/src/entity_base/transaction_table.rb +28 -3
  44. data/projects/type_declarations/src/desugarizer.rb +1 -1
  45. data/projects/type_declarations/src/type_builder.rb +42 -39
  46. data/projects/type_declarations/src/type_declaration_handler.rb +1 -1
  47. data/projects/type_declarations/src/type_declaration_handler_registry.rb +1 -1
  48. data/projects/type_declarations/src/type_declaration_validator.rb +1 -1
  49. data/projects/type_declarations/src/type_declarations.rb +39 -10
  50. data/projects/types/src/extensions/error.rb +3 -3
  51. data/projects/types/src/type/concerns/reflection.rb +79 -4
  52. data/projects/types/src/type.rb +42 -17
  53. data/projects/value/src/caster.rb +1 -1
  54. data/projects/value/src/mutator.rb +1 -1
  55. data/projects/value/src/processor/casting.rb +1 -1
  56. data/projects/value/src/processor/pipeline.rb +1 -1
  57. data/projects/value/src/processor/selection.rb +1 -1
  58. data/projects/value/src/processor.rb +13 -5
  59. data/projects/value/src/transformer.rb +1 -1
  60. data/projects/value/src/validator.rb +1 -1
  61. metadata +13 -6
@@ -9,10 +9,17 @@ module Foobara
9
9
  end
10
10
 
11
11
  # TODO: unable to address types here so it is handled as a hack higher up...
12
- def foobara_manifest(to_include: Set.new, remove_sensitive: true)
13
- to_include << foobara_organization
12
+ def foobara_manifest
13
+ to_include = TypeDeclarations.foobara_manifest_context_to_include
14
+
15
+ if to_include
16
+ to_include << foobara_organization
17
+ end
18
+
19
+ domain_manifest = TypeDeclarations.with_manifest_context(to_include: Set.new) do
20
+ unexposed_domain.foobara_manifest
21
+ end
14
22
 
15
- domain_manifest = unexposed_domain.foobara_manifest(to_include: Set.new, remove_sensitive:)
16
23
  mode = Foobara::Namespace::LookupMode::DIRECT
17
24
  commands = foobara_all_command(mode:).map(&:foobara_manifest_reference).sort
18
25
 
@@ -9,8 +9,8 @@ module Foobara
9
9
  end
10
10
 
11
11
  # TODO: unable to address types here so it is handled as a hack higher up...
12
- def foobara_manifest(to_include: Set.new, remove_sensitive: true)
13
- organization_manifest = unexposed_organization.foobara_manifest(to_include: Set.new, remove_sensitive:)
12
+ def foobara_manifest
13
+ organization_manifest = unexposed_organization.foobara_manifest
14
14
  mode = Foobara::Namespace::LookupMode::DIRECT
15
15
  domains = foobara_all_domain(mode:).map(&:foobara_manifest_reference).sort
16
16
 
@@ -8,7 +8,7 @@ module Foobara
8
8
  object.class.load(object)
9
9
  end
10
10
 
11
- object = object.attributes
11
+ object = object.attributes_with_delegates
12
12
  end
13
13
 
14
14
  entities_to_primary_keys_serializer.serialize(object)
@@ -4,8 +4,10 @@ module Foobara
4
4
  module CommandConnectors
5
5
  module Serializers
6
6
  class ErrorsSerializer < Serializer
7
- def always_applicable?
8
- !request.outcome.success?
7
+ def applicable?(error_collection)
8
+ if request.outcome.nil? || !request.outcome.success?
9
+ error_collection.has_errors?
10
+ end
9
11
  end
10
12
 
11
13
  def serialize(error_collection)
@@ -0,0 +1,40 @@
1
+ module Foobara
2
+ module CommandConnectors
3
+ module Transformers
4
+ # TODO: Should be a mutator instead
5
+ class LoadDelegatedAttributesEntitiesPreCommitTransformer < Value::Transformer
6
+ def applicable?(request)
7
+ request.command.outcome.success?
8
+ end
9
+
10
+ def transform(request)
11
+ result = request.command.outcome.result
12
+ load_delegated_attribute_entities(result)
13
+
14
+ request
15
+ end
16
+
17
+ def load_delegated_attribute_entities(object)
18
+ case object
19
+ when Entity
20
+ object.class.delegates.each_key do |delegated_attribute_name|
21
+ object.send(delegated_attribute_name)
22
+ end
23
+ when Array
24
+ object.each do |element|
25
+ load_delegated_attribute_entities(element)
26
+ end
27
+ when Hash
28
+ object.each_key do |key|
29
+ load_delegated_attribute_entities(key)
30
+ end
31
+
32
+ object.each_value do |value|
33
+ load_delegated_attribute_entities(value)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -76,6 +76,14 @@ module Foobara
76
76
  def parse(key_string)
77
77
  new(key_string)
78
78
  end
79
+
80
+ def for(object)
81
+ if object.is_a?(DataPath)
82
+ object
83
+ else
84
+ new(object)
85
+ end
86
+ end
79
87
  end
80
88
 
81
89
  attr_reader :path
@@ -204,6 +212,14 @@ module Foobara
204
212
  self.class == other.class && path == other.path
205
213
  end
206
214
 
215
+ def last
216
+ path.last
217
+ end
218
+
219
+ def empty?
220
+ path.empty?
221
+ end
222
+
207
223
  private
208
224
 
209
225
  def normalize_all(key_parts)
@@ -102,9 +102,13 @@ module Foobara
102
102
  }
103
103
  end
104
104
 
105
- def foobara_manifest(to_include: Set.new, remove_sensitive: false)
106
- types = types_depended_on(remove_sensitive:).map do |t|
107
- to_include << t
105
+ def foobara_manifest
106
+ to_include = TypeDeclarations.foobara_manifest_context_to_include
107
+
108
+ types = types_depended_on.map do |t|
109
+ if to_include
110
+ to_include << t
111
+ end
108
112
  t.foobara_manifest_reference
109
113
  end
110
114
 
@@ -112,7 +116,9 @@ module Foobara
112
116
  # don't bother including these core errors
113
117
  unless superclass == Foobara::Error
114
118
  base = superclass
115
- to_include << base
119
+ if to_include
120
+ to_include << base
121
+ end
116
122
  end
117
123
 
118
124
  manifest = super
@@ -46,12 +46,18 @@ module Foobara
46
46
  end
47
47
 
48
48
  # TODO: technically does not belong in this project but maybe it should
49
- def foobara_manifest(to_include: Set.new, remove_sensitive: false)
50
- to_include << error_class
49
+ def foobara_manifest
50
+ to_include = TypeDeclarations.foobara_manifest_context_to_include
51
+
52
+ if to_include
53
+ to_include << error_class
54
+ end
51
55
 
52
56
  if processor
53
57
  processor_class = processor.class
54
- to_include << processor_class
58
+ if to_include
59
+ to_include << processor_class
60
+ end
55
61
 
56
62
  if processor.scoped_path_set?
57
63
  # Unclear why nothing in the test suite passes through here.
@@ -5,18 +5,22 @@ module Foobara
5
5
  include Concern
6
6
 
7
7
  module ClassMethods
8
- def foobara_associations(remove_sensitive: false)
8
+ def foobara_associations
9
+ remove_sensitive = TypeDeclarations.foobara_manifest_context_remove_sensitive?
10
+
9
11
  if defined?(@foobara_associations) && @foobara_associations.key?(remove_sensitive)
10
12
  return @foobara_associations[remove_sensitive]
11
13
  end
12
14
 
13
15
  @foobara_associations ||= {}
14
- @foobara_associations[remove_sensitive] = construct_associations(remove_sensitive:)
16
+ @foobara_associations[remove_sensitive] = construct_associations
15
17
  end
16
18
 
17
19
  alias associations foobara_associations
18
20
 
19
- def foobara_deep_associations(remove_sensitive: false)
21
+ def foobara_deep_associations
22
+ remove_sensitive = TypeDeclarations.foobara_manifest_context_remove_sensitive?
23
+
20
24
  if defined?(@foobara_deep_associations) && @foobara_deep_associations.key?(remove_sensitive)
21
25
  return @foobara_deep_associations[remove_sensitive]
22
26
  end
@@ -30,7 +34,7 @@ module Foobara
30
34
 
31
35
  entity_class = type.target_class
32
36
 
33
- entity_class.deep_associations(remove_sensitive:).each_pair do |sub_data_path, sub_type|
37
+ entity_class.deep_associations.each_pair do |sub_data_path, sub_type|
34
38
  deep["#{data_path}.#{sub_data_path}"] = sub_type
35
39
  end
36
40
  end
@@ -126,10 +130,9 @@ module Foobara
126
130
  def construct_deep_associations(
127
131
  type = attributes_type,
128
132
  path = DataPath.new,
129
- result = {},
130
- remove_sensitive: false
133
+ result = {}
131
134
  )
132
- associations = construct_associations(type, path, result, remove_sensitive:)
135
+ associations = construct_associations(type, path, result)
133
136
 
134
137
  deep = {}
135
138
 
@@ -138,7 +141,7 @@ module Foobara
138
141
 
139
142
  entity_class = association_type.target_class
140
143
 
141
- entity_class.deep_associations(remove_sensitive:).each_pair do |sub_data_path, sub_type|
144
+ entity_class.deep_associations.each_pair do |sub_data_path, sub_type|
142
145
  deep["#{data_path}.#{sub_data_path}"] = sub_type
143
146
  end
144
147
  end
@@ -151,9 +154,10 @@ module Foobara
151
154
  def construct_associations(
152
155
  type = attributes_type,
153
156
  path = DataPath.new,
154
- result = {},
155
- remove_sensitive: false
157
+ result = {}
156
158
  )
159
+ remove_sensitive = TypeDeclarations.foobara_manifest_context_remove_sensitive?
160
+
157
161
  if type.extends?(BuiltinTypes[:entity])
158
162
  result[path.to_s] = type
159
163
  elsif type.extends?(BuiltinTypes[:tuple])
@@ -167,7 +171,7 @@ module Foobara
167
171
  end
168
172
 
169
173
  element_types&.each&.with_index do |element_type, index|
170
- construct_associations(element_type, path.append(index), result, remove_sensitive:)
174
+ construct_associations(element_type, path.append(index), result)
171
175
  end
172
176
  elsif type.extends?(BuiltinTypes[:array])
173
177
  # TODO: what to do about an associative array type?? Unclear how to make a key from that...
@@ -175,7 +179,7 @@ module Foobara
175
179
  element_type = type.element_type
176
180
 
177
181
  if element_type && (!remove_sensitive || !element_type.sensitive?)
178
- construct_associations(element_type, path.append(:"#"), result, remove_sensitive:)
182
+ construct_associations(element_type, path.append(:"#"), result)
179
183
  end
180
184
  elsif type.extends?(BuiltinTypes[:attributes]) # TODO: matches attributes itself instead of only subtypes
181
185
  type.element_types.each_pair do |attribute_name, element_type|
@@ -183,7 +187,7 @@ module Foobara
183
187
  next
184
188
  end
185
189
 
186
- construct_associations(element_type, path.append(attribute_name), result, remove_sensitive:)
190
+ construct_associations(element_type, path.append(attribute_name), result)
187
191
  end
188
192
  elsif type.extends?(BuiltinTypes[:model])
189
193
  target_class = type.target_class
@@ -192,12 +196,12 @@ module Foobara
192
196
  attributes_type = target_class.send(method)
193
197
 
194
198
  if !remove_sensitive || !attributes_type.sensitive?
195
- construct_associations(attributes_type, path, result, remove_sensitive:)
199
+ construct_associations(attributes_type, path, result)
196
200
  end
197
201
  elsif type.extends?(BuiltinTypes[:associative_array])
198
202
  # not going to bother testing this for now
199
203
  # :nocov:
200
- if contains_associations?(type, remove_sensitive:)
204
+ if contains_associations?(type)
201
205
  raise "Associative array types with associations in them are not currently supported. " \
202
206
  "Use attributes type if you can or set the key_type and/or value_type to duck type"
203
207
  end
@@ -207,7 +211,9 @@ module Foobara
207
211
  result
208
212
  end
209
213
 
210
- def contains_associations?(type = entity_type, initial = true, remove_sensitive: false)
214
+ def contains_associations?(type = entity_type, initial = true)
215
+ remove_sensitive = TypeDeclarations.foobara_manifest_context_remove_sensitive?
216
+
211
217
  if type.extends?(BuiltinTypes[:detached_entity])
212
218
  if initial
213
219
  element_types = type.element_types
@@ -219,7 +225,7 @@ module Foobara
219
225
  # :nocov:
220
226
  end
221
227
 
222
- contains_associations?(element_types, false, remove_sensitive:)
228
+ contains_associations?(element_types, false)
223
229
  else
224
230
  true
225
231
  end
@@ -229,12 +235,12 @@ module Foobara
229
235
  element_type = type.element_type
230
236
 
231
237
  if element_type && (!remove_sensitive || !element_type.sensitive?)
232
- contains_associations?(element_type, false, remove_sensitive:)
238
+ contains_associations?(element_type, false)
233
239
  end
234
240
  elsif type.extends?(BuiltinTypes[:attributes])
235
241
  type.element_types.values.any? do |element_type|
236
242
  if !remove_sensitive || !element_type.sensitive?
237
- contains_associations?(element_type, false, remove_sensitive:)
243
+ contains_associations?(element_type, false)
238
244
  end
239
245
  end
240
246
  elsif type.extends?(BuiltinTypes[:associative_array])
@@ -248,7 +254,7 @@ module Foobara
248
254
  end
249
255
 
250
256
  types.any? do |key_or_value_type|
251
- contains_associations?(key_or_value_type, false, remove_sensitive:)
257
+ contains_associations?(key_or_value_type, false)
252
258
  end
253
259
  end
254
260
  end
@@ -17,15 +17,15 @@ module Foobara
17
17
  types.map(&:target_class).uniq
18
18
  end
19
19
 
20
- def foobara_manifest(to_include: Set.new, remove_sensitive: false)
21
- associations = foobara_associations(remove_sensitive:).map do |(path, type)|
20
+ def foobara_manifest
21
+ associations = foobara_associations.map do |(path, type)|
22
22
  entity_class = type.target_class
23
23
  entity_name = entity_class.foobara_type.scoped_full_name
24
24
 
25
25
  [path, entity_name]
26
26
  end.sort.to_h
27
27
 
28
- deep_associations = foobara_deep_associations(remove_sensitive:).map do |(path, type)|
28
+ deep_associations = foobara_deep_associations.map do |(path, type)|
29
29
  entity_class = type.target_class
30
30
  entity_name = entity_class.foobara_type.scoped_full_name
31
31
 
@@ -18,11 +18,12 @@ module Foobara
18
18
  end
19
19
  end
20
20
 
21
- def foobara_manifest(to_include: Set.new, remove_sensitive: false)
21
+ def foobara_manifest
22
22
  manifest = super
23
23
 
24
24
  if detached_context?
25
25
  declaration_data = manifest[:declaration_data]
26
+
26
27
  if self.class.type_requires_conversion?(declaration_data[:type])
27
28
  declaration_data = declaration_data.merge(type: :detached_entity)
28
29
  end
@@ -31,13 +32,17 @@ module Foobara
31
32
  declaration_data = declaration_data.merge(model_base_class: "Foobara::DetachedEntity")
32
33
  end
33
34
 
35
+ # TODO: remove private attributes, add delegated attributes
36
+ # re: delegated attribute type... it can be required if required entire way, can be
37
+ # allow_nil if allow_nil anywhere along the way.
38
+ # remove private and delegated from the manifest hash.
34
39
  manifest = manifest.merge(declaration_data:)
35
40
  end
36
41
 
37
42
  manifest
38
43
  end
39
44
 
40
- def types_to_add_to_manifest(remove_sensitive: false)
45
+ def types_to_add_to_manifest
41
46
  types = super
42
47
 
43
48
  if detached_context?
@@ -57,7 +62,7 @@ module Foobara
57
62
  end
58
63
 
59
64
  def detached_context?
60
- Thread.foobara_var_get("foobara_manifest_context")&.[](:detached)
65
+ TypeDeclarations.foobara_manifest_context_detached?
61
66
  end
62
67
  end
63
68
  end
@@ -2,7 +2,7 @@ module Foobara
2
2
  module BuiltinTypes
3
3
  module DetachedEntity
4
4
  module Validators
5
- class AttributesDeclaration < Model::Validators::AttributesDeclaration
5
+ class ModelInstanceIsValid < Model::Validators::ModelInstanceIsValid
6
6
  # Why is this here in entity/ instead of in model/?
7
7
  def possible_errors
8
8
  return [] if parent_declaration_data == { type: expected_type_symbol }
@@ -431,20 +431,28 @@ module Foobara
431
431
  end
432
432
 
433
433
  # TODO: can we kill this skip concept?
434
- def foobara_manifest(to_include: Set.new, remove_sensitive: false)
434
+ def foobara_manifest
435
+ to_include = TypeDeclarations.foobara_manifest_context_to_include
436
+
435
437
  depends_on = foobara_depends_on.map do |name|
436
438
  domain = Domain.to_domain(name)
437
- to_include << domain
439
+ if to_include
440
+ to_include << domain
441
+ end
438
442
  domain.foobara_manifest_reference
439
443
  end.sort
440
444
 
441
445
  commands = foobara_all_command(mode: Namespace::LookupMode::DIRECT).map do |command_class|
442
- to_include << command_class
446
+ if to_include
447
+ to_include << command_class
448
+ end
443
449
  command_class.foobara_manifest_reference
444
450
  end.sort
445
451
 
446
452
  types = foobara_all_type(mode: Namespace::LookupMode::DIRECT).map do |type|
447
- to_include << type
453
+ if to_include
454
+ to_include << type
455
+ end
448
456
  type.foobara_manifest_reference
449
457
  end.sort
450
458
 
@@ -8,46 +8,49 @@ module Foobara
8
8
  # in the http connector.
9
9
  def manifest
10
10
  to_include = Namespace.global.foobara_all_organization.to_set
11
- included = {}
12
11
 
13
- h = {}
12
+ TypeDeclarations.with_manifest_context(to_include:) do
13
+ included = {}
14
14
 
15
- until to_include.empty?
16
- object = to_include.first
17
- to_include.delete(object)
15
+ h = {}
18
16
 
19
- unless object.scoped_path_set?
20
- # :nocov:
21
- raise "no scoped path set for #{object}"
22
- # :nocov:
23
- end
17
+ until to_include.empty?
18
+ object = to_include.first
19
+ to_include.delete(object)
24
20
 
25
- manifest_reference = object.foobara_manifest_reference.to_sym
26
- category_symbol = Namespace.global.foobara_category_symbol_for(object)
21
+ unless object.scoped_path_set?
22
+ # :nocov:
23
+ raise "no scoped path set for #{object}"
24
+ # :nocov:
25
+ end
27
26
 
28
- unless category_symbol
29
- # :nocov:
30
- raise "no category symbol for #{object}"
31
- # :nocov:
32
- end
27
+ manifest_reference = object.foobara_manifest_reference.to_sym
28
+ category_symbol = Namespace.global.foobara_category_symbol_for(object)
33
29
 
34
- if included.key?(manifest_reference)
35
- if included[manifest_reference] == category_symbol
36
- next
37
- else
30
+ unless category_symbol
38
31
  # :nocov:
39
- raise "Collision for #{manifest_reference}: #{included[manifest_reference]} and #{category_symbol}"
32
+ raise "no category symbol for #{object}"
40
33
  # :nocov:
41
34
  end
42
- end
43
35
 
44
- cat = h[category_symbol] ||= {}
45
- cat[manifest_reference] = object.foobara_manifest(to_include:)
36
+ if included.key?(manifest_reference)
37
+ if included[manifest_reference] == category_symbol
38
+ next
39
+ else
40
+ # :nocov:
41
+ raise "Collision for #{manifest_reference}: #{included[manifest_reference]} and #{category_symbol}"
42
+ # :nocov:
43
+ end
44
+ end
46
45
 
47
- included[manifest_reference] = category_symbol
48
- end
46
+ cat = h[category_symbol] ||= {}
47
+ cat[manifest_reference] = object.foobara_manifest
49
48
 
50
- h.sort.to_h
49
+ included[manifest_reference] = category_symbol
50
+ end
51
+
52
+ h.sort.to_h
53
+ end
51
54
  end
52
55
 
53
56
  def all_organizations
@@ -37,7 +37,9 @@ module Foobara
37
37
  end
38
38
  end
39
39
 
40
- def foobara_manifest(to_include: Set.new, remove_sensitive: false)
40
+ def foobara_manifest
41
+ to_include = TypeDeclarations.foobara_manifest_context_to_include
42
+
41
43
  h = {
42
44
  scoped_path:,
43
45
  scoped_name:,
@@ -57,7 +59,9 @@ module Foobara
57
59
  parent_category = Namespace.global.foobara_category_symbol_for(parent)
58
60
 
59
61
  if parent_category
60
- to_include << parent
62
+ if to_include
63
+ to_include << parent
64
+ end
61
65
  h[:parent] = [parent_category, parent.foobara_manifest_reference]
62
66
  end
63
67
  end
@@ -36,9 +36,13 @@ module Foobara
36
36
  foobara_all_domain(mode: Namespace::LookupMode::DIRECT)
37
37
  end
38
38
 
39
- def foobara_manifest(to_include: Set.new, remove_sensitive: false)
39
+ def foobara_manifest
40
+ to_include = TypeDeclarations.foobara_manifest_context_to_include
41
+
40
42
  domains = foobara_domains.map do |domain|
41
- to_include << domain
43
+ if to_include
44
+ to_include << domain
45
+ end
42
46
  domain.foobara_manifest_reference
43
47
  end.sort
44
48
 
@@ -91,7 +91,7 @@ module Foobara
91
91
  end
92
92
 
93
93
  def that_owns(record, filters = [])
94
- containing_records = that_own(record, filters)
94
+ containing_records = that_own(record, filters).to_a
95
95
 
96
96
  unless containing_records.empty?
97
97
  if containing_records.size == 1
@@ -107,42 +107,40 @@ module Foobara
107
107
  def that_own(record, filters = [])
108
108
  association_key = association_for([record.class, *filters])
109
109
 
110
- data_path = DataPath.new(association_key)
110
+ possible_direct_owner_path = DataPath.new(association_key)
111
111
 
112
- done = false
112
+ # We need to find the second-to-last entity in the association path
113
+ attribute_path = []
114
+ owning_entity_class = nil
113
115
 
114
- containing_records = Util.array(record)
116
+ begin
117
+ attribute_path.unshift(possible_direct_owner_path.last)
118
+ possible_direct_owner_path = DataPath.new(possible_direct_owner_path.path[0..-2])
115
119
 
116
- until done
117
- last = data_path.path.last
120
+ owning_entity_class = if possible_direct_owner_path.empty?
121
+ self
122
+ else
123
+ deep_associations[possible_direct_owner_path.to_s]&.target_class
124
+ end
125
+ end until owning_entity_class
118
126
 
119
- if last == :"#"
120
- method = :find_all_by_attribute_containing_any_of
121
- attribute_name = data_path.path[-2]
122
- data_path = DataPath.new(data_path.path[0..-3])
123
- else
124
- method = :find_all_by_attribute_any_of
125
- attribute_name = last
126
- data_path = DataPath.new(data_path.path[0..-2])
127
- end
128
-
129
- containing_entity_class_path = data_path.to_s
130
-
131
- entity_class = if containing_entity_class_path.empty?
132
- done = true
133
- self
134
- else
135
- deep_associations[
136
- containing_entity_class_path
137
- ].target_class
138
- end
139
-
140
- containing_records = entity_class.send(method, attribute_name, containing_records).to_a
141
-
142
- done = true unless containing_records
127
+ if attribute_path.size == 1
128
+ attribute_path = attribute_path.first
143
129
  end
144
130
 
145
- containing_records
131
+ if owning_entity_class == self
132
+ owning_entity_class.find_all_by_attribute(attribute_path, record)
133
+ else
134
+ Enumerator.new do |yielder|
135
+ owners = owning_entity_class.find_all_by_attribute(attribute_path, record)
136
+
137
+ owners.each do |owner|
138
+ that_own(owner, filters).each do |r|
139
+ yielder.yield(r)
140
+ end
141
+ end
142
+ end
143
+ end
146
144
  end
147
145
  end
148
146
  end
@@ -2,7 +2,7 @@ module Foobara
2
2
  module BuiltinTypes
3
3
  module Entity
4
4
  module Validators
5
- class AttributesDeclaration < DetachedEntity::Validators::AttributesDeclaration
5
+ class ModelInstanceIsValid < DetachedEntity::Validators::ModelInstanceIsValid
6
6
  def applicable?(record)
7
7
  record.created? || record.built?
8
8
  end