forest_liana 9.14.1 → 9.14.3
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/app/services/forest_liana/base_getter.rb +2 -0
- data/app/services/forest_liana/has_many_getter.rb +2 -3
- data/app/services/forest_liana/resources_getter.rb +20 -24
- data/app/services/forest_liana/schema_adapter.rb +16 -2
- data/app/services/forest_liana/schema_utils.rb +22 -0
- data/lib/forest_liana/version.rb +1 -1
- data/spec/services/forest_liana/resources_getter_spec.rb +20 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 82aa2dffa179fa0be6398321388077e3ad04f66583969c4fbb68112983dcd5d6
|
4
|
+
data.tar.gz: 9e84f6554455e681cf00ca15cee8bb337c4e9ae22289e11959caa889297a0ee1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0cd4367dcab7b965bccf0b49e289509ce0b97b9763491b67273444c06db7a226d4c1fc019da63167567de45afcb752fb76751b4512d0c5ff0754f217679bac0d
|
7
|
+
data.tar.gz: 67eb9531fc902db2a9db22cffb6b53ba2f5ff9635f67ef5668db5b107102fb2ddac46b901fa56a7ac245c0fff3215c064b66cede4c37ea819985ce78539346dd
|
@@ -47,6 +47,8 @@ module ForestLiana
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def separate_database?(resource, association)
|
50
|
+
return false if SchemaUtils.polymorphic?(association)
|
51
|
+
|
50
52
|
target_model_connection = association.klass.connection
|
51
53
|
target_model_database = target_model_connection.current_database if target_model_connection.respond_to? :current_database
|
52
54
|
resource_connection = resource.connection
|
@@ -62,9 +62,8 @@ module ForestLiana
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def field_names_requested
|
65
|
-
|
66
|
-
|
67
|
-
.map { |name| name.to_sym }
|
65
|
+
fields = @params.dig(:fields, @collection_name)
|
66
|
+
Array(fields&.split(',')).map(&:to_sym)
|
68
67
|
end
|
69
68
|
|
70
69
|
def model_association
|
@@ -32,7 +32,7 @@ module ForestLiana
|
|
32
32
|
def perform
|
33
33
|
polymorphic_association, preload_loads = analyze_associations(@resource)
|
34
34
|
includes = @includes.uniq - polymorphic_association - preload_loads - @optional_includes
|
35
|
-
has_smart_fields =
|
35
|
+
has_smart_fields = Array(@params.dig(:fields, @collection_name)&.split(',')).any? do |field|
|
36
36
|
ForestLiana::SchemaHelper.is_smart_field?(@resource, field)
|
37
37
|
end
|
38
38
|
|
@@ -58,7 +58,7 @@ module ForestLiana
|
|
58
58
|
records = @records.offset(offset).limit(limit).to_a
|
59
59
|
polymorphic_association, preload_loads = analyze_associations(@resource)
|
60
60
|
|
61
|
-
if polymorphic_association && Rails::VERSION::MAJOR >= 7
|
61
|
+
if polymorphic_association.any? && Rails::VERSION::MAJOR >= 7
|
62
62
|
preloader = ActiveRecord::Associations::Preloader.new(records: records, associations: polymorphic_association)
|
63
63
|
preloader.loaders
|
64
64
|
preloader.branches.each do |branch|
|
@@ -85,7 +85,6 @@ module ForestLiana
|
|
85
85
|
next unless separate_database?(@resource, association)
|
86
86
|
|
87
87
|
columns = columns_for_cross_database_association(association_name)
|
88
|
-
|
89
88
|
if association.macro == :belongs_to
|
90
89
|
foreign_key = association.foreign_key
|
91
90
|
primary_key = association.klass.primary_key
|
@@ -125,34 +124,27 @@ module ForestLiana
|
|
125
124
|
end
|
126
125
|
|
127
126
|
def columns_for_cross_database_association(association_name)
|
128
|
-
return [:id] unless @params[:fields].present?
|
129
|
-
|
130
|
-
fields = @params[:fields][association_name.to_s]
|
131
|
-
return [:id] unless fields
|
132
|
-
|
133
|
-
base_fields = fields.split(',').map(&:strip).map(&:to_sym) | [:id]
|
134
|
-
|
135
127
|
association = @resource.reflect_on_association(association_name)
|
136
|
-
extra_key = association.foreign_key
|
137
128
|
|
138
|
-
#
|
139
|
-
|
140
|
-
base_fields << extra_key if association.macro == :has_one
|
129
|
+
# Always include all columns of the associated model to avoid missing attribute errors
|
130
|
+
columns = association.klass.column_names.map(&:to_sym)
|
141
131
|
|
142
|
-
|
132
|
+
# Ensure the foreign key is present for manual binding (especially for has_one)
|
133
|
+
columns << association.foreign_key.to_sym if association.macro == :has_one
|
134
|
+
|
135
|
+
columns.uniq
|
143
136
|
end
|
144
137
|
|
145
138
|
def compute_includes
|
146
139
|
associations_has_one = ForestLiana::QueryHelper.get_one_associations(@resource)
|
140
|
+
|
147
141
|
@optional_includes = []
|
148
|
-
if @field_names_requested
|
142
|
+
if @field_names_requested && @params['searchExtended'].to_i != 1
|
149
143
|
includes = associations_has_one.map do |association|
|
150
144
|
association_name = association.name.to_s
|
151
145
|
|
152
|
-
|
153
|
-
|
154
|
-
@params[:fields][association_name].split(',').include?(association.klass.primary_key)
|
155
|
-
|
146
|
+
fields = @params[:fields]&.[](association_name)&.split(',')
|
147
|
+
if fields&.size == 1 && fields.include?(association.klass.primary_key)
|
156
148
|
@field_names_requested << association.foreign_key
|
157
149
|
@optional_includes << association.name
|
158
150
|
end
|
@@ -175,7 +167,10 @@ module ForestLiana
|
|
175
167
|
|
176
168
|
@includes = (includes & @field_names_requested).concat(includes_for_smart_search)
|
177
169
|
else
|
178
|
-
@includes = associations_has_one
|
170
|
+
@includes = associations_has_one
|
171
|
+
# Avoid eager loading has_one associations pointing to a different database as ORM can't join cross databases
|
172
|
+
.reject { |association| separate_database?(@resource, association) }
|
173
|
+
.map(&:name)
|
179
174
|
end
|
180
175
|
end
|
181
176
|
|
@@ -194,7 +189,7 @@ module ForestLiana
|
|
194
189
|
end
|
195
190
|
|
196
191
|
def field_names_requested
|
197
|
-
return
|
192
|
+
return [] unless @params.dig(:fields, @collection_name)
|
198
193
|
|
199
194
|
associations_for_query = extract_associations_from_filter
|
200
195
|
associations_for_query << @params[:sort].split('.').first.to_sym if @params[:sort]&.include?('.')
|
@@ -335,11 +330,12 @@ module ForestLiana
|
|
335
330
|
select << "#{@resource.table_name}.#{association.foreign_key}"
|
336
331
|
end
|
337
332
|
|
338
|
-
|
333
|
+
fields = @params[:fields]&.[](path)&.split(',')
|
334
|
+
if fields
|
339
335
|
association = get_one_association(path)
|
340
336
|
table_name = association.table_name
|
341
337
|
|
342
|
-
|
338
|
+
fields.each do |association_path|
|
343
339
|
if ForestLiana::SchemaHelper.is_smart_field?(association.klass, association_path)
|
344
340
|
association.klass.attribute_names.each { |attribute| select << "#{table_name}.#{attribute}" }
|
345
341
|
else
|
@@ -278,7 +278,13 @@ module ForestLiana
|
|
278
278
|
field[:field] = association.name
|
279
279
|
field[:inverse_of] = inverse_of(association)
|
280
280
|
field[:relationship] = get_relationship_type(association)
|
281
|
-
|
281
|
+
|
282
|
+
ForestLiana::SchemaUtils.disable_filter_and_sort_if_cross_db!(
|
283
|
+
field,
|
284
|
+
association.name.to_s,
|
285
|
+
ForestLiana.name_for(@model)
|
286
|
+
)
|
287
|
+
# NOTICE: Create the fields of hasOne, HasMany, … relationships.
|
282
288
|
else
|
283
289
|
collection.fields << get_schema_for_association(association)
|
284
290
|
end
|
@@ -346,7 +352,7 @@ module ForestLiana
|
|
346
352
|
end
|
347
353
|
|
348
354
|
def get_schema_for_association(association)
|
349
|
-
{
|
355
|
+
opts ={
|
350
356
|
field: association.name.to_s,
|
351
357
|
type: get_type_for_association(association),
|
352
358
|
relationship: get_relationship_type(association),
|
@@ -363,6 +369,14 @@ module ForestLiana
|
|
363
369
|
widget: nil,
|
364
370
|
validations: []
|
365
371
|
}
|
372
|
+
|
373
|
+
ForestLiana::SchemaUtils.disable_filter_and_sort_if_cross_db!(
|
374
|
+
opts,
|
375
|
+
association.name.to_s,
|
376
|
+
ForestLiana.name_for(@model)
|
377
|
+
)
|
378
|
+
|
379
|
+
opts
|
366
380
|
end
|
367
381
|
|
368
382
|
def get_relationship_type(association)
|
@@ -126,5 +126,27 @@ module ForestLiana
|
|
126
126
|
def self.is_active_type? model
|
127
127
|
Object.const_defined?('ActiveType::Object') && model < ActiveType::Object
|
128
128
|
end
|
129
|
+
|
130
|
+
def self.disable_filter_and_sort_if_cross_db!(opts, name, collection_name)
|
131
|
+
return unless opts[:reference]
|
132
|
+
|
133
|
+
assoc_name = opts[:reference].split('.').first&.underscore&.to_sym || name
|
134
|
+
model = find_model_from_collection_name(collection_name)
|
135
|
+
return unless model
|
136
|
+
|
137
|
+
association = model.reflect_on_association(assoc_name)
|
138
|
+
return unless association
|
139
|
+
return if polymorphic?(association)
|
140
|
+
|
141
|
+
model_db = model.connection_db_config.database
|
142
|
+
assoc_db = association.klass.connection_db_config.database
|
143
|
+
|
144
|
+
if model_db != assoc_db
|
145
|
+
opts[:is_filterable] = false
|
146
|
+
opts[:is_sortable] = false
|
147
|
+
end
|
148
|
+
rescue => e
|
149
|
+
FOREST_LOGGER.warn("Could not evaluate cross-db association for #{name}: #{e.message}")
|
150
|
+
end
|
129
151
|
end
|
130
152
|
end
|
data/lib/forest_liana/version.rb
CHANGED
@@ -572,6 +572,26 @@ module ForestLiana
|
|
572
572
|
expect(records.second.name).to eq 'Treasure'
|
573
573
|
end
|
574
574
|
end
|
575
|
+
|
576
|
+
describe '#perform' do
|
577
|
+
let(:resource) { User }
|
578
|
+
let(:fields) { nil }
|
579
|
+
let(:sort) { nil }
|
580
|
+
let(:filters) { nil }
|
581
|
+
|
582
|
+
it 'does not raise an error when params[:fields] is nil' do
|
583
|
+
expect {
|
584
|
+
getter.perform
|
585
|
+
}.not_to raise_error
|
586
|
+
|
587
|
+
records = getter.records
|
588
|
+
count = getter.count
|
589
|
+
|
590
|
+
expect(records).to all(be_a(User))
|
591
|
+
expect(count).to eq User.count
|
592
|
+
end
|
593
|
+
end
|
594
|
+
|
575
595
|
end
|
576
596
|
end
|
577
597
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: forest_liana
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 9.14.
|
4
|
+
version: 9.14.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sandro Munda
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-06-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|