forest_liana 9.11.3 → 9.12.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dcd40a6f023ba4a2a7eddd15891ac11743dea8fee0df3378c42e604afbfe8c7e
4
- data.tar.gz: 61ceac08bd477c79ea3d6284114b6a9a08f2514758378f4f7a96c3845efd4f8f
3
+ metadata.gz: 41634384199110d9a502915f8257c2e3ae3bb42553138cc3d178420de4ad2dea
4
+ data.tar.gz: 2c8ddb09bf770fd5f0dc8a051a0403a7caca8077becadf49444d11eede44eaab
5
5
  SHA512:
6
- metadata.gz: e09c8a0a86cee9b238e35057b0e29e5b842fcf0a2a1380a57fb10bf00c9c2cf6cb5cf16bb9908d72fc4219966efa910742de673e5d0f9cd6696bbd83724d4f67
7
- data.tar.gz: 24ecaa8c8a9442ec3c677bb71f47dbf8a120cba326732f202264869d1a3188265a30caa14054ffbd13c218deb6b13294ef997f60d83f0f347faccbc60d32bc98
6
+ metadata.gz: 5c25ddcb57957aa97d0e2fbb5a480a95821fb73d379ad3df207b6be05abc12e8181be943fca1845f499a14ba2aaa7df7e01df80d67eb272579cc490be652ba4b
7
+ data.tar.gz: 055f53038f537efca379093b048376ac044a1eb8e6c65a0305a7643fa95b2bd74313d7b9258d1daef6a21e62da40e48bb30db0498ee2bc85b8f284815237aa17
@@ -30,7 +30,20 @@ module ForestLiana
30
30
  end
31
31
 
32
32
  def perform
33
- @records = optimize_record_loading(@resource, @records)
33
+ polymorphic_association, preload_loads = analyze_associations(@resource)
34
+ includes = @includes.uniq - polymorphic_association - preload_loads
35
+ has_smart_fields = @params[:fields][@collection_name].split(',').any? do |field|
36
+ ForestLiana::SchemaHelper.is_smart_field?(@resource, field)
37
+ end
38
+
39
+ if includes.empty? || has_smart_fields
40
+ @records = optimize_record_loading(@resource, @records)
41
+ else
42
+ select = compute_select_fields
43
+ @records = optimize_record_loading(@resource, @records).references(includes).select(*select)
44
+ end
45
+
46
+ @records
34
47
  end
35
48
 
36
49
  def count
@@ -210,5 +223,29 @@ module ForestLiana
210
223
  def pagination?
211
224
  @params[:page]&.dig(:number)
212
225
  end
226
+
227
+ def compute_select_fields
228
+ select = ['_forest_admin_eager_load']
229
+ @params[:fields][@collection_name].split(',').each do |path|
230
+ if @params[:fields].key?(path)
231
+ association = ForestLiana::QueryHelper.get_one_associations(@resource)
232
+ .select { |association| association.name == path.to_sym }
233
+ .first
234
+ table_name = association.table_name
235
+
236
+ @params[:fields][path].split(',').each do |association_path|
237
+ if ForestLiana::SchemaHelper.is_smart_field?(association.klass, association_path)
238
+ association.klass.attribute_names.each { |attribute| select << "#{table_name}.#{attribute}" }
239
+ else
240
+ select << "#{table_name}.#{association_path}"
241
+ end
242
+ end
243
+ else
244
+ select << "#{@resource.table_name}.#{path}"
245
+ end
246
+ end
247
+
248
+ select
249
+ end
213
250
  end
214
251
  end
