foobara 0.0.48 → 0.0.50

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7c661c32185af433ba2355ce71bf37524893d00901a6e885ab5bd874339e48b6
4
- data.tar.gz: 8ab10b8b9191bc81548d07269ca8c4906515164aa87a702ac7b944170e2420a7
3
+ metadata.gz: 046fdc3bab52559499e744edbde0ef847e26c4e6107423779351a26acc654619
4
+ data.tar.gz: 56174a565dafcdf3cd03a66e791be3d5a6074bd426c203371b6d7f41fa3a7e12
5
5
  SHA512:
6
- metadata.gz: 3aaff8aa022ea5cf95ab300430576fbf08d813ccd2344630b035bf54372826fda4de76e5b7d9937e70278fcc7b0c23973d4499be25ad1531401b8b82004c153a
7
- data.tar.gz: ffbc1887647b08588f218798cb99ab27af30ece05d4540926cb521a429c3dc9a4d992163802528f9f3a8022a52558e5158ee4b5b13dbe297a2e6036393ec49dd
6
+ metadata.gz: ca08c711d53d11eb7ee073d040163df8bfe23c69b4b8e4c4f9647c6d216578755388b009b6d67e2cf988cc4e043413bfbe8f4f78ecb7690f713191cf00474255
7
+ data.tar.gz: a3b1e726a7295d1a0e4d22ef8f7a8130b39d57a1576f07f3f36bb20347ffce4bde07d6205c9c2853b392f47542ef7c696de57ab02c7c11d463484e3f5eebc779
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## [0.0.50] - 2025-01-22
2
+
3
+ - Fill out more foobara_ model attribute helper methods to further support the ActiveRecordType gem
4
+
1
5
  ## [0.0.48] - 2025-01-17
2
6
 
3
7
  - Add support for foobara_attributes_type to allow ActiveRecordType gem to work
@@ -25,7 +25,11 @@ module Foobara
25
25
  end
26
26
  end
27
27
 
28
- rawish_type_declaration[:defaults] = defaults unless defaults.empty?
28
+ if defaults.empty?
29
+ rawish_type_declaration.delete(:defaults)
30
+ else
31
+ rawish_type_declaration[:defaults] = defaults
32
+ end
29
33
 
30
34
  rawish_type_declaration
31
35
  end
@@ -40,7 +40,11 @@ module Foobara
40
40
  end
41
41
  end
42
42
 
43
- rawish_type_declaration[:required] = required_attributes unless required_attributes.empty?
43
+ if required_attributes.empty?
44
+ rawish_type_declaration.delete(:required)
45
+ else
46
+ rawish_type_declaration[:required] = required_attributes
47
+ end
44
48
 
45
49
  rawish_type_declaration
46
50
  end
@@ -25,6 +25,16 @@ module Foobara
25
25
  @inputs_type
26
26
  end
27
27
 
28
+ def add_inputs(...)
29
+ new_type = type_for_declaration(...)
30
+ new_declaration = TypeDeclarations::Attributes.merge(
31
+ inputs_type.declaration_data,
32
+ new_type.declaration_data
33
+ )
34
+
35
+ inputs new_declaration
36
+ end
37
+
28
38
  def inputs_type
29
39
  return @inputs_type if defined?(@inputs_type)
30
40
 
@@ -5,10 +5,12 @@ module Foobara
5
5
  include Concern
6
6
 
7
7
  module ClassMethods
8
- def associations
9
- @associations ||= construct_associations
8
+ def foobara_associations
9
+ @foobara_associations ||= construct_associations
10
10
  end
11
11
 
12
+ alias associations foobara_associations
13
+
12
14
  def deep_associations
13
15
  @deep_associations ||= begin
14
16
  deep = {}
@@ -20,18 +20,20 @@ module Foobara
20
20
  # :nocov:
21
21
  end
22
22
 
23
- @primary_key_attribute = attribute_name.to_sym
23
+ @foobara_primary_key_attribute = attribute_name.to_sym
24
24
 
25
25
  set_model_type
26
26
  end
27
27
 
28
- def primary_key_attribute
29
- return @primary_key_attribute if @primary_key_attribute
28
+ def foobara_primary_key_attribute
29
+ return @foobara_primary_key_attribute if @foobara_primary_key_attribute
30
30
 
31
31
  unless superclass == DetachedEntity
32
- @primary_key_attribute = superclass.primary_key_attribute
32
+ @foobara_primary_key_attribute = superclass.primary_key_attribute
33
33
  end
34
34
  end
35
+
36
+ alias primary_key_attribute foobara_primary_key_attribute
35
37
  end
