Skip to content

Commit b1cc83e

Browse files
committed
Add option linkage_always option to sideloads, add tests
1 parent 2a83d6b commit b1cc83e

File tree

3 files changed

+198
-35
lines changed

3 files changed

+198
-35
lines changed

lib/graphiti/sideload.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ def initialize(name, opts)
4242
@group_name = opts[:group_name]
4343
@polymorphic_child = opts[:polymorphic_child]
4444
@parent = opts[:parent]
45+
46+
@linkage_always = if opts[:linkage_always].nil?
47+
# option not provided, use default
48+
type == :belongs_to
49+
else
50+
!!opts[:linkage_always]
51+
end
52+
4553
if polymorphic_child?
4654
parent.resource.polymorphic << resource_class
4755
end
@@ -112,6 +120,10 @@ def polymorphic_has_many?
112120
!!@polymorphic_as
113121
end
114122

123+
def linkage_always?
124+
!!@linkage_always
125+
end
126+
115127
def link?
116128
return true if link_proc
117129

lib/graphiti/util/serializer_relationships.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def block
5454

5555
# include relationship links for belongs_to relationships
5656
# https://github.com/graphiti-api/graphiti/issues/167
57-
linkage always: true if sideload_ref.type == :belongs_to
57+
linkage always: sideload_ref.linkage_always?
5858

5959
if link_ref
6060
if @proxy.query.links?

spec/sideloading_spec.rb

Lines changed: 185 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -215,46 +215,128 @@ class PositionSideload < ::Graphiti::Sideload::HasMany
215215
end
216216

217217
describe "has_many macro" do
218-
before do
219-
resource.class_eval do
220-
has_many :positions do
221-
scope do |employee_ids|
222-
{
223-
type: :positions,
224-
conditions: {employee_id: employee_ids},
225-
}
218+
context "with includes" do
219+
before do
220+
resource.class_eval do
221+
has_many :positions do
222+
scope do |employee_ids|
223+
{
224+
type: :positions,
225+
conditions: {employee_id: employee_ids},
226+
}
227+
end
226228
end
227229
end
230+
params[:include] = "positions"
228231
end
229-
params[:include] = "positions"
230-
end
231232

232-
it "works" do
233-
render
234-
expect(included("positions").map(&:id)).to eq([1, 2])
233+
it "works" do
234+
render
235+
expect(included("positions").map(&:id)).to eq([1, 2])
236+
end
237+
238+
it "includes relationship linkage" do
239+
render
240+
jsonapi_data.each do |record|
241+
data = record.relationships["positions"]["data"]
242+
expect(data.pluck(:type).uniq).to match_array(["positions"])
243+
expect(data.pluck(:id).uniq).to match_array(["1", "2"])
244+
end
245+
end
246+
247+
context "when custom foreign key given" do
248+
before do
249+
PORO::DB.data[:positions][0] = {id: 1, e_id: 1}
250+
PORO::DB.data[:positions][1] = {id: 2, e_id: 1}
251+
252+
resource.class_eval do
253+
has_many :positions, foreign_key: :e_id do
254+
scope do |employee_ids|
255+
{
256+
type: :positions,
257+
conditions: {e_id: employee_ids},
258+
}
259+
end
260+
end
261+
end
262+
params[:include] = "positions"
263+
end
264+
265+
it "is used" do
266+
render
267+
expect(included("positions").map(&:id)).to eq([1, 2])
268+
end
269+
end
235270
end
236271

237-
context "when custom foreign key given" do
272+
context "without includes and default linkage" do
238273
before do
239-
PORO::DB.data[:positions][0] = {id: 1, e_id: 1}
240-
PORO::DB.data[:positions][1] = {id: 2, e_id: 1}
241-
242274
resource.class_eval do
243-
has_many :positions, foreign_key: :e_id do
275+
has_many :positions do
244276
scope do |employee_ids|
245277
{
246278
type: :positions,
247-
conditions: {e_id: employee_ids},
279+
conditions: {employee_id: employee_ids},
248280
}
249281
end
250282
end
251283
end
252-
params[:include] = "positions"
284+
render
253285
end
254286