@@ -0,0 +1,65 @@
1
+ module ForestLiana
2
+ module ActiveRecordOverride
3
+ module Associations
4
+ require 'active_record/associations/join_dependency'
5
+ module JoinDependency
6
+ def apply_column_aliases(relation)
7
+ if !(@join_root_alias = relation.select_values.empty?) &&
8
+ relation.select_values.first.to_s == '_forest_admin_eager_load'
9
+
10
+ relation.select_values.shift
11
+ used_cols = {}
12
+ # Find and expand out all column names being used in select(...)
13
+ new_select_values = relation.select_values.map(&:to_s).each_with_object([]) do |col, select|
14
+ unless col.include?(' ') # Pass it through if it's some expression (No chance for a simple column reference)
15
+ col = if (col_parts = col.split('.')).length == 1
16
+ [col]
17
+ else
18
+ [col_parts[0..-2].join('.'), col_parts.last]
19
+ end
20
+ used_cols[col] = nil
21
+ end
22
+ select << col
23
+ end
24
+
25
+ if new_select_values.present?
26
+ relation.select_values = new_select_values
27
+ else
28
+ relation.select_values.clear
29
+ end
30
+
31
+ @aliases ||= ActiveRecord::Associations::JoinDependency::Aliases.new(join_root.each_with_index.map do |join_part, i|
32
+ join_alias = join_part.table&.table_alias || join_part.table_name
33
+ keys = [join_part.base_klass.primary_key] # Always include the primary key
34
+
35
+ # # %%% Optional to include all foreign keys:
36
+ # keys.concat(join_part.base_klass.reflect_on_all_associations.select { |a| a.belongs_to? }.map(&:foreign_key))
37
+ # Add foreign keys out to referenced tables that we belongs_to
38
+ join_part.children.each { |child| keys << child.reflection.foreign_key if child.reflection.belongs_to? }
39
+
40
+ # Add the foreign key that got us here -- "the train we rode in on" -- if we arrived from
41
+ # a has_many or has_one:
42
+ if join_part.is_a?(ActiveRecord::Associations::JoinDependency::JoinAssociation) &&
43
+ !join_part.reflection.belongs_to?
44
+ keys << join_part.reflection.foreign_key
45
+ end
46
+ keys = keys.compact # In case we're using composite_primary_keys
47
+ j = 0
48
+ columns = join_part.column_names.each_with_object([]) do |column_name, s|
49
+ # Include columns chosen in select(...) as well as the PK and any relevant FKs
50
+ if used_cols.keys.find { |c| (c.length == 1 || c.first == join_alias) && c.last == column_name } ||
51
+ keys.find { |c| c == column_name }
52
+ s << ActiveRecord::Associations::JoinDependency::Aliases::Column.new(column_name, "t#{i}_r#{j}")
53
+ end
54
+ j += 1
55
+ end
56
+ ActiveRecord::Associations::JoinDependency::Aliases::Table.new(join_part, columns)
57
+ end)
58
+ relation.select_values.clear
59
+ end
60
+ relation._select!(-> { aliases.columns })
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -7,6 +7,7 @@ require 'jwt'
7
7
  require 'bcrypt'
8
8
  require_relative 'bootstrapper'
9
9
  require_relative 'collection'
10
+ require_relative 'active_record_override'
10
11
 
11
12
  module Rack
12
13
  class Cors
@@ -90,6 +91,12 @@ module ForestLiana
90
91
  end
91
92
  end
92
93
 
94
+ initializer 'forest_liana.override_active_record_dependency' do
95
+ ActiveSupport.on_load(:active_record) do
96
+ ActiveRecord::Associations::JoinDependency.prepend(ForestLiana::ActiveRecordOverride::Associations::JoinDependency)
97
+ end
98
+ end
99
+
93
100
  config.after_initialize do |app|
94
101
  if error
95
102
  FOREST_REPORTER.report error
@@ -1,3 +1,3 @@
1
1
  module ForestLiana
2
- VERSION = "9.11.3"
2
+ VERSION = "9.12.0"
3
3
  end
@@ -4,7 +4,7 @@ module ForestLiana
4
4
  let(:pageSize) { 10 }
5
5
  let(:pageNumber) { 1 }
6
6
  let(:sort) { 'id' }
7
- let(:fields) {}
7
+ let(:fields) { { resource.name => 'id' } }
8
8
  let(:filters) {}
9
9
  let(:scopes) { {'scopes' => {}, 'team' => {'id' => '1', 'name' => 'Operations'}} }
10
10
  let(:rendering_id) { 13 }
@@ -190,6 +190,7 @@ module ForestLiana
190
190
 
191
191
  describe 'when on a model having a reserved SQL word as name' do
192
192
  let(:resource) { Reference }
193
+ let(:fields) { { resource.name => 'id' } }
193
194
 
194
195
  it 'should get the ressource properly' do
195
196
  getter.perform
@@ -219,6 +220,7 @@ module ForestLiana
219
220
 
220
221
  describe 'when sorting by a belongs_to association' do
221
222
  let(:resource) { Tree }
223
+ let(:fields) { { resource.name => 'id' } }
222
224
  let(:sort) { 'owner.name' }
223
225
 
224
226
  it 'should get only the expected records' do
@@ -501,7 +503,7 @@ module ForestLiana
501
503
  describe 'when scopes are defined' do
502
504
  let(:resource) { Island }
503
505
  let(:pageSize) { 15 }
504
- let(:fields) { }
506
+ let(:fields) { { resource.name => 'id' } }
505
507
  let(:filters) { }
506
508
  let(:scopes) {
507
509
  {
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.11.3
4
+ version: 9.12.0
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-04-09 00:00:00.000000000 Z
11
+ date: 2025-05-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -317,6 +317,7 @@ files:
317
317
  - config/routes.rb
318
318
  - config/routes/actions.rb
319
319
  - lib/forest_liana.rb
320
+ - lib/forest_liana/active_record_override.rb
320
321
  - lib/forest_liana/base64_string_io.rb
321
322
  - lib/forest_liana/bootstrapper.rb
322
323
  - lib/forest_liana/collection.rb