Late Night Confessions — Building a Website Using Rust, Rocket, Diesel, and Askama — Part 2
By: Johnny Tordgeman
Tags: Rust, Rustlang, Diesel, Tutorial, Software Engineering

Late Night Confessions — Building a Website Using Rust, Rocket, Diesel, and Askama — Part 2 Johnny Tordgeman Follow Apr 22 · 10 min read

Photo by David Watkis on Unsplash

This is part 2 in a three-part series. Read part 1 here.

We previously left off with our server able to handle static content, but that is about all. In order to store and retrieve confessions, our app needs to interact with a database. That’s where Diesel comes to our aid!

⚠️ In order for Diesel to interact with a database, a database instance needs to already exist. Make sure you have access to a Postgres instance (local or cloud based, both work) before moving forward.

Housekeeping

1. We begin with installing diesel_cli - a tool that helps us manage the database. As we only use Diesel for Postgres, we use the features flag to specify that:

cargo install diesel_cli --no-default-features --features postgres

2. In the root folder of the project, create a .env file. At the top of the file add the DATABASE_URL property that Diesel will use to get the connection details of your Postgres instance.

3. In the project root folder run diesel setup . Diesel will create a new database (confessions), as well as a set of empty migrations.

A new database and migrations

Using Migrations

With the database setup, it’s time to create the confessions table. Diesel uses a concept called migrations to track changes done to a database schema. You can think of migrations as a list of actions that you either apply to the database (up.sql) or revert (down.sql).

Generate a new migration set for the confessions table by running the following command at the root of the project:

diesel migration generate confessions_table

This creates a new folder inside of the migrations folder that holds the new migration set (up/down.sql) for the confessions table:

2. To create the new table, cd to the new migration folder and add the following to the up.sql file:

3. In down.sql we specify how to revert the migration (i.e., dropping the confessions table):

4. Apply the new migration by running the following command:

diesel migration run

💡To revert the last migration run diesel migration redo .

5. cd to the src folder to find a new file called schema.rs. This file contains the table definition created by Diesel that enables us to work with the database in a typesafe way.

With the housekeeping behind us, we proceed to establish a connection between our Rocket instance and Diesel.

Getting Connected

The first rule of working with a database is connecting to a database. A common method of connection between a database and an application is Connection Pool — a data structure that maintains active database connections (pool of connections) which the application can use at any point of time it needs.

Rocket, with its rocket_contrib crate (a crate that adds functionality commonly used by Rocket applications), allows us to easily set up a connection pool to our database using an ORM of our choice. In our case, that’s going to be Diesel.

We begin with adding three dependencies to our cargo.toml file: diesel, serde, and rocket_contrib:

🔭 As we only need certain features from the above crates, we specify these features using the features property. In our case we only need Postgres support so we specify that in the features list for diesel and rocket_contrib.

2. Add the following import statements to your main.rs file:

3. Next, we configure the connection settings for our database. Create a new file named Rocket.toml in the root folder of the project with the following content:

At this point you are probably thinking to yourself: “Johnny WTF? this is exactly the same connection string we configured earlier in the .env file. Can’t we just use that environmental variable and be done with it?”

it really is!

Of course you can! But I’ll touch on how to do that a little bit later. For now, let’s roll with Rocket.toml.

4. Open your main.rs file and add a new unit-like struct called DBPool :

The database attribute is used to bind a previously configured database to a poolable type in our application.The database attribute accepts the name of the database to bind as a single string parameter. This must match a database key configured in Rocket.toml. The macro will generate all the code needed on the decorated type to enable us to retrieve a connection from the database pool later on, or fail with an error.

5. Lastly we need to attach the database to our Rocket instance. We do that using the attach method of our Rocket instance. The attach method takes a fairing (think of that like a middleware) and attaches it to the request flow.