第 6 部分 – 關聯

這個應用程式還有另一個功能 – 清單。如果您點擊提醒面板左側的按鈕,就會開啟一個側邊面板,顯示這個應用程式中不同的清單。

Failing

但現在,我們的控制台中只會看到一個錯誤,因為我們的應用程式預期會從 /api/lists 提取清單。讓我們模擬這個端點。

首先,我們將在伺服器頂部定義一個新的 list 模型

models: {
  list: Model,
  reminder: Model,
}

我們還會為 GET 到 /api/lists 的請求新增一個路由處理器,傳回所有清單

this.get("/api/lists", (schema, request) => {
  return schema.lists.all()
})

Mirage 現在會回應 200,但沒有清單。讓我們在 seeds() 中建立一些清單

seeds(server) {
  server.create("reminder", { text: "Walk the dog" });
  server.create("reminder", { text: "Take out the trash" });
  server.create("reminder", { text: "Work out" });

  server.create("list", { name: "Home" });
  server.create("list", { name: "Work" });
}

現在,當我們開啟側邊欄時,會看到兩個新的清單「家庭」和「工作」正在呈現。

嘗試點擊一個清單。您會看到一個錯誤,因為我們的應用程式預期存在另一個 API 端點:/api/lists/1/reminders。這就是它擷取特定清單的提醒的方式。讓我們看看如何模擬它。

在 Mirage 中模擬處理關聯資料的端點最簡單的方式是使用關聯。我們會先使用 Mirage 的關聯輔助程式來為這個資料建模。

在這個應用程式中,清單和提醒之間存在一對多的關聯(一個清單可以有很多提醒),因此我們將使用 hasManybelongsTo 輔助程式來定義這種關聯。

匯入這些輔助程式並更新您的模型以定義這種關聯

import { createServer, Model, hasMany, belongsTo } from "miragejs"

export default function () {
  createServer({
    models: {
      list: Model.extend({
        reminders: hasMany(),
      }),

      reminder: Model.extend({
        list: belongsTo(),
      }),
    },

    // rest of server
  })
}

現在 Mirage 知道 list.remindersreminder.list 屬性是關聯,因此我們可以開始在我們的路由處理器中使用它們。

讓我們使用我們新的關聯來模擬 /api/lists/:id/reminders。這個端點應該查詢對應的清單,並回應屬於該清單的所有提醒。

以下是程式碼

this.get("/api/lists/:id/reminders", (schema, request) => {
  let listId = request.params.id
  let list = schema.lists.find(listId)

  return list.reminders
})

我們使用 :id 的動態區段,它對應於我們點擊的清單。然後,我們使用該 ID 在 Mirage 的資料層中查詢對應的清單。最後,我們傳回與該清單關聯的提醒。

將此路由處理器複製到您的 Mirage 伺服器定義中,並嘗試點擊每個清單。您應該不會再看到錯誤。但是您也不會看到任何提醒。這是因為我們到目前為止建立的提醒並未與任何清單關聯 – 我們只是單獨建立它們。

若要為特定清單建立提醒,我們可以利用我們新的關聯。

seeds(server) {
  // Unassociated reminders
  server.create("reminder", { text: "Walk the dog" });
  server.create("reminder", { text: "Take out the trash" });
  server.create("reminder", { text: "Work out" });

  let homeList = server.create("list", { name: "Home" });
  server.create("reminder", { list: homeList, text: "Do taxes" });

  let workList = server.create("list", { name: "Work" });
  server.create("reminder", { list: workList, text: "Visit bank" });
}

現在,點擊「家庭」應該會顯示「繳稅」提醒。如果您點擊「全部」,應用程式將會連線至 /api/reminders 端點,它仍然會傳回我們系統中的所有提醒 – 包括與清單關聯的提醒,以及單獨存在的提醒。

最後,嘗試在 UI 中為特定清單建立新的提醒。點擊「工作」,然後新增「回覆 Jill」的提醒。如果您點擊應用程式,您會看到它已正確地與「工作」清單關聯。(它會顯示在「工作」和「全部」中,但不會顯示在「家庭」中)。

這是因為我們的 UI 已經在我們在清單上建立提醒時傳送 { listId }。若要查看此情況,我們可以在我們現有的 POST 路由處理器中新增一個記錄,以檢查請求中的 attrs

this.post("/api/reminders", (schema, request) => {
  let attrs = JSON.parse(request.requestBody)
  console.log(attrs)

  return schema.reminders.create(attrs)
})

當建立未關聯的待辦事項時,attrs 為 { text: "新待辦事項" },但關聯的待辦事項具有類似 { text: "回覆 Jill", listId: "2" } 的 attrs。

當我們定義關聯時,Mirage 在我們的模型上設定了特殊的屬性,稱為外來鍵。這就是它追蹤哪些模型彼此關聯的方式。設定類似 listIdreminderIds: [] 的外來鍵足以更新關聯,並使其反映在您所有的 Mirage 路由處理器中。

因此,我們不必更新我們的 POST 處理器來適應我們 UI 的清單功能,因為 listId 已經傳遞到 reminders.create() 中。

Mirage 的關聯輔助程式足夠彈性,可以為幾乎任何資料情況建模,讓您在模擬處理關聯的端點時更容易完成工作。

重點

  • Mirage 讓您可以定義和存取關聯資料
  • 使用 belongsTohasMany 輔助程式來定義模型上的具名關聯
  • 在路由處理器中使用關聯來傳回與其他模型關聯的模型或集合
  • Mirage 使用簡單的外來鍵來追蹤關聯資料