forest_liana 9.12.2 → 9.14.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 +4 -4
- data/app/serializers/forest_liana/serializer_factory.rb +24 -6
- data/app/services/forest_liana/base_getter.rb +4 -3
- data/app/services/forest_liana/has_many_getter.rb +2 -0
- data/app/services/forest_liana/resources_getter.rb +102 -18
- data/lib/forest_liana/version.rb +1 -1
- 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: 133660170841c0069ffdc0da3e2a4918e4147f417eae55c87b79bb300d9924b0
|
4
|
+
data.tar.gz: eba503c46d489b6f6a4e81f26764f284574db290aed180755c6ca33841fc8b19
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a1b5122e4700ae49500fbfc7b7c1060561e3a73cdfe3c980f946453c54eac0fa0c0982914b2ffcb3a18710d9e5c4fddb0cc7b6a12f18feca424d64067987691d
|
7
|
+
data.tar.gz: 4b4183d21184e1986ca78158f7d6e99aae06ea6767292448ddb1bc29b00f3fe2862000d9c642eb8b8c84e4ce19166778a5fa5e3439cdac1c33e925d2f0ce988f
|
@@ -118,12 +118,6 @@ module ForestLiana
|
|
118
118
|
|
119
119
|
if ret[:href].blank?
|
120
120
|
begin
|
121
|
-
if @options[:include].try(:include?, attribute_name.to_s) &&
|
122
|
-
!SchemaHelper.is_smart_field?(object.class, attribute_name.to_s)
|
123
|
-
|
124
|
-
object.send(attribute_name)
|
125
|
-
end
|
126
|
-
|
127
121
|
SchemaUtils.many_associations(object.class).each do |a|
|
128
122
|
if a.name == attribute_name
|
129
123
|
ret[:href] = "/forest/#{ForestLiana.name_for(object.class)}/#{object.id}/relationships/#{attribute_name}"
|
@@ -137,6 +131,30 @@ module ForestLiana
|
|
137
131
|
ret
|
138
132
|
end
|
139
133
|
|
134
|
+
def has_one_relationships
|
135
|
+
return {} if self.class.to_one_associations.nil?
|
136
|
+
data = {}
|
137
|
+
self.class.to_one_associations.each do |attribute_name, attr_data|
|
138
|
+
relation = object.class.reflect_on_all_associations.find { |a| a.name == attribute_name }
|
139
|
+
|
140
|
+
next if !should_include_attr?(attribute_name, attr_data)
|
141
|
+
|
142
|
+
unless relation.polymorphic?
|
143
|
+
relation_class_name = ForestLiana.name_for(relation.klass).demodulize
|
144
|
+
|
145
|
+
if object.send(relation.foreign_key.to_sym) &&
|
146
|
+
@options[:fields][relation_class_name]&.size == 1 &&
|
147
|
+
@options[:fields][relation_class_name]&.include?(relation.klass.primary_key.to_sym)
|
148
|
+
|
149
|
+
attr_data[:attr_or_block] = proc { relation.klass.new(relation.klass.primary_key => object.send(relation.foreign_key.to_sym)) }
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
data[attribute_name] = attr_data
|
154
|
+
end
|
155
|
+
data
|
156
|
+
end
|
157
|
+
|
140
158
|
private
|
141
159
|
|
142
160
|
def intercom_integration?
|
@@ -19,13 +19,14 @@ module ForestLiana
|
|
19
19
|
|
20
20
|
def compute_includes
|
21
21
|
@includes = ForestLiana::QueryHelper.get_one_association_names_symbol(@resource)
|
22
|
+
@optional_includes = []
|
22
23
|
end
|
23
24
|
|
24
|
-
def optimize_record_loading(resource, records)
|
25
|
+
def optimize_record_loading(resource, records, force_preload = true)
|
25
26
|
polymorphic, preload_loads = analyze_associations(resource)
|
26
|
-
result = records.eager_load(@includes.uniq - preload_loads - polymorphic)
|
27
|
+
result = records.eager_load(@includes.uniq - preload_loads - polymorphic - @optional_includes)
|
27
28
|
|
28
|
-
result = result.preload(preload_loads) if Rails::VERSION::MAJOR >= 7
|
29
|
+
result = result.preload(preload_loads) if Rails::VERSION::MAJOR >= 7 && force_preload
|
29
30
|
|
30
31
|
result
|
31
32
|
end
|
@@ -31,16 +31,16 @@ module ForestLiana
|
|
31
31
|
|
32
32
|
def perform
|
33
33
|
polymorphic_association, preload_loads = analyze_associations(@resource)
|
34
|
-
includes = @includes.uniq - polymorphic_association - preload_loads
|
34
|
+
includes = @includes.uniq - polymorphic_association - preload_loads - @optional_includes
|
35
35
|
has_smart_fields = @params[:fields][@collection_name].split(',').any? do |field|
|
36
36
|
ForestLiana::SchemaHelper.is_smart_field?(@resource, field)
|
37
37
|
end
|
38
38
|
|
39
39
|
if includes.empty? || has_smart_fields
|
40
|
-
@records = optimize_record_loading(@resource, @records)
|
40
|
+
@records = optimize_record_loading(@resource, @records, false)
|
41
41
|
else
|
42
42
|
select = compute_select_fields
|
43
|
-
@records = optimize_record_loading(@resource, @records).references(includes).select(*select)
|
43
|
+
@records = optimize_record_loading(@resource, @records, false).references(includes).select(*select)
|
44
44
|
end
|
45
45
|
|
46
46
|
@records
|
@@ -55,31 +55,115 @@ module ForestLiana
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def records
|
58
|
-
@records.offset(offset).limit(limit).to_a
|
58
|
+
records = @records.offset(offset).limit(limit).to_a
|
59
|
+
|
60
|
+
polymorphic_association, preload_loads = analyze_associations(@resource)
|
61
|
+
if polymorphic_association && Rails::VERSION::MAJOR >= 7
|
62
|
+
# TODO
|
63
|
+
end
|
64
|
+
|
65
|
+
preload_cross_database_associations(records, preload_loads)
|
66
|
+
|
67
|
+
records
|
59
68
|
end
|
60
69
|
|
61
|
-
def
|
62
|
-
|
70
|
+
def preload_cross_database_associations(records, preload_loads)
|
71
|
+
preload_loads.each do |association_name|
|
72
|
+
association = @resource.reflect_on_association(association_name)
|
73
|
+
next unless separate_database?(@resource, association)
|
74
|
+
|
75
|
+
columns = columns_for_cross_database_association(association_name)
|
76
|
+
|
77
|
+
if association.macro == :belongs_to
|
78
|
+
foreign_key = association.foreign_key
|
79
|
+
primary_key = association.klass.primary_key
|
63
80
|
|
64
|
-
|
65
|
-
|
81
|
+
ids = records.map { |r| r.public_send(foreign_key) }.compact.uniq
|
82
|
+
next if ids.empty?
|
66
83
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
.map { |field| field.split('.').first.to_sym }
|
84
|
+
associated = association.klass.where(primary_key => ids)
|
85
|
+
.select(columns)
|
86
|
+
.index_by { |record| record.public_send(primary_key) }
|
71
87
|
|
72
|
-
|
73
|
-
|
74
|
-
|
88
|
+
records.each do |record|
|
89
|
+
record.define_singleton_method(association_name) do
|
90
|
+
associated[record.send(foreign_key.to_sym)] || nil
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
if association.macro == :has_one
|
96
|
+
foreign_key = association.foreign_key
|
97
|
+
primary_key = association.active_record_primary_key
|
98
|
+
|
99
|
+
ids = records.map { |r| r.public_send(primary_key) }.compact.uniq
|
100
|
+
next if ids.empty?
|
75
101
|
|
76
|
-
|
102
|
+
associated = association.klass.where(foreign_key => ids)
|
103
|
+
.select(columns)
|
104
|
+
.index_by { |record| record.public_send(foreign_key.to_sym) }
|
105
|
+
|
106
|
+
records.each do |record|
|
107
|
+
record.define_singleton_method(association_name) do
|
108
|
+
associated[record.send(primary_key.to_sym)] || nil
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
77
112
|
end
|
113
|
+
end
|
78
114
|
|
115
|
+
def columns_for_cross_database_association(association_name)
|
116
|
+
return [:id] unless @params[:fields].present?
|
117
|
+
|
118
|
+
fields = @params[:fields][association_name.to_s]
|
119
|
+
return [:id] unless fields
|
120
|
+
|
121
|
+
base_fields = fields.split(',').map(&:strip).map(&:to_sym) | [:id]
|
122
|
+
|
123
|
+
association = @resource.reflect_on_association(association_name)
|
124
|
+
extra_key = association.foreign_key
|
125
|
+
|
126
|
+
# Add the foreign key used for the association to ensure it's available in the preloaded records
|
127
|
+
# This is necessary for has_one associations, without it calling record.public_send(foreign_key) would raise a "missing attribute" error
|
128
|
+
base_fields << extra_key if association.macro == :has_one
|
129
|
+
|
130
|
+
base_fields.uniq
|
131
|
+
end
|
132
|
+
|
133
|
+
def compute_includes
|
134
|
+
associations_has_one = ForestLiana::QueryHelper.get_one_associations(@resource)
|
135
|
+
@optional_includes = []
|
79
136
|
if @field_names_requested
|
137
|
+
includes = associations_has_one.map do |association|
|
138
|
+
association_name = association.name.to_s
|
139
|
+
|
140
|
+
if @params[:fields].key?(association_name) &&
|
141
|
+
@params[:fields][association_name].split(',').size == 1 &&
|
142
|
+
@params[:fields][association_name].split(',').include?(association.klass.primary_key)
|
143
|
+
|
144
|
+
@field_names_requested << association.foreign_key
|
145
|
+
@optional_includes << association.name
|
146
|
+
end
|
147
|
+
|
148
|
+
association.name
|
149
|
+
end
|
150
|
+
|
151
|
+
includes_for_smart_search = []
|
152
|
+
if @collection && @collection.search_fields
|
153
|
+
includes_for_smart_search = @collection.search_fields
|
154
|
+
.select { |field| field.include? '.' }
|
155
|
+
.map { |field| field.split('.').first.to_sym }
|
156
|
+
|
157
|
+
includes_has_many = SchemaUtils.many_associations(@resource)
|
158
|
+
.select { |association| SchemaUtils.model_included?(association.klass) }
|
159
|
+
.map(&:name)
|
160
|
+
|
161
|
+
includes_for_smart_search = includes_for_smart_search & includes_has_many
|
162
|
+
end
|
163
|
+
|
80
164
|
@includes = (includes & @field_names_requested).concat(includes_for_smart_search)
|
81
165
|
else
|
82
|
-
@includes =
|
166
|
+
@includes = associations_has_one.map(&:name)
|
83
167
|
end
|
84
168
|
end
|
85
169
|
|
@@ -226,7 +310,7 @@ module ForestLiana
|
|
226
310
|
|
227
311
|
def compute_select_fields
|
228
312
|
select = ['_forest_admin_eager_load']
|
229
|
-
@
|
313
|
+
@field_names_requested.each do |path|
|
230
314
|
association = get_one_association(path)
|
231
315
|
if association
|
232
316
|
while association.options[:through]
|
data/lib/forest_liana/version.rb
CHANGED
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.
|
4
|
+
version: 9.14.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-05-
|
11
|
+
date: 2025-05-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|