【Vapor】09 Chapter 10:Sibling Relationships

11 篇文章 1 订阅

0x00 Chapter 10 Sibling Relationships

1.Sibling relationships describe a relationship that links two models to each other
They are also known as many-to-many relationships

Unlike parent-child relationships,
there are no constraints between models in a sibling relationship

For instance, if you model the relationship between pets and toys
a pet can have one or more toys
and a toy can be used by one or more pets

In the TIL application, you’ll be able to categorize acronyms.
An acronym can be part of one or more categories
and a category can contain one or more acronyms


2.Category model
create a new file Category.swift
in Sources/App/Models

import Vapor
import Fluent

final class Category: Model, Content {
    static let schema = "categories"
    
    @ID
    var id: UUID?
    
    @Field(key: "name")
    var name: String
    
    init() {}
    
    init(id: UUID? = nil, name: String) {
        self.id = id
        self.name = name
    }
}


3.Migration
create a new file CreateCategory.swift
in Sources/App/Migrations

import Fluent

struct CreateCategory: Migration {
    func prepare(on database: Database) -> EventLoopFuture<Void> {
        database.schema("categories")
            .id()
            .field("name", .string, .required)
            .create()
    }
    
    func revert(on database: Database) -> EventLoopFuture<Void> {
        database.schema("categories").delete()
    }
}

open configure.swift and add CreateCategory to the migration list, after
app.migrations.add(CreateAcronym())

app.migrations.add(CreateCategory())

4.Category controller
create a new file called CategoriesController.swift
In Sources/App/Controllers

import Fluent
import Vapor

struct CategoriesController: RouteCollection {
    func boot(routes: RoutesBuilder) throws {
        let categoriesRoute = routes.grouped("api", "categories")
        categoriesRoute.post(use: createHandler)
        categoriesRoute.get(use: getAllHandler)
        categoriesRoute.get(":categoryID", use: getHandler)
        categoriesRoute.get(":categoryID", "acronyms", use: getAcronymsHandler)
    }
    
    func createHandler(_ req: Request) throws -> EventLoopFuture<Category> {
        let category = try req.content.decode(Category.self)
        return category.save(on: req.db).map { category }
    }
    
    func getAllHandler(_ req: Request) throws -> EventLoopFuture<[Category]> {
        Category.query(on: req.db).all()
    }
    
    //
    func getHandler(_ req: Request) throws -> EventLoopFuture<Category> {
        Category.find(req.parameters.get("categoryID"), on: req.db)
            .unwrap(or: Abort(.notFound))
    }
    
    // http://127.0.0.1:8080/api/categories/<categoryID>/acronyms
    func getAcronymsHandler(_ req: Request) throws -> EventLoopFuture<[Acronym]> {
        Category.find(req.parameters.get("categoryID"), on: req.db)
            .unwrap(or: Abort(.notFound))
            .flatMap { category in
                category.$acronyms.get(on: req.db)
            }
    }
}

open routes.swift and register the controller by adding the following to the
end of routes(_:)

app.migrations.add(CreateCategory())

通过 Rested 提交 category 数据
url:http://127.0.0.1:8080/api/categories
method:POST
parameter:{"name": "Teenager"}
请添加图片描述


5.Creating a pivot
In Chapter 9, “Parent Child Relationships”, you added a reference to the user in the acronym to create the relationship between an acronym and a user

However, you can’t model a sibling relationship like this as it would be too inefficient to query

You need a separate model to hold on to this relationship. In Fluent, this is a pivot

create file called AcronymCategoryPivot.swift
in Sources/App/Models

import Vapor
import Fluent

final class AcronymCategoryPivot: Model {
    static let schema = "acronym-category-pivot"
    
    @ID
    var id: UUID?
    
    @Parent(key: "acronymID")
    var acronym: Acronym
    
    @Parent(key: "categoryID")
    var category: Category
    
    init() {}
    
    init(id: UUID? = nil, acronym: Acronym, category: Category) throws {
        self.id = id
        self.$acronym.id = try acronym.requireID()
        self.$category.id = try category.requireID()
    }
}

Create CreateAcronymCategoryPivot.swift
in Sources/App/Migrations

import Fluent

struct CreateAcronymCategoryPivot: Migration {
    func prepare(on database: Database) -> EventLoopFuture<Void> {
        database.schema("acronym-category-pivot")
            .id()
            .field("acronymID", .uuid, .required, .references("acronyms", "id", onDelete: .cascade))
            .field("categoryID", .uuid, .required, .references("categories", "id", onDelete: .cascade))
            .create()
    }
    
    func revert(on database: Database) -> EventLoopFuture<Void> {
        database.schema("acronym-category-pivot").delete()
    }
}

As in Chapter 9, “Parent Child Relationships,” it’s good practice to use foreign key
constraints with sibling relationships

The migration also sets a cascade schema reference action when you delete the model.
This causes the database to remove the relationship automatically instead of throwing an error

open configure.swift and add CreateAcronymCategoryPivot to the
migration list, after app.migrations.add(CreateCategory())

app.migrations.add(CreateAcronymCategoryPivot())

0x01 创建关联关系(多对多)

下篇正在准备中…
敬请期待~


0x02 我的作品

欢迎体验我的作品之一:小五笔小程序
五笔学习好帮手!
微信 搜索即可~


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

豪冷啊

你的鼓励是对我的认可!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值