diff --git a/docs/guide/model/decorators.md b/docs/guide/model/decorators.md index 23a3068..017eda3 100644 --- a/docs/guide/model/decorators.md +++ b/docs/guide/model/decorators.md @@ -229,3 +229,19 @@ class Cluster extends Model { image!: Image | null } ``` + +### `@MorphMany` + +Marks a property on the model as a [morphMany attribute](../relationships/polymorphic) type. For example: + +```ts +import { Model, MorphMany } from '@vuex-orm/core' +import Comment from '@/models/Comment' + +class Video extends Model { + static entity = 'videos' + + @MorphMany(() => Comment, 'commentableId', 'commentableType') + comments!: Comment[] +} +``` diff --git a/docs/guide/relationships/polymorphic.md b/docs/guide/relationships/polymorphic.md index f9ac56f..444e1eb 100644 --- a/docs/guide/relationships/polymorphic.md +++ b/docs/guide/relationships/polymorphic.md @@ -75,3 +75,77 @@ class User extends Model { } } ``` + +## One To Many + +A one-to-many polymorphic relation is similar to a simple one-to-many relation; however, the target model can belong to +more than one type of model on a single association. For example, a `Comment` might be associated with a `Post` or +`Video` model. + +### Defining A One To Many Polymorphic Relationship + +To define this relationship, for example, a `Post` or `Video` model might be associated with one or more `Comment`(s), we +define a `morphMany` field to the `Post` and `Video` models. + +```js +class Comment extends Model { + static entity = 'comments' + + static fields () { + return { + id: this.number(0), + url: this.string(''), + commentableId: this.number(0), + commentableType: this.string(''), + } + } +} + +class Video extends Model { + static entity = 'videos' + + static fields () { + return { + id: this.number(0), + link: this.string(''), + comments: this.morphMany(Comment, 'commentableId', 'commentableType') + } + } +} + +class Post extends Model { + static entity = 'posts' + + static fields () { + return { + id: this.number(0), + title: this.string(''), + comments: this.morphMany(Comment, 'commentableId', 'commentableType') + } + } +} +``` + +The first argument passed to the `morphMany` method is the name of the model, the second argument is the name of the +field which will contain the `id` of the model, and the third argument is the name of the field which will contain the +`entity` of the parent model. The third argument is used to determine the "type" of the related parent model. + +Additionally, Vuex ORM assumes that the foreign key should have a value matching the `id` +(or the custom `static primaryKey`) field of the parent. In other words, Vuex ORM will look for the value of the +video's `id` field in the `commentableId` field of the `Comment` record. If you would like the relationship to use a +value other than `id`, you may pass a fourth argument to the `morphMany` method specifying your custom key: + +```js +class Video extends Model { + static entity = 'videos' + + static fields () { + return { + id: this.number(0), + videoId: this.string(''), + link: this.string(''), + comments: this.morphMany(Comment, 'commentableId', 'commentableType', 'videoId') + } + } +} +```