Skip to content

Commit a163407

Browse files
fix: improve quey with duplicate alias (#687)
close #512 Co-authored-by: Nicolas Alexandre <[email protected]>
1 parent 34600e1 commit a163407

File tree

5 files changed

+152
-157
lines changed

5 files changed

+152
-157
lines changed

app/services/forest_liana/base_getter.rb

Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,14 @@ def get_collection(collection_name)
55
end
66

77
def get_resource
8-
use_act_as_paranoid = @resource.instance_methods
9-
.include? :really_destroyed?
10-
11-
# NOTICE: Do not unscope with the paranoia gem to prevent the retrieval
12-
# of deleted records.
13-
use_act_as_paranoid ? @resource : @resource.unscoped
8+
@resource.instance_methods.include?(:really_destroyed?) ? @resource : @resource.unscoped
149
end
1510

1611
def includes_for_serialization
17-
includes_initial = @includes
1812
includes_for_smart_belongs_to = @collection.fields_smart_belongs_to.map { |field| field[:field] }
13+
includes_for_smart_belongs_to &= @field_names_requested if @field_names_requested
1914

20-
if @field_names_requested
21-
includes_for_smart_belongs_to = includes_for_smart_belongs_to & @field_names_requested
22-
end
23-
24-
includes_initial.concat(includes_for_smart_belongs_to).map(&:to_s)
15+
@includes.concat(includes_for_smart_belongs_to).map(&:to_s)
2516
end
2617

2718
private
@@ -31,34 +22,36 @@ def compute_includes
3122
end
3223

3324
def optimize_record_loading(resource, records)
34-
instance_dependent_associations = instance_dependent_associations(resource)
25+
polymorphic, preload_loads = analyze_associations(resource)
26+
result = records.eager_load(@includes.uniq - preload_loads - polymorphic)
3527

28+
result = result.preload(preload_loads) if Rails::VERSION::MAJOR >= 7
29+
30+
result
31+
end
32+
33+
def analyze_associations(resource)
3634
polymorphic = []
37-
preload_loads = @includes.select do |name|
35+
preload_loads = @includes.uniq.select do |name|
3836
association = resource.reflect_on_association(name)
3937
if SchemaUtils.polymorphic?(association)
4038
polymorphic << association.name
4139
false
4240
else
43-
targetModelConnection = association.klass.connection
44-
targetModelDatabase = targetModelConnection.current_database if targetModelConnection.respond_to? :current_database
45-
resourceConnection = resource.connection
46-
resourceDatabase = resourceConnection.current_database if resourceConnection.respond_to? :current_database
47-
48-
targetModelDatabase != resourceDatabase
41+
separate_database?(resource, association)
4942
end
50-
end + instance_dependent_associations
43+
end + instance_dependent_associations(resource)
5144

52-
result = records.eager_load(@includes - preload_loads - polymorphic)
45+
[polymorphic, preload_loads]
46+
end
5347

54-
# Rails 7 can mix `eager_load` and `preload` in the same scope
55-
# Rails 6 cannot mix `eager_load` and `preload` in the same scope
56-
# Rails 6 and 7 cannot mix `eager_load` and `includes` in the same scope
57-
if Rails::VERSION::MAJOR >= 7
58-
result = result.preload(preload_loads)
59-
end
48+
def separate_database?(resource, association)
49+
target_model_connection = association.klass.connection
50+
target_model_database = target_model_connection.current_database if target_model_connection.respond_to? :current_database
51+
resource_connection = resource.connection
52+
resource_database = resource_connection.current_database if resource_connection.respond_to? :current_database
6053

61-
result
54+
target_model_database != resource_database
6255
end
6356

6457
def instance_dependent_associations(resource)

app/services/forest_liana/filters_parser.rb

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module ForestLiana
22
class FiltersParser
3-
AGGREGATOR_OPERATOR = %w(and or)
3+
AGGREGATOR_OPERATOR = %w(and or).freeze
44

55
def initialize(filters, resource, timezone, params = nil)
66
@filters = filters
@@ -13,18 +13,14 @@ def initialize(filters, resource, timezone, params = nil)
1313
def apply_filters
1414
return @resource unless @filters
1515

16-
where = parse_aggregation(@filters)
17-
return @resource unless where
16+
where_clause = parse_aggregation(@filters)
17+
return @resource unless where_clause
1818

1919
@joins.each do |join|
20-
current_resource = @resource.reflect_on_association(join.name).klass
21-
current_resource.include(ArelHelpers::Aliases)
22-
current_resource.aliased_as(join.name) do |aliased_resource|
23-
@resource = @resource.joins(ArelHelpers.join_association(@resource, join.name, Arel::Nodes::OuterJoin, aliases: [aliased_resource]))
24-
end
20+
@resource = @resource.eager_load(join.name)
2521
end
2622

27-
@resource.where(where)
23+
@resource.where(where_clause)
2824
end
2925

3026
def parse_aggregation(node)
@@ -170,8 +166,8 @@ def parse_field_name(field)
170166
current_resource = @resource.reflect_on_association(field.split(':').first.to_sym)&.klass
171167
raise ForestLiana::Errors::HTTP422Error.new("Field '#{field}' not found") unless current_resource
172168

173-
association = get_association_name_for_condition(field)
174-
quoted_table_name = ActiveRecord::Base.connection.quote_column_name(association)
169+
get_association_name_for_condition(field)
170+
quoted_table_name = current_resource.table_name
175171
field_name = field.split(':')[1]
176172
else
177173
quoted_table_name = @resource.quoted_table_name

0 commit comments

Comments
 (0)