固定裝置

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 在文章中新增了一個 authorId 外部鍵。belongsTo 外部鍵的慣例是

belongsToForeignKey = `${relationshipName}Id`

在這種情況下,一篇文章會獲得一個 authorId,即使該關聯指向的是一個 User 模型。由於模型可以有多個指向相同類型模型的關聯,因此始終使用關聯名稱而不是模型名稱。

看看上面的資料庫轉儲,如果你想只使用 Fixtures 來重建相同的關聯圖,你的資料只需要與之匹配即可

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" }],
  },
})

一旦這些 fixtures 被載入到 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 支援任意單向關聯。如果兩個關聯互為反向,如上述情況,只要你使用 ORM 方法,Mirage 將會保持每個模型上的鍵同步。

正如你所見,維護外鍵並保持它們在 fixture 檔案中的同步可能會有些混亂,這就是為什麼 Mirage 建議在大多數資料建立時使用 factories 的原因。

儘管如此,fixtures 在某些情況下仍然非常有用,因此它們是工具箱中一個很好的工具。


接下來,我們將透過學習序列化器來總結本節指南,它讓我們可以自訂 Mirage 在回應應用程式之前格式化資料的方式。