0
点赞
收藏
分享

微信扫一扫

【Vapor】08 Chapter 9: Parent-Child Relationships


0x00 Chapter 9: Parent-Child Relationships

5.Setting up the relationship

Because a ​​user​​​ owns each ​​acronym​​​, you add a ​​user​​​ property to the ​​acronym​​.

a. open Acronym.swift

add a new property after​var long: String​

    @Parent(key: "userID")
var user: User

Replace the initializer

    init(id: UUID? = nil, short: String, long: String, userID: User.IDValue) {
self.id = id
self.short = short
self.long = long
self.$user.id = userID
}

b. open CreateAcronym.swift

Before ​​.create()​​ add the following line

    .field("userID", .uuid, .required)

c. open AcronymsController.swift

add the following code At the bottom of file

struct CreateAcronymData: Content {
let short: String
let long: String
let userID: UUID
}

update the body of ​​createHandler(_:)​​ :

    func createHandler(_ req: Request) throws -> EventLoopFuture<Acronym> {
//let acronym = try req.content.decode(Acronym.self)
let data = try req.content.decode(CreateAcronymData.self)
let acronym = Acronym(short: data.short, long: data.long, userID: data.userID)
return acronym.save(on: req.db).map { acronym }
}

update the body of ​​updateHandler(_:) ​​:

    func updateHandler(_ req: Request) throws -> EventLoopFuture<Acronym> {
//let updatedAcronym = try req.content.decode(Acronym.self)
let updateData = try req.content.decode(CreateAcronymData.self)
return Acronym.find(req.parameters.get("acronymID"), on: req.db)
.unwrap(or: Abort(.notFound)).flatMap { acronym in
acronym.short = updateData.short
acronym.long = updateData.long
acronym.$user.id = updateData.userID
return acronym.save(on: req.db).map {
acronym
}
}
}

6.reset the database

To add the ​​new column​​​ to the table, you must ​​delete​​​ the database so ​​Fluent​​ will run the migration again.

如果数据库在运行,先停止
打开终端:
​​​docker stop postgres​

删除数据库:
​​​docker rm postgres​

重新创建数据库:

docker run --name postgres \
-e POSTGRES_DB=vapor_database \
-e POSTGRES_USER=vapor_username \
-e POSTGRES_PASSWORD=vapor_password \
-p 5432:5432 \
-d postgres

因为数据库被删除了
所以数据需要重新生成
参考前面几遍文章

提交 ​​acronym​​ 数据:

url: ​​http://127.0.0.1:8080/api/acronyms​​​ method: ​​POST​​ parameters: ​​{"short": "MMD", "long":"么么哒","userID":"A1B2C3D4"}​

​userID​​​ 是随便写的
后面加了外键约束后,就不能随便写了

提交 ​​user​​​ 数据:
url: ​​​http://127.0.0.1:8080/api/users​​​ method: ​​POST​​ parameters: ​​{"name": "老三", "username":"张三"}​

7.Querying the relationship

Getting the parent

open AcronymsController.swift
add a ​​​new​​​ route handler after ​​sortedHandler(_:)​​:

    func getUserHandler(_ req: Request) throws -> EventLoopFuture<User> {
Acronym.find(req.parameters.get("acronymID"), on: req.db)
.unwrap(or: Abort(.notFound))
.flatMap { acronym in
acronym.$user.get(on: req.db)
}
}

Register the route handler at the ​​end​​​ of ​​boot(routes:)​

    acronymsRoutes.get(":acronymID", "user", use: getUserHandler)

根据 ​​acronym​​​ 的 ​​ID​​​ 查询 ​​user​​​ url: ​​http://127.0.0.1:8080/api/acronyms/F3320C03-8570-443F-A8AB-071681470DA4/user​​ method: ​​GET​​ parameters: ​​无​

通过浏览器直接访问
返回数据,格式化后:

{
"id": "0DFD7B3A-F38D-43AA-8DD5-26B71E4FE3D0",
"username": "张三",
"name": "老三"
}

Getting the children

open User.swift
add a ​​​new​​​ property below ​​var username: String​

    @Children(for: \.$user)
var acronyms: [Acronym]

open UsersController.swift
add a ​​​new​​ route handler after​getHandler(_:)​​:

    func getAcronymsHandler(_ req: Request) throws -> EventLoopFuture<[Acronym]> {
User.find(req.parameters.get("userID"), on: req.db)
.unwrap(or: Abort(.notFound))
.flatMap { user in
user.$acronyms.get(on: req.db)
}
}

Register the route handler at the ​​end​​​ of ​​boot(routes:)​​:

usersRoute.get(":userID", "acronyms", use: getAcronymsHandler)

根据 ​​user​​​ 的 ​​ID​​​ 查询 ​​acronym​​​ url: ​​http://127.0.0.1:8080/api/users/0DFD7B3A-F38D-43AA-8DD5-26B71E4FE3D0/acronyms​​ method: ​​GET​​ parameters: ​​无​

通过浏览器直接访问
返回数据:

[
{
"id": "F3320C03-8570-443F-A8AB-071681470DA4",
"short": "MMD",
"long": "么么哒",
"user": {
"id": "0DFD7B3A-F38D-43AA-8DD5-26B71E4FE3D0"
}
}
]

8.Foreign key constraints

外键约束

describe a ​​link​​​ between ​​two​​ tables

Using ​​foreign key constraints​​​ has a number of ​​benefits​​:

  • It ensures you​​can’t​​ create acronyms with users that ​​don’t​​ exist
  • You​​can’t​​ delete users until you’ve ​​deleted​​ all their acronyms.
  • You​​can’t​​ delete the user table until you’ve ​​deleted​​ the acronym table.

9.Foreign key constraints are set up in the migration.

Open ​​CreateAcronym.swift​​​,
and replace​.field("userID", .uuid, .required)​​ with the following

.field("userID", .uuid, .required, .references("users", "id"))

Finally, because you’re linking the acronym’s ​​userID​​​ property to the ​​User​​​ table
you must ​​​create​​​ the ​​User​​​ table ​​first​​​ In ​​configure.swift​​, move the ​​User​​ migration to before the ​​Acronym​​ migration:

    app.migrations.add(CreateUser())
app.migrations.add(CreateAcronym())

最后再重新操作一遍:
停止数据库:
​​​docker stop postgres​

删除数据库:
​​​docker rm postgres​

重新创建数据库:

docker run --name postgres \
-e POSTGRES_DB=vapor_database \
-e POSTGRES_USER=vapor_username \
-e POSTGRES_PASSWORD=vapor_password \
-p 5432:5432 \
-d postgres

提交 ​​acronym​​​ 时,如果 ​​userID​​​ 随便写
比如把 ​​​userID​​​ 最后一位改一下
会导致错误:
​​​violates foreign key constraint​​ 违反外键约束

{
"error": true,
"reason": "server: insert or update on table \"acronyms\" violates foreign key constraint \"acronyms_userID_fkey\" (ri_ReportViolation)"
}

【Vapor】08 Chapter 9: Parent-Child Relationships_docker



举报

相关推荐

0 条评论