forest_liana 9.15.1 → 9.15.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/controllers/forest_liana/application_controller.rb +10 -1
- data/app/serializers/forest_liana/serializer_factory.rb +105 -12
- data/app/services/forest_liana/resources_getter.rb +0 -46
- data/lib/forest_liana/version.rb +1 -1
- data/spec/requests/resources_spec.rb +1 -12
- data/spec/services/forest_liana/serializer_factory_spec.rb +0 -21
- 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: 6c293cc19d5273766a98fcc556bb07bcdd9dea63cd604aeee9352055556b9994
|
4
|
+
data.tar.gz: fe841959936a030dc0989da2645ce9db9a74237bf86d7028c2cc4c7de27fece8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4ab70690f0da9891d2e5484ad33548e443bf5d72cf0edbc24caae74fe6214a2e3d9f10489ebdb331b907809a6d19cd2cfdd1631c80ed5c0aff4156a5e666326
|
7
|
+
data.tar.gz: bb3272e7f6ae11f3538f15ac0cb280df67015ac940d1734d8cc5d04f9ad1168b1e09ad9073e3b85cfef0c936d7393db70a90973e14a34d0e367584e46f3a4311
|
@@ -156,10 +156,12 @@ module ForestLiana
|
|
156
156
|
params_fields_hash.inject({}) do |fields, param_field|
|
157
157
|
relation_name = param_field[0]
|
158
158
|
relation_fields = param_field[1]
|
159
|
+
forest_collection = ForestLiana.apimap.find { |collection| collection.name.to_s == model.to_s.gsub('::', '__') }
|
160
|
+
smart_relations = forest_collection.fields_smart_belongs_to
|
159
161
|
|
160
162
|
if relation_name == ForestLiana.name_for(model)
|
161
163
|
fields[relation_name] = relation_fields
|
162
|
-
|
164
|
+
elsif model.reflect_on_association(relation_name.to_sym)
|
163
165
|
model_association = model.reflect_on_association(relation_name.to_sym)
|
164
166
|
if model_association
|
165
167
|
model_name = ForestLiana.name_for(model_association.klass)
|
@@ -173,7 +175,14 @@ module ForestLiana
|
|
173
175
|
fields[model_name] = relation_fields
|
174
176
|
end
|
175
177
|
end
|
178
|
+
else
|
179
|
+
smart_relations.each do |smart_relation|
|
180
|
+
if smart_relation[:field].to_s == relation_name
|
181
|
+
fields[smart_relation[:reference].split('.').first] = relation_fields
|
182
|
+
end
|
183
|
+
end
|
176
184
|
end
|
185
|
+
|
177
186
|
fields
|
178
187
|
end
|
179
188
|
else
|
@@ -47,6 +47,81 @@ module ForestLiana
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
+
# duplicate method from Serializer
|
51
|
+
ForestAdmin::JSONAPI::Serializer.singleton_class.send(:define_method, :find_recursive_relationships) do |root_object, root_inclusion_tree, results, options|
|
52
|
+
ActiveSupport::Notifications.instrument(
|
53
|
+
'render.jsonapi_serializers.find_recursive_relationships',
|
54
|
+
{class_name: root_object.class.name},
|
55
|
+
) do
|
56
|
+
root_inclusion_tree.each do |attribute_name, child_inclusion_tree|
|
57
|
+
next if attribute_name == :_include
|
58
|
+
|
59
|
+
serializer = ForestAdmin::JSONAPI::Serializer.find_serializer(root_object, options)
|
60
|
+
unformatted_attr_name = serializer.unformat_name(attribute_name).to_sym
|
61
|
+
object = nil
|
62
|
+
is_collection = false
|
63
|
+
is_valid_attr = false
|
64
|
+
if serializer.has_one_relationships.has_key?(unformatted_attr_name)
|
65
|
+
# only added this condition
|
66
|
+
if root_object.class.reflect_on_association(unformatted_attr_name)&.polymorphic?
|
67
|
+
options[:context][:unoptimized] = true
|
68
|
+
end
|
69
|
+
|
70
|
+
is_valid_attr = true
|
71
|
+
attr_data = serializer.has_one_relationships[unformatted_attr_name]
|
72
|
+
object = serializer.has_one_relationship(unformatted_attr_name, attr_data)
|
73
|
+
elsif serializer.has_many_relationships.has_key?(unformatted_attr_name)
|
74
|
+
is_valid_attr = true
|
75
|
+
is_collection = true
|
76
|
+
attr_data = serializer.has_many_relationships[unformatted_attr_name]
|
77
|
+
object = serializer.has_many_relationship(unformatted_attr_name, attr_data)
|
78
|
+
end
|
79
|
+
|
80
|
+
if !is_valid_attr
|
81
|
+
raise ForestAdmin::JSONAPI::Serializer::InvalidIncludeError.new(
|
82
|
+
"'#{attribute_name}' is not a valid include.")
|
83
|
+
end
|
84
|
+
|
85
|
+
if attribute_name != serializer.format_name(attribute_name)
|
86
|
+
expected_name = serializer.format_name(attribute_name)
|
87
|
+
|
88
|
+
raise ForestAdmin::JSONAPI::Serializer::InvalidIncludeError.new(
|
89
|
+
"'#{attribute_name}' is not a valid include. Did you mean '#{expected_name}' ?"
|
90
|
+
)
|
91
|
+
end
|
92
|
+
|
93
|
+
next if object.nil?
|
94
|
+
|
95
|
+
objects = is_collection ? object : [object]
|
96
|
+
if child_inclusion_tree[:_include] == true
|
97
|
+
objects.each do |obj|
|
98
|
+
obj_serializer = ForestAdmin::JSONAPI::Serializer.find_serializer(obj, options)
|
99
|
+
key = [obj_serializer.type, obj_serializer.id]
|
100
|
+
|
101
|
+
current_child_includes = []
|
102
|
+
inclusion_names = child_inclusion_tree.keys.reject { |k| k == :_include }
|
103
|
+
inclusion_names.each do |inclusion_name|
|
104
|
+
if child_inclusion_tree[inclusion_name][:_include]
|
105
|
+
current_child_includes << inclusion_name
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
current_child_includes += results[key] && results[key][:include_linkages] || []
|
110
|
+
current_child_includes.uniq!
|
111
|
+
results[key] = {object: obj, include_linkages: current_child_includes}
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
if !child_inclusion_tree.empty?
|
116
|
+
objects.each do |obj|
|
117
|
+
find_recursive_relationships(obj, child_inclusion_tree, results, options)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
nil
|
123
|
+
end
|
124
|
+
|
50
125
|
def initialize(is_smart_collection = false)
|
51
126
|
@is_smart_collection = is_smart_collection
|
52
127
|
end
|
@@ -136,28 +211,46 @@ module ForestLiana
|
|
136
211
|
data = {}
|
137
212
|
self.class.to_one_associations.each do |attribute_name, attr_data|
|
138
213
|
relation = object.class.reflect_on_all_associations.find { |a| a.name == attribute_name }
|
139
|
-
|
140
214
|
next if !should_include_attr?(attribute_name, attr_data)
|
141
215
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
216
|
+
if relation && relation.belongs_to? && relation.polymorphic?.nil?
|
217
|
+
reflection_primary_key = relation.options[:primary_key]&.to_sym || :id
|
218
|
+
klass_primary_key = relation.klass.primary_key.to_sym
|
219
|
+
|
220
|
+
if reflection_primary_key != klass_primary_key
|
221
|
+
data[attribute_name] = attr_data.merge({
|
222
|
+
attr_or_block: proc {
|
223
|
+
relation.klass.find_by(reflection_primary_key => object.send(relation.foreign_key))
|
224
|
+
}
|
225
|
+
})
|
226
|
+
next
|
153
227
|
end
|
154
228
|
end
|
155
229
|
|
156
230
|
data[attribute_name] = attr_data
|
157
231
|
end
|
232
|
+
|
158
233
|
data
|
159
234
|
end
|
160
235
|
|
236
|
+
def should_include_attr?(attribute_name, attr_data)
|
237
|
+
collection = self.type
|
238
|
+
|
239
|
+
unless @options.dig(:context, :unoptimized)
|
240
|
+
return false unless @options[:fields][collection]&.include?(attribute_name.to_sym)
|
241
|
+
end
|
242
|
+
|
243
|
+
# Allow "if: :show_title?" and "unless: :hide_title?" attribute options.
|
244
|
+
if_method_name = attr_data[:options][:if]
|
245
|
+
unless_method_name = attr_data[:options][:unless]
|
246
|
+
formatted_attribute_name = format_name(attribute_name).to_sym
|
247
|
+
show_attr = true
|
248
|
+
show_attr &&= send(if_method_name) if if_method_name
|
249
|
+
show_attr &&= !send(unless_method_name) if unless_method_name
|
250
|
+
show_attr &&= @_fields[type.to_s].include?(formatted_attribute_name) if @_fields[type.to_s]
|
251
|
+
show_attr
|
252
|
+
end
|
253
|
+
|
161
254
|
private
|
162
255
|
|
163
256
|
def intercom_integration?
|
@@ -74,55 +74,9 @@ module ForestLiana
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
-
preload_cross_database_associations(records, preload_loads)
|
78
|
-
|
79
77
|
records
|
80
78
|
end
|
81
79
|
|
82
|
-
def preload_cross_database_associations(records, preload_loads)
|
83
|
-
preload_loads.each do |association_name|
|
84
|
-
association = @resource.reflect_on_association(association_name)
|
85
|
-
next unless separate_database?(@resource, association)
|
86
|
-
|
87
|
-
columns = columns_for_cross_database_association(association_name)
|
88
|
-
if association.macro == :belongs_to
|
89
|
-
foreign_key = association.foreign_key
|
90
|
-
primary_key = association.klass.primary_key
|
91
|
-
|
92
|
-
ids = records.map { |r| r.public_send(foreign_key) }.compact.uniq
|
93
|
-
next if ids.empty?
|
94
|
-
|
95
|
-
associated = association.klass.where(primary_key => ids)
|
96
|
-
.select(columns)
|
97
|
-
.index_by { |record| record.public_send(primary_key) }
|
98
|
-
|
99
|
-
records.each do |record|
|
100
|
-
record.define_singleton_method(association_name) do
|
101
|
-
associated[record.send(foreign_key.to_sym)] || nil
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
if association.macro == :has_one
|
107
|
-
foreign_key = association.foreign_key
|
108
|
-
primary_key = association.active_record_primary_key
|
109
|
-
|
110
|
-
ids = records.map { |r| r.public_send(primary_key) }.compact.uniq
|
111
|
-
next if ids.empty?
|
112
|
-
|
113
|
-
associated = association.klass.where(foreign_key => ids)
|
114
|
-
.select(columns)
|
115
|
-
.index_by { |record| record.public_send(foreign_key.to_sym) }
|
116
|
-
|
117
|
-
records.each do |record|
|
118
|
-
record.define_singleton_method(association_name) do
|
119
|
-
associated[record.send(primary_key.to_sym)] || nil
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
80
|
def columns_for_cross_database_association(association_name)
|
127
81
|
association = @resource.reflect_on_association(association_name)
|
128
82
|
|
data/lib/forest_liana/version.rb
CHANGED
@@ -124,18 +124,7 @@ describe 'Requesting Tree resources', :type => :request do
|
|
124
124
|
"included" => [{
|
125
125
|
"type" => "Location",
|
126
126
|
"id" => "1",
|
127
|
-
"
|
128
|
-
"id" => 1,
|
129
|
-
"created_at" => nil,
|
130
|
-
"updated_at" => nil,
|
131
|
-
"coordinates" => nil
|
132
|
-
),
|
133
|
-
"links" => { "self" => "/forest/location/1" },
|
134
|
-
"relationships" => {
|
135
|
-
"island" => {
|
136
|
-
"links" => { "related" => {} }
|
137
|
-
}
|
138
|
-
}
|
127
|
+
"links" => { "self" => "/forest/location/1" }
|
139
128
|
}]
|
140
129
|
})
|
141
130
|
end
|
@@ -5,27 +5,6 @@ module ForestLiana
|
|
5
5
|
let(:island) { Island.create!(name: 'TestIsland') }
|
6
6
|
let(:tree) { Tree.create!(name: 'TestTree', island: island, owner: user) }
|
7
7
|
|
8
|
-
it 'simulates has_one relation with only primary key' do
|
9
|
-
factory = described_class.new
|
10
|
-
serializer_class = factory.serializer_for(Tree)
|
11
|
-
|
12
|
-
serializer_class.send(:has_one, :island) { }
|
13
|
-
|
14
|
-
instance = serializer_class.new(tree, fields: {
|
15
|
-
'Island' => [:id],
|
16
|
-
'Tree' => [:island]
|
17
|
-
})
|
18
|
-
|
19
|
-
relationships = instance.send(:has_one_relationships)
|
20
|
-
expect(relationships).to have_key(:island)
|
21
|
-
relation_data = relationships[:island]
|
22
|
-
expect(relation_data[:attr_or_block]).to be_a(Proc)
|
23
|
-
model = relation_data[:attr_or_block].call
|
24
|
-
|
25
|
-
expect(model).to be_a(Island)
|
26
|
-
expect(model.id).to eq(island.id)
|
27
|
-
end
|
28
|
-
|
29
8
|
it 'returns nil if foreign key is nil' do
|
30
9
|
tree_without_island = Tree.create!(name: 'NoIslandTree', island_id: nil, owner: user)
|
31
10
|
|
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.15.
|
4
|
+
version: 9.15.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-08-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|