数据模型
Mirage 还允许您使用扁平数据模型文件来为您的数据库播种数据。
通常,我们建议在大多数情况下使用工厂,因为它们往往使您的模拟数据更容易维护。但当然,数据模型在某些时候是有意义的。
数据模型只不过是完成以下操作的一种传统方法
import { createServer } from "miragejs"
createServer({
seeds(server) {
server.db.loadData({
countries: [
{ id: 1, name: "China" },
{ id: 2, name: "India" },
{ id: 3, name: "United States" },
],
})
},
})
让我们看看如何使用数据模型做同样的事情。
基本用法
数据模型数据可以使用 fixtures
键传递到 Mirage 服务器定义中
import { createServer } from "miragejs"
createServer({
fixtures: {
countries: [
{ id: 1, name: "China" },
{ id: 2, name: "India" },
{ id: 3, name: "United States" },
],
},
})
除非您定义了 seeds 函数,否则这些数据将自动加载到 Mirage 的数据库中,作为其初始数据。
如果您定义了 seeds 函数,Mirage 假设您希望使用工厂来播种数据
import { createServer } from "miragejs"
createServer({
fixtures: {
countries: [
{ id: 1, name: "China" },
{ id: 2, name: "India" },
{ id: 3, name: "United States" },
],
},
seeds(server) {
// Fixtures won't be loaded automatically, because this function is defined
server.create("post")
},
})
但是,您可以通过在默认场景中调用 server.loadFixtures
来将数据模型与工厂结合使用
import { createServer } from "miragejs"
createServer({
fixtures: {
countries: [
{ id: 1, name: "China" },
{ id: 2, name: "India" },
{ id: 3, name: "United States" },
],
},
seeds(server) {
// Load all fixture data into the development db
server.loadFixtures()
// Also create some db data using factories
server.create("post")
},
})
通常,数据模型会被提取到单独的文件中。我们可以将国家数据模型数据放到自己的 fixtures/countries.js
文件中,并将其导出为数组
// mirage/fixtures/countries.js
export default [
{ id: 1, name: "China", largestCity: "Shanghai" },
{ id: 2, name: "India", largestCity: "Mumbai" },
{ id: 3, name: "United States", largestCity: "New York City" },
{ id: 4, name: "Indonesia", largestCity: "Jakarta" },
{ id: 5, name: "Pakistan", largestCity: "Karachi" },
{ id: 6, name: "Brazil", largestCity: "São Paulo" },
{ id: 7, name: "Nigeria", largestCity: "Lagos" },
{ id: 8, name: "Bangladesh", largestCity: "Dhaka" },
{ id: 9, name: "Russia", largestCity: "Moscow" },
{ id: 10, name: "Mexico", largestCity: "Mexico City" },
]
现在我们可以导入它并将其传递到服务器定义中
import { createServer } from "miragejs"
import countries from "./fixtures/countries"
createServer({
fixtures: {
countries,
},
})
许多团队发现将某些种子数据存储为单独的数据模型文件很有用。
属性格式化
由于数据模型数据直接读入 Mirage 的数据库,因此对于所有多字属性都使用 camelCase 非常重要。(Mirage 使用 camelCasing 约定来避免对标识外键等事物的配置。)
如果您生产 API 格式不使用 camelCase,请不要担心。我们将在序列化器层中自定义 Mirage 的 API 格式。
loadFixtures 助手
如上所述,如果 Mirage 检测到数据模型和默认场景,它将不会自动加载数据模型数据。
要在开发期间将数据模型加载到数据库中,请在默认场景中调用 server.loadFixtures
seeds(server) {
server.loadFixtures()
}
server.loadFixtures()
将加载所有数据模型。您可以通过将数据模型名称的实参列表传递到 loadFixtures
来选择性地加载数据模型
import { createServer, Model } from "miragejs"
import cities from "./fixtures/cities"
import countries from "./fixtures/countries"
import users from "./fixtures/users"
createServer({
models: {
country: Model,
city: Model,
user: Model,
},
fixtures: {
countries: countries,
cities: cities,
users: users,
},
seeds(server) {
// only load the countries and cities fixtures
server.loadFixtures("countries", "cities")
},
})
与默认场景一样,数据模型在测试期间将被忽略。如果您想在测试中加载数据模型数据,可以调用 server.loadFixtures
test("I can see the countries", async function (assert) {
server.loadFixtures("countries")
await visit("/")
assert.dom("option.country").exists({ length: 100 })
})
关系
没有专门的 API 用于使用数据模型创建关系,您只需要了解 Mirage 如何使用外键来连接关系。
假设我们有以下模型
import { createServer, Model } from "miragejs"
createServer({
models: {
user: Model,
post: Model.extend({
author: belongsTo("user"),
}),
},
})
使用 ORM,我们可以创建两个相关的模型
let chris = schema.users.create({ name: "Chris Garrett" })
schema.posts.create({
author: chris,
title: "Coming Soon in Ember Octane",
})
如果我们在此之后查看 Mirage 的数据库,我们将看到以下数据
// server.db.dump()
{
"users": [{ "id": "1", "name": "Chris Garrett" }],
"posts": [
{ "id": "1", "authorId": "1", "title": "Coming Soon in Ember Octane" }
]
}
如您所见,Mirage 在 post 中添加了一个 authorId
外键。belongsTo 外键的约定是
belongsToForeignKey = `${relationshipName}Id`
在本例中,post 获取了一个 authorId
,即使该关系指向 User
模型。始终使用关系名称而不是模型名称,因为模型可以具有指向同一类型模型的多个关系。
查看上面的数据库转储,如果您想仅使用数据模型重新创建相同的关系图,您的数据只需要匹配它
import { createServer, Model } from "miragejs"
createServer({
models: {
user: Model,
post: Model.extend({
author: belongsTo("user"),
}),
},
fixtures: {
users: [{ id: "1", name: "Chris Garrett" }],
posts: [{ id: "1", authorId: "1", title: "Coming Soon in Ember Octane" }],
},
})
一旦这些数据被加载到 Mirage 中,所有 ORM 方法、快捷方式和序列化器将按预期工作。
如果这是一个双向关系
models: {
user: Model.extend({
+ posts: hasMany()
}),
post: Model.extend({
author: belongsTo("user"),
}),
},
那么 Mirage 将为新的 hasMany 关联添加一组外键
// server.db.dump()
{
"users": [{ "id": "1", "name": "Chris Garrett", "postIds": ["1"] }],
"posts": [
{ "id": "1", "authorId": "1", "title": "Coming Soon in Ember Octane" }
]
}
hasMany 关系外键的约定是
hasManyForeignKey = `${singularize(relationshipName)}Ids`
所有关联都有自己的键,因为 Mirage 支持任意单向关系。如果两个关联是彼此的倒数,如上例所示,Mirage 将在使用 ORM 方法的情况下保持每个模型上的键同步。
如您所见,维护外键并使其在 fixture 文件中保持同步可能会变得有点混乱,这就是为什么 Mirage 建议您在大多数数据创建中使用工厂的原因。
尽管如此,fixture 在某些情况下仍然非常有用,因此它们是您工具箱中的一款好工具。
接下来,我们将通过学习序列化器来结束本节指南,序列化器允许我们自定义 Mirage 在将数据发回以响应我们的应用程序之前如何格式化数据。