Skip to content

Commit 9e45e41

Browse files
committed
Support MorphToMany
1 parent 1a74579 commit 9e45e41

File tree

6 files changed

+234
-24
lines changed

6 files changed

+234
-24
lines changed

src/graphql/query-builder.ts

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Relation } from "@vuex-orm/core";
12
import Model from "../orm/model";
23
import { Arguments, Field, GraphQLField } from "../support/interfaces";
34
import { clone, isPlainObject, takeWhile, upcaseFirstLetter } from "../support/utils";
@@ -354,16 +355,32 @@ export default class QueryBuilder {
354355

355356
model.getRelations().forEach((field: Field, name: string) => {
356357
let relatedModel: Model;
357-
358-
if (field.related) {
359-
relatedModel = context.getModel(field.related.entity);
360-
} else if (field.parent) {
361-
relatedModel = context.getModel(field.parent.entity);
358+
let fieldAsRelation: Relation = field as Relation;
359+
360+
if (
361+
fieldAsRelation instanceof context.components.BelongsToMany ||
362+
fieldAsRelation instanceof context.components.HasMany ||
363+
fieldAsRelation instanceof context.components.HasManyThrough ||
364+
fieldAsRelation instanceof context.components.MorphedByMany ||
365+
fieldAsRelation instanceof context.components.MorphMany ||
366+
fieldAsRelation instanceof context.components.MorphOne ||
367+
fieldAsRelation instanceof context.components.MorphToMany ||
368+
fieldAsRelation instanceof context.components.HasOne
369+
) {
370+
relatedModel = context.getModel(fieldAsRelation.related.entity);
371+
} else if (
372+
fieldAsRelation instanceof context.components.BelongsTo ||
373+
fieldAsRelation instanceof context.components.HasManyBy
374+
) {
375+
relatedModel = context.getModel(fieldAsRelation.parent.entity);
376+
} else if (fieldAsRelation instanceof context.components.MorphTo) {
377+
relatedModel = context.getModel(fieldAsRelation.type);
362378
} else {
363379
relatedModel = context.getModel(name);
380+
364381
context.logger.log(
365-
"WARNING: field has neither parent nor related property. Fallback to attribute name",
366-
field
382+
"WARNING: unknown field type. Fallback to attribute name",
383+
fieldAsRelation
367384
);
368385
}
369386

test/integration/plugin.spec.ts

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { setupMockData, User, Profile, Post, Tariff, Category } from "../support/mock-data";
1+
import { setupMockData, User, Profile, Post, Tariff, Category, Tag } from "../support/mock-data";
22
import Context from "../../src/common/context";
33
import { recordGraphQLRequest } from "../support/helpers";
44

@@ -72,6 +72,12 @@ query Post($id: ID!) {
7272
}
7373
}
7474
}
75+
tags {
76+
nodes {
77+
id
78+
name
79+
}
80+
}
7581
}
7682
}
7783
`.trim() + "\n"
@@ -362,6 +368,12 @@ mutation CreatePost($post: PostInput!) {
362368
}
363369
}
364370
}
371+
tags {
372+
nodes {
373+
id
374+
name
375+
}
376+
}
365377
}
366378
}
367379
`.trim() + "\n"
@@ -448,6 +460,12 @@ mutation DeletePost($id: ID!) {
448460
}
449461
}
450462
}
463+
tags {
464+
nodes {
465+
id
466+
name
467+
}
468+
}
451469
}
452470
}
453471
`.trim() + "\n"
@@ -501,6 +519,12 @@ query UnpublishedPosts($authorId: ID!) {
501519
}
502520
}
503521
}
522+
tags {
523+
nodes {
524+
id
525+
name
526+
}
527+
}
504528
}
505529
}
506530
}
@@ -557,6 +581,12 @@ query UnpublishedPosts($authorId: ID!, $id: ID!) {
557581
}
558582
}
559583
}
584+
tags {
585+
nodes {
586+
id
587+
name
588+
}
589+
}
560590
}
561591
}
562592
}
@@ -615,6 +645,12 @@ mutation UpvotePost($captchaToken: String!, $postId: ID!) {
615645
}
616646
}
617647
}
648+
tags {
649+
nodes {
650+
id
651+
name
652+
}
653+
}
618654
}
619655
}
620656
`.trim() + "\n"
@@ -793,7 +829,21 @@ query Status {
793829

794830
describe("Polymorphic Many To Many", async () => {
795831
test("works", async () => {
796-
// TODO
832+
// @ts-ignore
833+
await Tag.fetch();
834+
835+
// @ts-ignore
836+
await Post.fetch(1);
837+
838+
const tag = Tag.query()
839+
.withAllRecursive()
840+
.find(1)!;
841+
842+
const post = Post.query()
843+
.withAllRecursive()
844+
.find(1);
845+
846+
expect(post!.tags).toContain(tag);
797847
});
798848
});
799849
});

