foobara 0.0.102 → 0.0.104
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 +11 -0
- data/projects/command/src/command_pattern_implementation/concerns/transactions.rb +4 -0
- data/projects/command/src/transformed_command.rb +13 -4
- data/projects/command_connectors/src/command_connector.rb +1 -1
- data/projects/detached_entity/src/concerns/associations.rb +10 -5
- data/projects/foobara/lib/foobara/all.rb +1 -1
- data/projects/manifest/src/foobara/manifest/command.rb +3 -1
- data/projects/model/src/concerns/types.rb +6 -1
- data/projects/persistence/src/entity_attributes_crud_driver.rb +27 -16
- data/projects/persistence/src/entity_base/transaction_table.rb +0 -2
- data/projects/types/src/type.rb +11 -2
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: be41d74ce30f423271c0b160d955d9ea7422e5d4337ab1d3c17deb0dae395d53
|
4
|
+
data.tar.gz: 51f8a06a9468870be7e2db0dd2116a8bca141852f27d462b4ce01b74df490710
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 49e75de0f35a1a1eb257efd6e1304ed39d340ee8531e1b768ca8fc58ab4a0bc8e4422e3c50c379565c899708ac7a0768aa87aca326240933771147c285212894
|
7
|
+
data.tar.gz: 6d3234ee0c549fd91d21fe11e16968a5fe56da263eafa90474b20baa2b091ec33b57b439891eeeccf7149e4a9d1995ebab8a3ecc864e1eb796a1a8bef60f1d63
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
# [0.0.104] - 2025-04-17
|
2
|
+
|
3
|
+
- Fix manifest bug when command has no possible errors
|
4
|
+
|
5
|
+
# [0.0.103] - 2025-04-17
|
6
|
+
|
7
|
+
- Fix bugs in complicated entity query calls involving mixtures of models/records/primary keys/attributes
|
8
|
+
- Fix bugs re: .construct_associations/_deep_associations resulting in terribad performance in some projects
|
9
|
+
- Allow lambdas to be used as allowed rules
|
10
|
+
- Improve .delegate_attribute interface
|
11
|
+
|
1
12
|
# [0.0.102] - 2025-04-13
|
2
13
|
|
3
14
|
- Extract ThreadParent to its own repository/gem
|
@@ -35,6 +35,10 @@ module Foobara
|
|
35
35
|
entity_classes += Entity.construct_associations(
|
36
36
|
result_type
|
37
37
|
).values.uniq.map(&:target_class)
|
38
|
+
|
39
|
+
if result_type.extends?(BuiltinTypes[:entity])
|
40
|
+
entity_classes << result_type.target_class
|
41
|
+
end
|
38
42
|
end
|
39
43
|
|
40
44
|
entity_classes += entity_classes.uniq.map do |entity_class|
|
@@ -556,9 +556,7 @@ module Foobara
|
|
556
556
|
|
557
557
|
if rule
|
558
558
|
command.after_load_records do |command:, **|
|
559
|
-
|
560
|
-
# TODO: raise exception here if rule.lambda? is true, if this starts becoming a common error
|
561
|
-
is_allowed = instance_eval(&rule)
|
559
|
+
is_allowed = instance_exec(&rule)
|
562
560
|
|
563
561
|
unless is_allowed
|
564
562
|
explanation = allowed_rule.explanation
|
@@ -568,7 +566,18 @@ module Foobara
|
|
568
566
|
end
|
569
567
|
|
570
568
|
if explanation.nil?
|
571
|
-
|
569
|
+
source = begin
|
570
|
+
allowed_rule.block.source
|
571
|
+
rescue MethodSource::SourceNotFoundError
|
572
|
+
# This path is hit if the way the source code is extracted
|
573
|
+
# doesn't result in valid Ruby, for example, as part of a hash such as:
|
574
|
+
# allowed_rule: -> () { whatever?(something) },
|
575
|
+
# :nocov:
|
576
|
+
allowed_rule.block.source_location.join(":")
|
577
|
+
# :nocov:
|
578
|
+
end
|
579
|
+
|
580
|
+
explanation = source || "No explanation."
|
572
581
|
end
|
573
582
|
|
574
583
|
error = CommandConnector::NotAllowedError.new(rule_symbol: rule.symbol, explanation:)
|
@@ -374,7 +374,7 @@ module Foobara
|
|
374
374
|
request_command = request.command
|
375
375
|
|
376
376
|
request_command.after_load_records do |command:, **|
|
377
|
-
authenticated_user = request.
|
377
|
+
authenticated_user = request.instance_exec(&authenticator)
|
378
378
|
|
379
379
|
request_command.authenticated_user = authenticated_user
|
380
380
|
|
@@ -154,8 +154,13 @@ module Foobara
|
|
154
154
|
def construct_associations(
|
155
155
|
type = attributes_type,
|
156
156
|
path = DataPath.new,
|
157
|
-
result = {}
|
157
|
+
result = {},
|
158
|
+
initial: true
|
158
159
|
)
|
160
|
+
if initial && type.extends?(BuiltinTypes[:detached_entity])
|
161
|
+
return construct_associations(type.element_types, path, result, initial: false)
|
162
|
+
end
|
163
|
+
|
159
164
|
remove_sensitive = TypeDeclarations.foobara_manifest_context_remove_sensitive?
|
160
165
|
|
161
166
|
if type.extends?(BuiltinTypes[:entity])
|
@@ -171,7 +176,7 @@ module Foobara
|
|
171
176
|
end
|
172
177
|
|
173
178
|
element_types&.each&.with_index do |element_type, index|
|
174
|
-
construct_associations(element_type, path.append(index), result)
|
179
|
+
construct_associations(element_type, path.append(index), result, initial: false)
|
175
180
|
end
|
176
181
|
elsif type.extends?(BuiltinTypes[:array])
|
177
182
|
# TODO: what to do about an associative array type?? Unclear how to make a key from that...
|
@@ -179,7 +184,7 @@ module Foobara
|
|
179
184
|
element_type = type.element_type
|
180
185
|
|
181
186
|
if element_type && (!remove_sensitive || !element_type.sensitive?)
|
182
|
-
construct_associations(element_type, path.append(:"#"), result)
|
187
|
+
construct_associations(element_type, path.append(:"#"), result, initial: false)
|
183
188
|
end
|
184
189
|
elsif type.extends?(BuiltinTypes[:attributes]) # TODO: matches attributes itself instead of only subtypes
|
185
190
|
type.element_types.each_pair do |attribute_name, element_type|
|
@@ -187,7 +192,7 @@ module Foobara
|
|
187
192
|
next
|
188
193
|
end
|
189
194
|
|
190
|
-
construct_associations(element_type, path.append(attribute_name), result)
|
195
|
+
construct_associations(element_type, path.append(attribute_name), result, initial: false)
|
191
196
|
end
|
192
197
|
elsif type.extends?(BuiltinTypes[:model])
|
193
198
|
target_class = type.target_class
|
@@ -196,7 +201,7 @@ module Foobara
|
|
196
201
|
attributes_type = target_class.send(method)
|
197
202
|
|
198
203
|
if !remove_sensitive || !attributes_type.sensitive?
|
199
|
-
construct_associations(attributes_type, path, result)
|
204
|
+
construct_associations(attributes_type, path, result, initial: false)
|
200
205
|
end
|
201
206
|
elsif type.extends?(BuiltinTypes[:associative_array])
|
202
207
|
# not going to bother testing this for now
|
@@ -3,6 +3,8 @@ module Foobara
|
|
3
3
|
class Command < BaseManifest
|
4
4
|
self.category_symbol = :command
|
5
5
|
|
6
|
+
optional_key :possible_errors
|
7
|
+
|
6
8
|
def requires_authentication?
|
7
9
|
!!self[:requires_authentication]
|
8
10
|
end
|
@@ -30,7 +32,7 @@ module Foobara
|
|
30
32
|
end
|
31
33
|
|
32
34
|
def possible_errors
|
33
|
-
super.keys.to_h do |key|
|
35
|
+
(super || {}).keys.to_h do |key|
|
34
36
|
[key, PossibleError.new(root_manifest, [*path, :possible_errors, key])]
|
35
37
|
end
|
36
38
|
end
|
@@ -173,11 +173,16 @@ module Foobara
|
|
173
173
|
|
174
174
|
def delegate_attributes(delegates)
|
175
175
|
delegates.each_pair do |attribute_name, delegate_info|
|
176
|
-
|
176
|
+
data_path = DataPath.for(delegate_info[:data_path])
|
177
|
+
delegate_attribute(attribute_name, data_path, writer: delegate_info[:writer])
|
177
178
|
end
|
178
179
|
end
|
179
180
|
|
180
181
|
def delegate_attribute(attribute_name, data_path, writer: false)
|
182
|
+
if data_path.is_a?(::Symbol) || data_path.is_a?(::String)
|
183
|
+
data_path = [data_path, attribute_name]
|
184
|
+
end
|
185
|
+
|
181
186
|
data_path = DataPath.for(data_path)
|
182
187
|
|
183
188
|
delegate_manifest = { data_path: data_path.to_s }
|
@@ -1,4 +1,5 @@
|
|
1
1
|
module Foobara
|
2
|
+
# Might be best to rename this to CrudDrivers or CrudDriver instead of Persistence?
|
2
3
|
module Persistence
|
3
4
|
class EntityAttributesCrudDriver
|
4
5
|
attr_accessor :raw_connection, :tables
|
@@ -156,29 +157,39 @@ module Foobara
|
|
156
157
|
|
157
158
|
def matches_attributes_filter?(attributes, attributes_filter)
|
158
159
|
attributes_filter.all? do |attribute_name_or_path, value|
|
159
|
-
|
160
|
+
value = normalize_attribute_filter_value(value)
|
160
161
|
|
161
162
|
if attribute_name_or_path.is_a?(::Array)
|
162
163
|
values = DataPath.values_at(attribute_name_or_path, attributes)
|
163
164
|
|
164
|
-
|
165
|
-
|
166
|
-
else
|
167
|
-
type ||= entity_class.model_type.type_at_path(attribute_name_or_path)
|
168
|
-
if type.extends?(:detached_entity)
|
169
|
-
values.any? do |v|
|
170
|
-
value.primary_key == v
|
171
|
-
end
|
172
|
-
end
|
165
|
+
values.any? do |attribute_value|
|
166
|
+
normalize_attribute_filter_value(attribute_value) == value
|
173
167
|
end
|
174
|
-
elsif attributes[attribute_name_or_path] == value
|
175
|
-
true
|
176
168
|
else
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
169
|
+
attribute_value = attributes[attribute_name_or_path]
|
170
|
+
normalize_attribute_filter_value(attribute_value) == value
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def normalize_attribute_filter_value(value)
|
176
|
+
case value
|
177
|
+
when ::Array
|
178
|
+
value.map { |v| normalize_attribute_filter_value(v) }
|
179
|
+
when ::Hash
|
180
|
+
value.to_h do |k, v|
|
181
|
+
[normalize_attribute_filter_value(k), normalize_attribute_filter_value(v)]
|
182
|
+
end
|
183
|
+
when DetachedEntity
|
184
|
+
if value.persisted?
|
185
|
+
normalize_attribute_filter_value(value.primary_key)
|
186
|
+
else
|
187
|
+
value
|
181
188
|
end
|
189
|
+
when Model
|
190
|
+
normalize_attribute_filter_value(value.attributes)
|
191
|
+
else
|
192
|
+
value
|
182
193
|
end
|
183
194
|
end
|
184
195
|
|
data/projects/types/src/type.rb
CHANGED
@@ -20,8 +20,6 @@ module Foobara
|
|
20
20
|
:validators,
|
21
21
|
:element_processors,
|
22
22
|
:structure_count,
|
23
|
-
:element_types,
|
24
|
-
:element_type,
|
25
23
|
:is_builtin,
|
26
24
|
:raw_declaration_data,
|
27
25
|
:name,
|
@@ -33,6 +31,9 @@ module Foobara
|
|
33
31
|
|
34
32
|
attr_reader :type_symbol
|
35
33
|
|
34
|
+
attr_writer :element_types,
|
35
|
+
:element_type
|
36
|
+
|
36
37
|
def initialize(
|
37
38
|
*,
|
38
39
|
target_classes:,
|
@@ -83,6 +84,14 @@ module Foobara
|
|
83
84
|
sensitive_exposed
|
84
85
|
end
|
85
86
|
|
87
|
+
def element_type
|
88
|
+
@element_type || base_type&.element_type
|
89
|
+
end
|
90
|
+
|
91
|
+
def element_types
|
92
|
+
@element_types || base_type&.element_types
|
93
|
+
end
|
94
|
+
|
86
95
|
def has_sensitive_types?
|
87
96
|
return true if sensitive?
|
88
97
|
|