36
38
 
37
39
  def primary_key
@@ -23,10 +23,12 @@ module Foobara
23
23
  end
24
24
  end
25
25
 
26
- def primary_key_type
27
- @primary_key_type ||= attributes_type.element_types[primary_key_attribute]
26
+ def foobara_primary_key_type
27
+ @foobara_primary_key_type ||= attributes_type.element_types[primary_key_attribute]
28
28
  end
29
29
 
30
+ alias primary_key_type foobara_primary_key_type
31
+
30
32
  def full_entity_name
31
33
  full_model_name
32
34
  end
@@ -7,7 +7,6 @@ module Foobara
7
7
  include Concerns::Attributes
8
8
  include Concerns::Persistence
9
9
  include Concerns::Initialization
10
- include Concerns::AttributeHelpers
11
10
  include Concerns::Types
12
11
 
13
12
  class << self
@@ -30,6 +30,7 @@ module Foobara
30
30
  "model",
31
31
  "detached_entity",
32
32
  "entity",
33
+ "model_attribute_helpers",
33
34
  "command",
34
35
  "domain_mapper",
35
36
  "persistence",
@@ -102,7 +102,7 @@ module Foobara
102
102
  )
103
103
  end
104
104
 
105
- def attributes_type
105
+ def foobara_attributes_type
106
106
  return @attributes_type if @attributes_type
107
107
 
108
108
  @attributes_type = if model_type
@@ -112,6 +112,8 @@ module Foobara
112
112
  end
113
113
  end
114
114
 
115
+ alias attributes_type foobara_attributes_type
116
+
115
117
  def model_type=(model_type)
116
118
  @model_type = model_type
117
119
 
