Using Fluent and Persisting Models in Vapor
The Fluent ORM lets you use any number of database engines in your Vapor app. Learn how to persist your models in your server side Swift apps using Vapor! By Tim Condon.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Using Fluent and Persisting Models in Vapor
15 mins
Running Migrations
Open configure.swift and, after app.databases.use(_:as:)
, add:
// 1
app.migrations.add(CreateAcronym())
// 2
app.logger.logLevel = .debug
// 3
try app.autoMigrate().wait()
Here your new code:
- Adds
CreateAcronym
to the list of migrations to run. - Sets the log level for the app to debug. This provides more information and lets you see your migrations.
- Automatically runs migrations and waits for the result. Fluent lets you choose when to run your migrations. This is helpful when you need to schedule them. You can use
wait()
here since you’re not running on anEventLoop
.
To test with PostgreSQL, you’ll run the Postgres server in a Docker container. Open Terminal and enter:
docker run --name postgres -e POSTGRES_DB=vapor_database \
-e POSTGRES_USER=vapor_username \
-e POSTGRES_PASSWORD=vapor_password \
-p 5432:5432 -d postgres
Here’s what this does:
- Runs a new container named postgres.
- Then specifies the database name, username and password through environment variables.
- Lets apps connect to the Postgres server on its default port: 5432.
- Then runs the server in the background as a daemon.
- Uses the Docker image named postgres for this container. If the image isn’t present on your machine, Docker automatically downloads it.
To check if your database is running, enter the following in Terminal to list all active containers:
docker ps
If you have any questions about Docker, check out this post. It breaks down everything you need to know.
Now you’re ready to run the app! Set the active scheme to TILApp with My Mac as the destination. Build and run. Check the console and see the migrations ran.
You’ll see something similar to this:
Now that you’ve run the migration, you need to save the model.
Saving Models
When your app’s user enters a new acronym, you need a way to save it.
In Vapor 4, Codable
makes this trivial. Vapor provides Content
, a wrapper around Codable
, which lets you convert models and other data between various formats. It’s used extensively in Vapor.
Open Acronym.swift and add the following to the end of the file to make Acronym
conform to Content
:
extension Acronym: Content {}
Since Acronym
already conforms to Codable
via Model
, you don’t have to add anything else. To create an acronym, the client sends a POST request containing a JSON payload that looks similar to this:
{
"short": "OMG",
"long": "Oh My God"
}
You need a route to handle this POST request and save the new acronym. Open routes.swift and at the end of routes(_:)
add:
// 1
app.post("api", "acronyms") { req -> EventLoopFuture<Acronym> in
// 2
let acronym = try req.content.decode(Acronym.self)
// 3
return acronym.save(on: req.db).map {
// 4
acronym
}
}
Here you:
-
Register a new route at /api/acronyms that accepts a POST request and returns
EventLoopFuture
. It returns the acronym once it’s saved. - Decode the request’s JSON into an
Acronym
model usingCodable
. - Save the model using Fluent and the database from
Request
. - Because
save(on:)
returnsEventLoopFuture
usemap
to return the acronym when the save completes.
Fluent and Vapor’s integrated use of Codable
makes this simple. Since Acronym
conforms to Content
, it’s easily converted between JSON and Model
. This lets Vapor return the model as JSON in the response without any effort on your part.
Build and run the app to try it out. A good tool to test this is RESTed, available as a free download from the Mac App Store. Other tools such as Paw and Postman are suitable as well.
In RESTed, configure the request as follows:
- URL: http://localhost:8080/api/acronyms
- method: POST
- Parameter encoding: JSON-encoded
Add two parameters with names and values:
- short: OMG
- long: Oh My God
Setting the parameter encoding to JSON-encoded ensures RESTed sends the data as JSON. It’s important to note this also sets the Content-Type
header to application/json
, which tells Vapor the request contains JSON. If you’re using a different client to send the request, you may need to set this manually.
Click Send Request and you’ll see the acronym provided in the response. The id
field has a value since you now saved it in the database:
Troubleshooting
Some folks get the following error when they run the app:
“[ ERROR ] role "vapor_username" does not exist (InitializeSessionUserId)
You might have this issue if you have PostgreSQL installed on the machine hosting the docker container. To handle this error, stop the PostgreSQL server. For example, if you installed PostgreSQL using Homebrew, type the following into Terminal:
brew services stop postgresql
Then, you can start the docker container and run the app according to the instructions. That should solve the "vapor_username" does not exist’
issue. If it persists, join the chat and discuss the problem there.
Where to Go From Here?
You can download the final project by clicking the Download Materials button at the top and bottom of this page.
In this tutorial you learned how to create models in Vapor and save them to a database. If you enjoyed this tutorial, check out our full-length book on Vapor development: Server Side Swift with Vapor.
If you’re new to web development but have experience with Swift, you’ll find it’s easy to create robust, fully-featured web apps and web APIs with Vapor 4.
Whether you’re looking to create a back end for your iOS app or want to create fully-featured web apps, Vapor is the perfect platform for you.
If you have any questions or comments please join the discussion below.