255-
it "is used" do
287+
it "does not include anything" do
288+
expect {
289+
included("positions")
290+
}.to raise_error(GraphitiSpecHelpers::Errors::NoSideloads)
291+
end
292+
293+
it "specifies meta[:included] = false" do
294+
jsonapi_data.each do |record|
295+
expect(record.relationships["positions"]["meta"]["included"]).to eq(false)
296+
end
297+
end
298+
299+
it "does not includes relationship linkage" do
300+
jsonapi_data.each do |record|
301+
data = record.relationships["positions"]["data"]
302+
expect(data).to be_nil
303+
end
304+
end
305+
end
306+
307+
context "without includes and linkage always: true" do
308+
before do
309+
resource.class_eval do
310+
has_many :positions, linkage_always: true do
311+
scope do |employee_ids|
312+
{
313+
type: :positions,
314+
conditions: {employee_id: employee_ids},
315+
}
316+
end
317+
end
318+
end
256319
render
257-
expect(included("positions").map(&:id)).to eq([1, 2])
320+
end
321+
322+
it "does not include anything" do
323+
expect {
324+
included("positions")
325+
}.to raise_error(GraphitiSpecHelpers::Errors::NoSideloads)
326+
end
327+
328+
it "does not have meta[:included] = false" do
329+
jsonapi_data.each do |record|
330+
expect(record.relationships["positions"].dig("meta", "included")).to be_nil
331+
end
332+
end
333+
334+
it "includes relationship linkage" do
335+
jsonapi_data.each do |record|
336+
data = record.relationships["positions"]["data"]
337+
expect(data.pluck(:type).uniq).to match_array(["positions"])
338+
expect(data.pluck(:id).uniq).to match_array(["1", "2"])
339+
end
258340
end
259341
end
260342
end
@@ -270,23 +352,92 @@ def self.name
270352

271353
let(:base_scope) { {type: :positions} }
272354

273-
before do
274-
resource.class_eval do
275-
belongs_to :employee do
276-
scope do |employee_ids|
277-
{
278-
type: :employees,
279-
conditions: {id: employee_ids},
280-
}
355+
context "with includes" do
356+
before do
357+
resource.class_eval do
358+
belongs_to :employee do
359+
scope do |employee_ids|
360+
{
361+
type: :employees,
362+
conditions: {id: employee_ids},
363+
}
364+
end
281365
end
282366
end
367+
params[:include] = "employee"
368+
end
369+
370+
it "works" do
371+
render
372+
expect(included("employees").map(&:id)).to eq([1])
373+
end
374+
375+
it "has relationship linkage" do
376+
render
377+
378+
jsonapi_data.each do |record|
379+
data = record.relationships["employee"]["data"]
380+
381+
expect(data[:type]).to eq("employees")
382+
expect(data[:id]).to eq("1")
383+
end
283384
end
284-
params[:include] = "employee"
285385
end
286386

287-
it "works" do
288-
render
289-
expect(included("employees").map(&:id)).to eq([1])
387+
context "with default linkage" do
388+
before do
389+
resource.class_eval do
390+
belongs_to :employee do
391+
scope do |employee_ids|
392+
{
393+
type: :employees,
394+
conditions: {id: employee_ids},
395+
}
396+
end
397+
end
398+
end
399+
end
400+
401+
it "has relationship linkage" do
402+
render
403+
404+
jsonapi_data.each do |record|
405+
data = record.relationships["employee"]["data"]
406+
407+
expect(data[:type]).to eq("employees")
408+
expect(data[:id]).to eq("1")
409+
end
410+
end
411+
end
412+
413+
context "with linkage: false" do
414+
before do
415+
resource.class_eval do
416+
belongs_to :employee, linkage_always: false do
417+
scope do |employee_ids|
418+
{
419+
type: :employees,
420+
conditions: {id: employee_ids},
421+
}
422+
end
423+
end
424+
end
425+
end
426+
427+
it "works" do
428+
render
429+
expect(included("employees").map(&:id)).to eq([1])
430+
end
431+
432+
it "has no relationship linkage" do
433+
render
434+
435+
jsonapi_data.each do |record|
436+
data = record.relationships["employee"]
437+
438+
expect(data.keys).to_not include('data')
439+
end
440+
end
290441
end
291442
end
292443

0 commit comments

Comments
 (0)