@@ -0,0 +1,16 @@
1
+ require "date"
2
+ require "time"
3
+ require "bigdecimal"
4
+
5
+ module Foobara
6
+ module ModelAttributeHelpers
7
+ class << self
8
+ def install!
9
+ Model.include Concerns::AttributeHelpers
10
+ Model.include Concerns::AttributeHelperAliases
11
+ Entity.include Concerns::AttributeHelpers
12
+ Entity.include Concerns::AttributeHelperAliases
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,30 @@
1
+ # This is currently the working file, fix this up/move it
2
+
3
+ module Foobara
4
+ module ModelAttributeHelpers
5
+ module Concerns
6
+ module AttributeHelperAliases
7
+ include Foobara::Concern
8
+
9
+ module ClassMethods
10
+ %i[
11
+ attributes_for_update
12
+ type_from_foobara_model_class
13
+ attributes_type_from_foobara_model_class
14
+ primary_key_attribute_from_foobara_model_class
15
+ foobara_model_class_has_primary_key
16
+ attributes_for_create
17
+ attributes_for_aggregate_update
18
+ attributes_for_atom_update
19
+ attributes_for_find_by
20
+ type_declaration_value_at
21
+ ].each do |method_name|
22
+ define_method method_name do |*args, **opts, &block|
23
+ send("foobara_#{method_name}", *args, **opts, &block)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,143 @@
1
+ # delete this file
2
+
3
+ module Foobara
4
+ module ModelAttributeHelpers
5
+ module Concerns
6
+ # TODO: This concern is retroactively designed to be mixed into any entity-like class that can hold an
7
+ # entity-like foobara type.
8
+ # Because we want a subclass of ActiveRecord::Base to be such a target in the case of the
9
+ # foobara-active-record-type class, but because we can't make ActiveRecord::Base a subclass of Entity or
10
+ # DetachedEntity, and also because it makes sense to extend such behavior to foobara model classes,
11
+ # we will implement this as a Concern/mixin with a published expected interface and prefixed methods.
12
+ # This also means it should live in its own project, not here in the entity project.
13
+ # required methods:
14
+ #
15
+ # foobara_type
16
+ # foobara_attributes_type
17
+ # foobara_primary_key_attribute (nil if not an entity type)
18
+ # foobara_primary_key_type (nil if not an entity type)
19
+ # foobara_associations
20
+ module AttributeHelpers
21
+ include Foobara::Concern
22
+
23
+ module ClassMethods
24
+ def foobara_has_primary_key?
25
+ respond_to?(:foobara_primary_key_attribute)
26
+ end
27
+
28
+ def foobara_attributes_for_update(require_primary_key: false)
29
+ foobara_attributes_for_aggregate_update(require_primary_key:)
30
+ end
31
+
32
+ # TODO: we should have metadata on the entity about whether it required a primary key
33
+ # upon creation or not instead of an option here.
34
+ def foobara_attributes_for_create(includes_primary_key: false)
35
+ return foobara_attributes_type if includes_primary_key
36
+ return foobara_attributes_type unless foobara_has_primary_key?
37
+
38
+ declaration = foobara_attributes_type.declaration_data
39
+
40
+ Foobara::TypeDeclarations::Attributes.reject(declaration, foobara_primary_key_attribute)
41
+ end
42
+
43
+ def foobara_attributes_for_aggregate_update(require_primary_key: false, initial: true)
44
+ declaration = foobara_attributes_type.declaration_data
45
+ declaration = Util.deep_dup(declaration)
46
+
47
+ declaration.delete(:defaults)
48
+ declaration.delete(:required)
49
+
50
+ if initial && foobara_has_primary_key?
51
+ if require_primary_key
52
+ declaration[:required] = [foobara_primary_key_attribute]
53
+ else
54
+ TypeDeclarations::Attributes.reject(declaration, foobara_primary_key_attribute)
55
+ end
56
+ end
57
+
58
+ foobara_associations.each_pair do |data_path, type|
59
+ if type.extends?(BuiltinTypes[:entity])
60
+ target_class = type.target_class
61
+
62
+ entry = foobara_type_declaration_value_at(declaration, DataPath.new(data_path).path)
63
+ entry.clear
64
+ entry.merge!(target_class.foobara_attributes_for_aggregate_update(initial: false))
65
+ end
66
+ end
67
+
68
+ declaration
69
+ end
70
+
71
+ def foobara_attributes_for_atom_update(require_primary_key: false)
72
+ declaration = foobara_attributes_type.declaration_data
73
+ declaration = Util.deep_dup(declaration)
74
+
75
+ declaration.delete(:defaults)
76
+
77
+ if foobara_has_primary_key?
78
+ if require_primary_key
79
+ declaration[:required] = [foobara_primary_key_attribute]
80
+ else
81
+ declaration = TypeDeclarations::Attributes.reject(declaration, foobara_primary_key_attribute)
82
+ end
83
+ end
84
+
85
+ # expect all associations to be expressed as primary key values
86
+ # TODO: should we have a special type for encapsulating primary keys types??
87
+ foobara_associations.each_pair do |data_path, type|
88
+ if type.extends?(BuiltinTypes[:entity])
89
+ target_class = type.target_class
90
+ # TODO: do we really need declaration_data? Why cant we use the type directly?
91
+ # TODO: make this work with the type directly for performance reasons.
92
+ primary_key_type_declaration = target_class.foobara_primary_key_type.declaration_data
93
+ entry = foobara_type_declaration_value_at(declaration, DataPath.new(data_path).path)
94
+ entry.clear
95
+ entry.merge!(primary_key_type_declaration)
96
+ end
97
+ end
98
+
99
+ declaration
100
+ end
101
+
102
+ def foobara_attributes_for_find_by
103
+ element_type_declarations = {}
104
+
105
+ foobara_attributes_type.element_types.each_pair do |attribute_name, attribute_type|
106
+ element_type_declarations[attribute_name] = attribute_type.reference_or_declaration_data
107
+ end
108
+
109
+ handler = Domain.global.foobara_type_builder.handler_for_class(
110
+ TypeDeclarations::Handlers::ExtendAttributesTypeDeclaration
111
+ )
112
+
113
+ handler.desugarize(
114
+ type: "::attributes",
115
+ element_type_declarations:
116
+ )
117
+ end
118
+
119
+ private
120
+
121
+ def foobara_type_declaration_value_at(declaration, path_parts)
122
+ return declaration if path_parts.empty?
123
+
124
+ path_part, *path_parts = path_parts
125
+
126
+ declaration = case path_part
127
+ when :"#"
128
+ declaration[:element_type_declaration]
129
+ when Symbol, Integer
130
+ declaration[:element_type_declarations][path_part]
131
+ else
132
+ # :nocov:
133
+ raise "Bad path part #{path_part}"
134
+ # :nocov:
135
+ end
136
+
137
+ foobara_type_declaration_value_at(declaration, path_parts)
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
@@ -21,12 +21,55 @@ module Foobara
21
21
  end
22
22
  end
23
23
 
