在本章中,我们将为 Post 创建一个 Controller,将 Route 和 Route Handler 都移动到这里,保持项目代码的整洁
Table of Contents
Controller 中的 Routing
在上一章中,下面两个和 Post 相关的 Route 和 Handler 都写在了 Sources/App/configure.swift
中
- app.post("posts")
- app.get("posts")
现在我们创建 Sources/App/Controllers/PostController.swift
文件,并将代码移动到这里
import Fluent
import Vapor
struct PostController: RouteCollection {
func boot(routes: RoutesBuilder) throws {
routes.group("posts") { posts in
posts.get(use: index)
posts.post(use: create)
}
}
func create(req: Request) async throws -> Post {
let postData = try req.content.decode(Post.CreateDTO.self)
let post = Post(content: postData.content)
try await post.create(on: req.db)
return post
}
func index(req: Request) async throws -> [Post] {
let posts = try await Post.query(on: req.db).all()
return posts
}
}
在 boot 函数中,我们通过 RoutesBuilder 定义了 route 和 handler 之间的关系。
注册 Controller
现在我们需要将 Controller 注册到 Application 中,让 Application 知道有哪些路由需要被处理
修改 Sources/App/configure.swift
import Fluent
import FluentPostgresDriver
import Vapor
public func configure(_ app: Application) throws {
app.databases.use(.postgres(configuration: SQLPostgresConfiguration(
hostname: Environment.get("DATABASE_HOST") ?? "localhost",
port: Environment.get("DATABASE_PORT").flatMap(Int.init(_:)) ?? SQLPostgresConfiguration.ianaPortNumber,
username: Environment.get("DATABASE_USERNAME") ?? "vapor_username",
password: Environment.get("DATABASE_PASSWORD") ?? "vapor_password",
database: Environment.get("DATABASE_NAME") ?? "vapor_database",
tls: .prefer(try .init(configuration: .clientDefault)))
), as: .psql)
app.migrations.add([CreatePost()])
try app.register(collection: PostController())
}
完成添加之后,可以使用 swift run App routes
来打印 App 内生效的 routes
+------+--------+
| GET | / |
+------+--------+
| GET | /posts |
+------+--------+
| POST | /posts |
+------+--------+
测试 PostTests
我们的项目经过了一遍较大的结构改动,但如果逻辑没有错误,我们之前写的 PostTests 应该仍然是可以通过的,换句话说,只要 PostTests 通过了, 我们就无需过于担心功能是否可以正常运行。
运行测试
swift test
测试结果通过
Test Case '-[AppTests.PostTests testCreatePost]' passed (0.230 seconds).
Unit Test 又一次验证了它的必要性。
下章预告
在下一章中,我们将会添加 User 并关联 User 和 Post