Vapor には Command というモジュールがあり、これを利用すると CLI のコマンドを作ることができる (ややこしいことに、これを使いたい場合は vapor/console を依存関係に追加する必要がある) 。
だが、その中でデータベースにアクセスしようとして困った。
やろうとしたことは、
- コマンドを実行してユーザーを作りたい
というもので、当然データベースにデータを INSERT
する必要がある。
CLI を作る場合、Command
プロトコルに準拠した型を用意し、その run
メソッドに処理を実装するのだが、その際に利用できる CommandContext
というコンテナは DatabaseConnectable
を満たさないのだ。
argument type 'Container' does not conform to expected type 'DatabaseConnectable'
で、質問して教えてもらった方法が、ここ にあるように、Conitainer
には withNewConnection
という拡張メソッドがあり、それを使うとクロージャに Database.Connection
が渡るのでデータベースにアクセスすることができる。
例えばやりたかったことは↓で実現可能。
...
func run(using context: CommandContext) throws -> Future<Void> {
let email = try context.argument("email")
let password = try context.requireOption("password")
let passwordHash = try BCrypt.hash(password)
let user = User(email: email, password: passwordHash)
return context.container.withNewConnection(to: .psql) { db in
return user.save(on: db).transform(to: ())
}
}
...
ちなみに newConnection
というメソッドもあるが、こちらは自分でコネクションを閉じる必要があるため、普通は withNewConnection
を使ったほうが良いと思う。