24
- {
24
+ handler = Domain.global.foobara_type_builder.handler_for_class(
25
+ TypeDeclarations::Handlers::ExtendAttributesTypeDeclaration
26
+ )
27
+
28
+ handler.desugarize(
25
29
  type: "::attributes",
26
30
  element_type_declarations:,
27
31
  required:,
28
32
  defaults:
29
- }
33
+ )
34
+ end
35
+
36
+ def reject(declaration, *keys)
37
+ declaration = Util.deep_dup(declaration)
38
+
39
+ element_type_declarations = declaration[:element_type_declarations]
40
+ required = declaration[:required]
41
+ defaults = declaration[:defaults]
42
+
43
+ changed = false
44
+
45
+ keys.flatten.each do |key|
46
+ key = key.to_sym
47
+
48
+ if element_type_declarations.key?(key)
49
+ changed = true
50
+ element_type_declarations.delete(key)
51
+ end
52
+
53
+ if required&.include?(key)
54
+ changed = true
55
+ required.delete(key)
56
+ end
57
+
58
+ if defaults&.key?(key)
59
+ changed = true
60
+ defaults.delete(key)
61
+ end
62
+ end
63
+
64
+ if changed
65
+ handler = Domain.global.foobara_type_builder.handler_for_class(
66
+ TypeDeclarations::Handlers::ExtendAttributesTypeDeclaration
67
+ )
68
+
69
+ handler.desugarize(declaration)
70
+ else
71
+ declaration
72
+ end
30
73
  end
31
74
  end
32
75
  end
@@ -47,7 +47,6 @@ module Foobara
47
47
 
48
48
  def _to_declaration(&)
49
49
  instance_eval(&)
50
- _prune_type_declaration
51
50
  _type_declaration
52
51
  end
53
52
 
@@ -163,30 +162,20 @@ module Foobara
163
162
  end
164
163
 
165
164
  def _add_to_required(attribute_name)
165
+ _type_declaration[:required] ||= []
166
166
  _type_declaration[:required] << attribute_name.to_sym
167
167
  end
168
168
 
169
169
  def _add_to_defaults(attribute_name, value)
170
+ _type_declaration[:defaults] ||= {}
170
171
  _type_declaration[:defaults][attribute_name.to_sym] = value
171
172
  end
172
173
 
173
- def _prune_type_declaration
174
- if _type_declaration[:required].empty?
175
- _type_declaration.delete(:required)
176
- end
177
-
178
- if _type_declaration[:defaults].empty?
179
- _type_declaration.delete(:defaults)
180
- end
181
- end
182
-
183
174
  def _type_declaration
184
175
  @_type_declaration ||= begin
185
176
  sugar = {
186
177
  type: "::attributes",
187
- element_type_declarations: {},
188
- required: [],
189
- defaults: {}
178
+ element_type_declarations: {}
190
179
  }
191
180
 
192
181
  handler = Domain.current.foobara_type_builder.handler_for_class(Handlers::ExtendAttributesTypeDeclaration)
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.48
4
+ version: 0.0.50
5
5
  platform: ruby
6
6
  authors:
7
7
  - Miles Georgi
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-01-18 00:00:00.000000000 Z
10
+ date: 2025-01-22 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: bigdecimal
@@ -219,7 +219,6 @@ files:
219
219
  - projects/domain_mapper/src/domain_mapper.rb
220
220
  - projects/domain_mapper/src/domain_mapper_lookups.rb
221
221
  - projects/entity/lib/foobara/entity.rb
222
- - projects/entity/src/concerns/attribute_helpers.rb
223
222
  - projects/entity/src/concerns/attributes.rb
224
223
  - projects/entity/src/concerns/callbacks.rb
225
224
  - projects/entity/src/concerns/initialization.rb
@@ -289,6 +288,9 @@ files:
289
288
  - projects/model/src/extensions/type_declarations/handlers/extend_registered_model_type_declaration/to_type_transformer.rb
290
289
  - projects/model/src/extensions/type_declarations/handlers/registered_type_declaration/model_class_desugarizer.rb
291
290
  - projects/model/src/model.rb
291
+ - projects/model_attribute_helpers/lib/foobara/model_attribute_helpers.rb
292
+ - projects/model_attribute_helpers/src/attribute_helper_aliases.rb
293
+ - projects/model_attribute_helpers/src/attribute_helpers.rb
292
294
  - projects/monorepo/lib/foobara/monorepo.rb
293
295
  - projects/monorepo/lib/foobara/monorepo/project.rb
294
296
  - projects/namespace/lib/foobara/namespace.rb
@@ -415,6 +417,7 @@ require_paths:
415
417
  - "./projects/in_memory_crud_driver_minimal/lib"
416
418
  - "./projects/manifest/lib"
417
419
  - "./projects/model/lib"
420
+ - "./projects/model_attribute_helpers/lib"
418
421
  - "./projects/monorepo/lib"
419
422
  - "./projects/namespace/lib"
420
423
  - "./projects/persistence/lib"
