如果你用 Vapor 写后端,那么你肯定写过下面类似代码。
Todo.swift 文件
import Vapor
import Fluent
final class Todo: Model {
static let schema = "todos"
@ID(key: .id)
var id: UUID?
@Field(key: "name")
var name: String
@Parent(key: "user")
var user: User
init() {}
init(id: UUID? = nil, name: String) {
self.id = id
self.name = name
}
}
User.swift 文件
final class User: Model {
static let schema = "users"
@ID(key: .id)
var id: UUID?
@Field(key: "name")
var name: String
init() {}
init(id: UUID? = nil, name: String) {
self.id = id
self.name = name
}
}
按照官方使用指南,我们还需要写迁移类:
extension CreateTodo: AsyncMigration {
func prepare(on database: Database) async throws {
try await database.schema("todos")
.field("id", .uuid, .identifier(auto: false))
.field("name", .string, .required)
.field("user", .uuid, .required, .references("users", .id, onDelete: .cascade, onUpdate: .cascade))
.create()
}
func revert(on database: Database) async throws {
try await database.schema("todos")
.delete()
}
}
extension CreateUser: AsyncMigration {
func prepare(on database: Database) async throws {
try await database.schema("users")
.field("id", .uuid, .identifier(auto: false))
.field("name", .string, .required)
.create()
}
func revert(on database: Database) async throws {
try await database.schema("users")
.delete()
}
}
写完迁移类后,我们还需要添加迁移:
app.databases.use(.postgres(configuration: .init(
hostname: "localhost",
port: SQLPostgresConfiguration.ianaPortNumber,
username: "vapor",
password: "vapor",
database: "hello",
tls: .disable
)
), as: .psql)
app.migrations.add(CreateUser())
app.migrations.add(CreateTodo())
try await app.autoMigrate()
完成这些后才会在数据库中生成对应的表:
如果项目简单,写迁移类的所花的时间还可以接受,但是如果是这样:
工作量就不是一般的大了,而且写多了,你会觉得写这些代码没有任何营养,它就是个体力活,为什么这么说?
@Field(key: "name")
var name: String
从这块代码,我们就可以知道这个属性信息,完全能够通过这些信息自动去生成迁移类,flask-migrate 就是这么做的,开发效率非常高效,那么有没有针对 Vapor 的类似工具呢?
AutoMigrator
国外小哥应该也意识到了这点,开发了这个库。原理也非常简单:
- 获取到数据库中表信息
- 通过类型反射获取到属性信息
- 对比差异,生成迁移文件
实现细节可以阅读源码。
使用
添加依赖
.package(url: "https://github.com/swiftdo/AutoMigrator.git", from: "0.2.0")
MatsMoll/AutoMigrator 还有些小bug,个人进行了修复,所以引用了自己的源
然后在 testTarget 添加:
在 AppTests 上添加
然后直接运行单元测试,运行完成后:
然后迁移代码:
app.migrations.add(MigrationBatch1.users())
app.migrations.add(MigrationBatch1.todos())
完工,以后每修改模型,跑一下testHelloWorld测试用例,就会自动将修改生成到 Migrations 目录下,然后我们将手动调用下新增的迁移类就行。
Swift 爱好者,不妨关注的微信公众号:OldBirds,可入Swift微信群。