关系
定义完模型后,可以使用 belongsTo
和 hasMany
辅助函数来定义它们之间的关系。每个辅助函数都会为你的模型添加一些动态方法。
belongsTo
要定义一对一关系,导入 belongsTo
辅助函数,并在指向另一个模型的模型上定义一个新属性
import { createServer, Model, belongsTo } from "miragejs"
createServer({
models: {
blogPost: Model.extend({
author: belongsTo(),
}),
author: Model,
},
})
这定义了与 Author
模型的 belongsTo
关系。
该 belongsTo
辅助函数为你的模型添加了一些新属性和方法。
在本例中,我们的 BlogPost
模型现在获得了一个 authorId
属性,以及一些用于处理关联的 author
模型的方法
blogPost.authorId // 1
blogPost.authorId = 2 // updates the relationship
blogPost.author // Author instance
blogPost.author = anotherAuthor
blogPost.newAuthor(attrs) // new unsaved author
blogPost.createAuthor(attrs) // new saved author (updates blogPost.authorId in memory only)
请注意,createAuthor
方法将创建一个新作者并立即将其保存到 db
中,但博客文章的外键仅在此实例中更新,并且不会立即持久保存到数据库。因此,blogPost.authorId
将在内存中更新,但如果你再次从 db
中获取 blogPost
,则关系不会持久保存。
要持久保存新外键,你需要在创建新作者后调用 blogPost.save()
。
hasMany
要定义一对多关系,使用 hasMany
辅助函数
import { createServer, Model, hasMany } from "miragejs"
createServer({
models: {
blogPost: Model.extend({
comments: hasMany(),
}),
comment: Model,
},
})
该辅助函数为 blogPost
模型添加了 commentIds
属性,以及一些用于处理关联的 comments
集合的方法
blogPost.commentIds // [1, 2, 3]
blogPost.commentIds = [2, 3] // updates the relationship
blogPost.comments // array of related comments
blogPost.comments = [comment1, comment2] // updates the relationship
blogPost.newComment(attrs) // new unsaved comment
blogPost.createComment(attrs) // new saved comment (comment.blogPostId is set)
一对一
可以使用两个模型上的 belongsTo
辅助函数来定义一对一关系
import { createServer, Model, belongsTo } from "miragejs"
createServer({
models: {
supplier: Model.extend({
account: belongsTo(),
}),
account: Model.extend({
supplier: belongsTo(),
}),
},
})
默认情况下,Mirage 会将这两个关系标记为彼此的倒数,因此能够在它们发生变化时保持同步。例如,如果 supplierA.account
为 accountB
,则 accountB.supplier
将指向 supplierA
。如果 supplierA.account
设置为 null
,则 accountB.supplier
关系侧也将设置为 null
以保持关系同步。
一对多
可以使用一个模型上的 belongsTo
助手和逆模型上的 hasMany
助手来定义一对多关系。
import { createServer, Model, belongsTo, hasMany } from "miragejs"
createServer({
models: {
user: Model.extend({
comments: hasMany(),
}),
comment: Model.extend({
user: belongsTo(),
}),
},
})
Mirage 会将它们标记为彼此的逆,并在它们发生变化时保持同步。
多对多
可以使用两个模型上的 hasMany
助手来定义多对多关系。
import { createServer, Model, hasMany } from "miragejs"
createServer({
models: {
blogPost: Model.extend({
tags: hasMany(),
}),
tag: Model.extend({
blogPosts: hasMany(),
}),
},
})
Mirage 会将它们标记为彼此的逆,并在它们发生变化时保持同步。
关联选项
以下选项可用于自定义您的 belongsTo
和 hasMany
关系定义。
modelName
如果您的关联模型与关联本身的名称不同,则可以在关联上指定 modelName
。
例如,
import { createServer, Model, belongsTo, hasMany } from "miragejs"
createServer({
models: {
user: Model,
annotation: Model,
blogPost: Model.extend({
author: belongsTo("user"),
comments: hasMany("annotation"),
}),
},
})
将添加上面列出的所有名为 author
和 comment
的方法,但使用 User
和 Annotation
模型用于实际关系。
inverse
通常,关系可以是彼此的逆。
例如,假设我们有以下两个模型
import { createServer, Model, belongsTo, hasMany } from "miragejs"
createServer({
models: {
blogPost: Model.extend({
comments: hasMany(),
}),
comment: Model.extend({
blogPost: belongsTo(),
}),
},
})
在这种情况下,blogPost.comments
将指向 Comment 模型的集合,并且这些 Comment 模型中的每一个都将具有一个 comment.blogPost
关系,该关系指向原始帖子。
Mirage 通常可以推断出两个不同模型上的两个关系是彼此的逆,但有时您需要明确说明。这通常发生在模型具有两个指向相同模型类型的关系时。
例如,假设我们有以下模式
import { createServer, Model, belongsTo, hasMany } from "miragejs"
createServer({
models: {
user: Model.extend({
blogPosts: hasMany(),
}),
blogPost: Model.extend({
author: belongsTo("user"),
reviewer: belongsTo("user"),
}),
},
})
在这种情况下,Mirage 不知道哪个关系(blogPost.author
或 blogPost.reviewer
)应与 user.blogPosts
集合同步。因此,您可以使用 inverse
选项指定哪一个是逆。
import { createServer, Model, belongsTo, hasMany } from "miragejs"
createServer({
models: {
user: Model.extend({
blogPosts: hasMany(),
}),
blogPost: Model.extend({
author: belongsTo("user", { inverse: "blogPosts" }),
reviewer: belongsTo("user", { inverse: null }),
}),
},
})
现在,如果将一篇博文添加到 user.blogPosts
,该博文的 author
将被正确更新。
polymorphic
您可以通过传递 { polymorphic: true }
作为选项来指定关联是否为多态关联。
例如,假设您有 BlogPost
和 Picture
模型,它们都可以有一个 Comment
。以下是模型定义的示例
import { createServer, Model, belongsTo, hasMany } from "miragejs"
createServer({
models: {
blogPost: Model.extend({
comments: hasMany(),
}),
picture: Model.extend({
comments: hasMany(),
}),
comment: Model.extend({
commentable: belongsTo({ polymorphic: true }),
}),
},
})
我们为 Comment
模型提供了一个 commentable
多态关系,因为被评论的模型可能是 BlogPost
或 Picture
。请注意,commentable
没有类型,因为在该关系上存在哪些类型的模型没有进行验证。
多态关联对其外键和构建/创建方法具有略微不同的方法签名。
let comment = server.schema.comments.create({ text: "foo" })
comment.buildCommentable("blog-post", { title: "Lorem Ipsum" })
comment.createCommentable("blog-post", { title: "Lorem Ipsum" })
// getter
comment.commentableId // { id: 1, type: 'blog-post' }
// setter
comment.commentableId = { id: 2, type: "picture" }
多对多关系也可以是多态的
import { createServer, Model, belongsTo, hasMany } from "miragejs"
createServer({
models: {
car: Model,
watch: Model
user: Model.extend({
things: hasMany({ polymorphic: true })
}),
},
})
let user = server.schema.users.create({ name: "Sam" });
user.buildThing('car', { attrs });
user.createThing('watch', { attrs });
// getter
user.thingIds; // [ { id: 1, type: 'car' }, { id: 3, type: 'watch' }, ... ]
// setter
user.thingIds = [ { id: 2, type: 'watch' }, ... ];
请务必查看 Schema、Model 和 Collection API 文档,以了解所有可用的 ORM 方法。
我们还将在这些指南中介绍序列化器,您将在其中学习如何自定义模型和集合的序列化形式以匹配您的生产 API。
接下来,让我们看一下工厂,工厂利用您的模型定义来简化创建关系数据的图表。