@@ -1,133 +0,0 @@
1
- module Foobara
2
- class Entity < DetachedEntity
3
- module Concerns
4
- module AttributeHelpers
5
- include Foobara::Concern
6
-
7
- module ClassMethods
8
- def attributes_for_update
9
- attributes_for_aggregate_update
10
- end
11
-
12
- # TODO: we should have metadata on the entity about whether it required a primary key
13
- # upon creation or not instead of an option here.
14
- def attributes_for_create(includes_primary_key: false)
15
- return attributes_type if includes_primary_key
16
-
17
- declaration = attributes_type.declaration_data
18
- # TODO: just slice out the element type declarations
19
- declaration = Util.deep_dup(declaration)
20
-
21
- if declaration.key?(:required) && declaration[:required].include?(primary_key_attribute)
22
- declaration[:required].delete(primary_key_attribute)
23
- end
24
-
25
- if declaration.key?(:defaults) && declaration[:defaults].include?(primary_key_attribute)
26
- declaration[:defaults].delete(primary_key_attribute)
27
- end
28
-
29
- if declaration.key?(:element_type_declarations)
30
- if declaration[:element_type_declarations].key?(primary_key_attribute)
31
- declaration[:element_type_declarations].delete(primary_key_attribute)
32
- end
33
- end
34
-
35
- handler = Domain.global.foobara_type_builder.handler_for_class(
36
- TypeDeclarations::Handlers::ExtendAttributesTypeDeclaration
37
- )
38
-
39
- handler.desugarize(declaration)
40
- end
41
-
42
- def attributes_for_aggregate_update(initial = true)
43
- declaration = attributes_type.declaration_data
44
- # TODO: just slice out the element type declarations
45
- declaration = Util.deep_dup(declaration)
46
-
47
- declaration.delete(:defaults)
48
- declaration.delete(:required)
49
-
50
- if initial
51
- declaration[:required] = [primary_key_attribute]
52
- end
53
-
54
- associations.each_pair do |data_path, type|
55
- if type.extends?(BuiltinTypes[:entity])
56
- target_class = type.target_class
57
-
58
- entry = type_declaration_value_at(declaration, DataPath.new(data_path).path)
59
- entry.clear
60
- entry.merge!(target_class.attributes_for_aggregate_update(false))
61
- end
62
- end
63
-
64
- declaration
65
- end
66
-
67
- def attributes_for_atom_update
68
- declaration = attributes_type.declaration_data
69
- # TODO: just slice out the element type declarations
70
- declaration = Util.deep_dup(declaration)
71
-
72
- declaration.delete(:defaults)
73
- declaration[:required] = [primary_key_attribute]
74
-
75
- # expect all associations to be expressed as primary key values
76
- # TODO: should we have a special type for encapsulating primary keys types??
77
- associations.each_pair do |data_path, type|
78
- if type.extends?(BuiltinTypes[:entity])
79
- target_class = type.target_class
80
- # TODO: do we really need declaration_data? Why cant we use the type directly?
81
- # TODO: make this work with the type directly for performance reasons.
82
- primary_key_type_declaration = target_class.primary_key_type.declaration_data
83
- entry = type_declaration_value_at(declaration, DataPath.new(data_path).path)
84
- entry.clear
85
- entry.merge!(primary_key_type_declaration)
86
- end
87
- end
88
-
89
- declaration
90
- end
91
-
92
- def attributes_for_find_by
93
- element_type_declarations = {}
94
-
95
- attributes_type.element_types.each_pair do |attribute_name, attribute_type|
96
- element_type_declarations[attribute_name] = attribute_type.reference_or_declaration_data
97
- end
98
-
99
- handler = Domain.global.foobara_type_builder.handler_for_class(
100
- TypeDeclarations::Handlers::ExtendAttributesTypeDeclaration
101
- )
102
-
103
- handler.desugarize(
104
- type: "::attributes",
105
- element_type_declarations:
106
- )
107
- end
108
-
109
- private
110
-
111
- def type_declaration_value_at(declaration, path_parts)
112
- return declaration if path_parts.empty?
113
-
114
- path_part, *path_parts = path_parts
115
-
116
- declaration = case path_part
117
- when :"#"
118
- declaration[:element_type_declaration]
119
- when Symbol, Integer
120
- declaration[:element_type_declarations][path_part]
121
- else
122
- # :nocov:
123
- raise "Bad path part #{path_part}"
124
- # :nocov:
125
- end
126
-
127
- type_declaration_value_at(declaration, path_parts)
128
- end
129
- end
130
- end
131
- end
132
- end
133
- end