關聯
一旦定義好模型,就可以使用 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,
},
})
此輔助函式會將 commentIds
屬性新增至 blogPost
模型,以及一些用於處理關聯的 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。
接下來,讓我們看看工廠,它利用您的模型定義來輕鬆建立關係資料圖。