Database Persistence with Fluent and Postgres in Vapor
Adding persistence to your Vapor-based REST API is crucial for ensuring that your data is saved even after server restarts. This guide shows how to integrate Fluent and PostgreSQL into your Vapor project to persist tasks in a database.
Details
URL: 🔗 https://vapor.codes
Source: 🔗 Book: Server-Side Swift
Author: [Author Name]
Tags:
Fluent
, Vapor
, Postgres
, Swift
, Database Persistence
Platforms Supported: macOS, Linux
Swift Version: 5.x
Setting Up Database Persistence​
Step 1: Create a Migration for Tasks​
In the Migrations
folder, create CreateTasks.swift
:
import Fluent
struct CreateTask: Migration {
func prepare(on database: Database) -> EventLoopFuture<Void> {
database.schema("task")
.id()
.field("description", .string, .required)
.field("category", .string, .required)
.create()
}
func revert(on database: Database) -> EventLoopFuture<Void> {
database.schema("task").delete()
}
}
Step 2: Register the Migration​
Add the migration in configure.swift
:
import Vapor
import Fluent
public func configure(_ app: Application) throws {
app.migrations.add(CreateTask())
try app.autoMigrate().wait()
}
This will create the database schema when the server starts.
Step 3: Update the Task Model​
Modify Task.swift
to conform to Model
for database persistence:
import Fluent
import Vapor
final class Task: Model, Content {
static let schema = "task"
@ID(key: .id)
var id: UUID?
@Field(key: "description")
var description: String
@Field(key: "category")
var category: String
init() { }
init(id: UUID? = nil, description: String, category: String) {
self.id = id
self.description = description
self.category = category
}
}
Step 4: Update the TaskController​
Modify TaskControllerAPI
to save tasks to the database:
import Vapor
import Fluent
final class TaskControllerAPI {
func index(req: Request) throws -> EventLoopFuture<[Task]> {
Task.query(on: req.db).all()
}
func create(req: Request) throws -> EventLoopFuture<Task> {
let task = try req.content.decode(Task.self)
return task.save(on: req.db).map { task }
}
func delete(req: Request) throws -> EventLoopFuture<HTTPStatus> {
Task.find(req.parameters.get("taskID"), on: req.db)
.unwrap(or: Abort(.notFound))
.flatMap { $0.delete(on: req.db) }
.transform(to: .ok)
}
}
extension TaskControllerAPI: RouteCollection {
func boot(routes: RoutesBuilder) throws {
let tasks = routes.grouped("tasks")
tasks.get(use: index)
tasks.post(use: create)
tasks.group(":taskID") { task in
task.delete(use: delete)
}
}
}
Step 5: Setup Postgres with Docker​
Run PostgreSQL in a Docker container:
docker run --name postgres -e POSTGRES_DB=vapor_database \
-e POSTGRES_USER=vapor_username \
-e POSTGRES_PASSWORD=vapor_password \
-p 5432:5432 -d postgres
This matches the configuration in configure.swift
.
Step 6: Test the API​
Run the server and use cURL to test:
- Create a Task:
curl -H "Content-Type: application/json" -X POST -d '{"description":"Buy milk","category":"Shopping"}' http://127.0.0.1:8080/tasks
- Retrieve Tasks:
curl http://127.0.0.1:8080/tasks
Conclusion​
With these steps, your Vapor-based REST API now persists data in a PostgreSQL database, ensuring that your tasks are saved even after server restarts.
Related Snippets​
ddddd