test/integration/test-utils.spec.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,8 @@ describe("TestUtils", () => {
172172
id: 4,
173173
content: "Test content",
174174
title: "Test title",
175-
published: true
175+
published: true,
176+
tags: []
176177
});
177178

178179
let result;
@@ -195,7 +196,8 @@ describe("TestUtils", () => {
195196
otherId: 0,
196197
published: true,
197198
author: null,
198-
comments: []
199+
comments: [],
200+
tags: []
199201
}
200202
]
201203
});

test/support/mock-data.ts

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export class Profile extends ORMModel {
3838

3939
export class Video extends ORMModel {
4040
static entity = "videos";
41-
static eagerLoad = ["comments"];
41+
static eagerLoad = ["comments", "tags"];
4242

4343
static fields(): Fields {
4444
return {
@@ -49,14 +49,15 @@ export class Video extends ORMModel {
4949
otherId: this.number(0), // This is a field which ends with `Id` but doesn't belong to any relation
5050
ignoreMe: this.string(""),
5151
author: this.belongsTo(User, "authorId"),
52-
comments: this.morphMany(Comment, "subjectId", "subjectType")
52+
comments: this.morphMany(Comment, "subjectId", "subjectType"),
53+
tags: this.morphToMany(Tag, Taggable, "tagId", "subjectId", "subjectType")
5354
};
5455
}
5556
}
5657

5758
export class Post extends ORMModel {
5859
static entity = "posts";
59-
static eagerLoad = ["comments"];
60+
static eagerLoad = ["comments", "tags"];
6061

6162
static fields(): Fields {
6263
return {
@@ -67,7 +68,8 @@ export class Post extends ORMModel {
6768
otherId: this.number(0), // This is a field which ends with `Id` but doesn't belong to any relation
6869
published: this.boolean(true),
6970
author: this.belongsTo(User, "authorId"),
70-
comments: this.morphMany(Comment, "subjectId", "subjectType")
71+
comments: this.morphMany(Comment, "subjectId", "subjectType"),
72+
tags: this.morphToMany(Tag, Taggable, "tagId", "subjectId", "subjectType")
7173
};
7274
}
7375
}
@@ -152,6 +154,30 @@ export class Category extends ORMModel {
152154
}
153155
}
154156

157+
export class Taggable extends ORMModel {
158+
static entity = "taggables";
159+
160+
static fields(): Fields {
161+
return {
162+
id: this.increment(),
163+
tagId: this.number(0),
164+
subjectId: this.number(0),
165+
subjectType: this.string("")
166+
};
167+
}
168+
}
169+
170+
export class Tag extends ORMModel {
171+
static entity = "tags";
172+
173+
static fields(): Fields {
174+
return {
175+
id: this.increment(),
176+
name: this.string("")
177+
};
178+
}
179+
}
180+
155181
export async function setupMockData() {
156182
let store;
157183
let vuexOrmGraphQL;
@@ -165,7 +191,9 @@ export async function setupMockData() {
165191
{ model: TariffOption },
166192
{ model: Tariff },
167193
{ model: TariffTariffOption },
168-
{ model: Category }
194+
{ model: Category },
195+
{ model: Taggable },
196+
{ model: Tag }
169197
]);
170198

171199
setupTestUtils(VuexORMGraphQLPlugin);

0 commit comments

Comments
 (0)