Using PostgreSQL With Vapor 2
Persistence of data is one of the most important features of many web applications. My Goal in this article is to show you how to connect your Vapor application to a PostgreSQL database.
First, make sure you have the Vapor Toolbox installed. Then generate a project. I passed in the --web
flag for mine, but you won’t need that for this tutorial.
Before we get any further, we should install Postgres on our machine. I recommend using Homebrew. Run brew install postgres
. Once Postgres is installed, you can run postgres -D /usr/local/var/postgres
to boot up the database. You will have to close the current terminal window and open a new one when this command stops giving output.
Back at the project, we want to include the PostgreSQL Provider package into our project. You can copy and paste this line into your Package.swift
:
Then, run vapor update
and vapor xcode
(if you are using Xcode).
We will now create a model that we can store in the database. Create a new file at the path Sources/App/Models/
named User.swift
:
And regenerate your Xcode project.
Next, import the PostgreSQL Provider module and create a class User
that conforms to the Model
protocol:
Our user will have a username, email, and password, so we will need to add these properties and an initializer to the class:
Note that I am not hashing the password. Don’t do this in real life! I will cover that in a future article on authentication.
Next, we will add the proper methods and properties to the User
class to conform to Model
. We will start by adding the storage
property:
This allows Fluent to store extra information on the model, such as its database ID.
After adding the storage
property, we create a new initializer that takes in an instance of type Row
and gets the needed information from it for the model’s properties:
We also need to be able to serialize the model into a row, so we will implement the makeRow()
method. The Swift conventions say that you should put protocol conformance in an extension of the class. You can’t do this with initializers and instance properties, but you can do this with methods, so we will put the makeRow()
method in an extension of User
that conforms to RowRepresentable
:
The last protocol we need to conform to is Preparation
. This allows us to create and delete the table in the database. Preparation
has us implement two static functions, prepare
and revert
. Here is what the implementation looks like:
Now our User
model is ready to run! But we can’t use it until we do a couple more things. First, we need to add the User
model to the Config
.
Go to App/Config+Setup.swift
and import the PostgreSQL Provider:
Next, add the provider to the Config
in the setupProviders
method:
Lastly, we will create a new method called addPreparations
and add User
to the Config
there:
And call addPreparations
in setup()
:
Second, we need to add the JSON config files for both Fluent and the PostgreSQL Provider.
Create a file at Config/fluent.json
, then add the driver key:
Then create Config/secrets/postgresql.json
(you need to create the secrets folder) and add the configuration keys:
The value of the user
and database
keys is the result of running whoami
in the terminal.
Now that everything is setup, let’s tryout our new User
model!
Go to App/Routes.swift
and create a post
route in Routes.build()
. It will need to get a username, password, and email from the request and create an instance of User
with those values. We will then save the new instance of User
and then return a string with the users data along with its database ID:
Before we run, create a new database by running createdb `whoami`
.
Now build and run you project. I will be testing the route with Postman, but any other REST API app will work.
Set the URL to localhost:8080/user/new
and the HTTP method to POST
. Then add a password
, username
, and email
key for form data and send the request. You should get an output that looks something like this:
Congrats! You just implemented PostgreSQL in your web app!
If you want to mess around with this a bit more, you can find the project here on GitHub.