Skip to content

Commit 6472522

Browse files
authored
fix: include has_one through associations in compute_select_fields in ResourcesGetter (#732)
1 parent 10904ed commit 6472522

File tree

7 files changed

+90
-14
lines changed

7 files changed

+90
-14
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ Here is the contribution workflow:
164164
Please ensure that the **tests** are passing before submitting any pull request:
165165

166166
```
167-
$ RAILS_ENV=test bundle exec rake --trace db:migrate test
167+
$ RAILS_ENV=test bundle exec rake --trace db:migrate test; bundle exec rspec
168168
```
169169

170170
## Community

app/services/forest_liana/resources_getter.rb

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -227,10 +227,20 @@ def pagination?
227227
def compute_select_fields
228228
select = ['_forest_admin_eager_load']
229229
@params[:fields][@collection_name].split(',').each do |path|
230+
association = get_one_association(path)
231+
if association
232+
while association.options[:through]
233+
association = get_one_association(association.options[:through])
234+
end
235+
236+
if SchemaUtils.polymorphic?(association)
237+
select << "#{@resource.table_name}.#{association.foreign_type}"
238+
end
239+
select << "#{@resource.table_name}.#{association.foreign_key}"
240+
end
241+
230242
if @params[:fields].key?(path)
231-
association = ForestLiana::QueryHelper.get_one_associations(@resource)
232-
.select { |association| association.name == path.to_sym }
233-
.first
243+
association = get_one_association(path)
234244
table_name = association.table_name
235245

236246
@params[:fields][path].split(',').each do |association_path|
@@ -245,7 +255,13 @@ def compute_select_fields
245255
end
246256
end
247257

248-
select
258+
select.uniq
259+
end
260+
261+
def get_one_association(name)
262+
ForestLiana::QueryHelper.get_one_associations(@resource)
263+
.select { |association| association.name == name.to_sym }
264+
.first
249265
end
250266
end
251267
end

spec/dummy/app/models/tree.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ class Tree < ActiveRecord::Base
77
class_name: 'Island',
88
inverse_of: :eponymous_tree,
99
optional: true
10+
11+
has_one :location, through: :island
1012
end

spec/helpers/forest_liana/query_helper_spec.rb

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ module ForestLiana
3737
{ name: :cutter, klass: User },
3838
{ name: :island, klass: Island },
3939
{ name: :eponymous_island, klass: Island },
40+
{ name: :location, klass: Location },
4041
]
4142
end
4243

@@ -52,13 +53,17 @@ module ForestLiana
5253

5354
describe 'get_one_association_names_symbol' do
5455
it 'should return the one-one associations names as symbols' do
55-
expect(QueryHelper.get_one_association_names_symbol(Tree)).to eq([:owner, :cutter, :island, :eponymous_island])
56+
expect(QueryHelper.get_one_association_names_symbol(Tree)).to eq(
57+
[:owner, :cutter, :island, :eponymous_island, :location]
58+
)
5659
end
5760
end
5861

5962
describe 'get_one_association_names_string' do
6063
it 'should return the one-one associations names as strings' do
61-
expect(QueryHelper.get_one_association_names_string(Tree)).to eq(['owner', 'cutter', 'island', 'eponymous_island'])
64+
expect(QueryHelper.get_one_association_names_string(Tree)).to eq(
65+
['owner', 'cutter', 'island', 'eponymous_island', 'location']
66+
)
6267
end
6368
end
6469

@@ -71,12 +76,12 @@ module ForestLiana
7176
end
7277
end
7378

74-
context 'on a model having 2 belongsTo associations' do
79+
context 'on a model having 3 belongsTo/hasOne associations' do
7580
tables_associated_to_relations_name =
7681
QueryHelper.get_tables_associated_to_relations_name(Tree)
7782

7883
it 'should return the one-one associations' do
79-
expect(tables_associated_to_relations_name.keys.length).to eq(2)
84+
expect(tables_associated_to_relations_name.keys.length).to eq(3)
8085
end
8186

8287
it 'should return relationships having a name different than the targeted model' do

spec/requests/resources_spec.rb

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
let(:scope_filters) { {'scopes' => {}, 'team' => {'id' => '1', 'name' => 'Operations'}} }
55
before do
66
user = User.create(name: 'Michel')
7-
Tree.create(name: 'Lemon Tree', owner: user, cutter: user)
7+
tree = Tree.create(name: 'Lemon Tree', owner: user, cutter: user)
8+
island = Island.create(name: 'Lemon Island', trees: [tree])
9+
Location.create(coordinates: '1,2', island: island)
810

911
Rails.cache.write('forest.users', {'1' => { 'id' => 1, 'roleId' => 1, 'rendering_id' => '1' }})
1012
Rails.cache.write('forest.has_permission', true)
@@ -32,6 +34,8 @@
3234
after do
3335
User.destroy_all
3436
Tree.destroy_all
37+
Island.destroy_all
38+
Location.destroy_all
3539
end
3640

3741
token = JWT.encode({
@@ -54,7 +58,7 @@
5458
describe 'index' do
5559
describe 'without any filter' do
5660
params = {
57-
fields: { 'Tree' => 'id,name' },
61+
fields: { 'Tree' => 'id,name,location' },
5862
page: { 'number' => '1', 'size' => '10' },
5963
searchExtended: '0',
6064
sort: '-id',
@@ -98,7 +102,8 @@
98102

99103
it 'should respond the tree data' do
100104
get '/forest/Tree', params: params, headers: headers
101-
expect(JSON.parse(response.body)).to eq({
105+
106+
expect(JSON.parse(response.body)).to include({
102107
"data" => [{
103108
"type" => "Tree",
104109
"id" => "1",
@@ -108,9 +113,30 @@
108113
},
109114
"links" => {
110115
"self" => "/forest/tree/1"
116+
},
117+
"relationships" => {
118+
"location" => {
119+
"data" => { "id" => "1", "type" => "Location" },
120+
"links" => { "related" => {} }
121+
}
111122
}
112123
}],
113-
"included" => []
124+
"included" => [{
125+
"type" => "Location",
126+
"id" => "1",
127+
"attributes" => include(
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+
}
139+
}]
114140
})
115141
end
116142
end

spec/services/forest_liana/resources_getter_spec.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,22 @@ def association_connection.current_database
290290
end
291291
end
292292

293+
describe 'when getting a has_one through association' do
294+
let(:resource) { Tree }
295+
let(:fields) { { 'Tree' => 'id,location' } }
296+
297+
it 'should get the expected records, including the foreign_key for the direct association' do
298+
getter.perform
299+
records = getter.records
300+
count = getter.count
301+
302+
expect(records.count).to eq Tree.count
303+
expect(count).to eq Tree.count
304+
expect(records.map(&:id)).to match_array(Tree.pluck(:id))
305+
expect(records.map(&:island_id)).to match_array(Tree.pluck(:island_id))
306+
end
307+
end
308+
293309
describe 'when filtering on an ambiguous field' do
294310
let(:resource) { Tree }
295311
let(:pageSize) { 5 }

spec/services/forest_liana/schema_adapter_spec.rb

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,18 @@ module ForestLiana
6161
end
6262

6363
expect(collection.fields.map { |field| field[:field].to_s}).to eq(
64-
["age", "created_at", "cutter", "eponymous_island", "id", "island", "name", "owner", "updated_at"]
64+
[
65+
"age",
66+
"created_at",
67+
"cutter",
68+
"eponymous_island",
69+
"id",
70+
"island",
71+
"location",
72+
"name",
73+
"owner",
74+
"updated_at"
75+
]
6576
)
6677
end
6778
end

0 commit comments

Comments
 (0)