Getting Started with RethinkDB and the Phoenix Framework — Building an App
This is the second post in my Getting Started with RethinkDB and the Phoenix Framework series. If you missed the first post you can find it here. That said, you don’t necessarily need to go back and read it. It is a simple introduction post and demonstrates how to connect to RethinkDB from Elixir. If you start here you will be just fine.
In this post I will create a new Phoenix application and set it up to use RethinkDB. In a follow up post we will use RethinkDB Changefeeds and Phoenix Channels to make our app realtime.
Install RethinkDB and Create a Database
The first thing you need to do is install RethinkDB on your machine. You can do that here. If you are running Windows then you will not be able to install RethinkDB unfortunately. It only works on Unix based machines at the moment.
Once you have RethinkDB installed, you will need to start the RethinkDB server. This can be done by either running the launch commands provided by Homebrew (if you installed on a mac) or by running the rethinkdb command in a terminal window. After you run the command open your browser to http://localhost:8080 and you should see this screen:
Congratulations, you now have RethinkDB installed and working! Let’s setup a database and table to get us started. Navigate to the Tables page by clicking on the link at the top of the RethinkDB admin panel. Click the “Add Database” button and add a database called “rethink_example”.
Our next step is to add a table to the “rethink_example” database. Click the “Add Table” button and add a table called “posts”.
You can create databases and tables programmatically, but the RethinkDB admin interface is so nice that I just like to do it there.
Create a New Phoenix App
Our next step is to create a Phoenix application that will connect to our new RethinkDB database:
mix phoenix.new rethink_example
Note: I’m not running this command with the — no-ecto flag because we are actually going to use Ecto for model validation and changesets. Peter Hamilton, the author of the Elixir RethinkDB package, has written a RethinkDB Ecto shim (not a full adapter) that allows us to use some of the features of Ecto (Please note that the RethinkDB Ecto shim is very new and is likely to change in the coming weeks/months).
Don’t worry about running the mix ecto.create command that the prompt instructs you to run. We just need to move into our new app directory and run the server:
If your app compiles and starts up at http://localhost:4000 you’ll know that everything is working.
Let’s now add the dependencies that we’ll need to hook RethinkDB up to our app. We will need both the RethinkDB package and the RethinkDB Ecto package before we can continue. Shut down your server, open up your mix.exs file, and add the new dependencies:
Next, run the mix deps.get command to load the packages into your app. Great! We now have everything we need.
Adding a Post Resource
Our app is going to be a simple blog app so our first step is to add a post resource. Fortunately, the Phoenix generators make this very simple:
mix phoenix.gen.html Post posts title:string content:text
Just a side note — I went from Rails to Meteor and oh how I missed the code generators. Writing boilerplate code is terrible! Yay for Phoenix!
Once the generator finishes it will provide instructions that tell us to run a migration. You don’t need to worry about that (unless you also want a Postgres database) because we will not be using Ecto migrations. All you need to do is add the post resource to your router file:
Now, if you start your server back up and navigate to http://localhost:4000/posts you should find a beautiful new… error. Bummer.
Your app should be complaining that it can’t find a postgres database (because we didn’t run mix ecto.create ). We can fix this by setting up RethinkDB!
Adding a Default Connection
Turn off your server and create a new file at lib/rethink_example/database.ex . We need to create a new database module and then pull in the RethinkDB macros:
This module will serve as a default connection to our RethinkDB database. Using a default connection is the best way to use the RethinkDB package. It allows you to run database queries without passing a connection to the query functions and provides you with an easy way to supervise the connection.
Now that we have our database module, let’s add it to the supervision tree. Open your lib/rethink_example.ex file and add the module to your tree:
Note: I’ve commented out the worker(RethinkExample.Repo,) line because we aren’t using the default Postgres connection and don’t need it.
As you can see, we pass a few options to our database connection. The most important option is the :db option. By default, RethinkDB automatically connects to a “test” database if it exists. In order to specify a different database we have to pass it the name of the database. This is not to be confused with the :name option which specifies a name for the process that contains the default connection. You can find other options here.
At this point we have added all the necessary boilerplate for working with RethinkDB in our application code. Pretty simple huh?
Converting the Controller Code
Our next step is to convert all the “Repo” code in the post controller to RethinkDB code. Because of the wonderful RethinkDB Ecto shim, this pretty much amounts to changing the word “Repo” to the name of your default connection module.
In order to make working with the connection module easier, let’s add an alias so we don’t have to write it out every time we use it. Add this alias at the top of the post controller:
Now we can go through each of the controller actions and replace “Repo” with “DB”. Here is what the index action looks like:
The new action doesn’t require any changes.
The create action:
The show action:
In addition to replacing “Repo,” I’ve also removed the exclamation mark (or “bang”) from the end of the get function. The RethinkDB Ecto shim only supports the regular versions of these Ecto query functions.
The edit action:
The update action:
And finally, the delete action:
You should now have a fully functional Post resource backed by RethinkDB. Fire up your server and go to http://localhost:4000/posts . Add a new post, go to the show page, edit the post, delete it, and bask in the glory of RethinkDB.
As I mentioned earlier, you can use Ecto.Schema and Ecto.Changeset to validate and constrain your model. For instance, let’s say we wanted to add an arbitrary (and silly) constraint on the :title field of our post model that prevents it from being longer than 10 characters. Because we can still use Ecto.Changeset with RethinkDB we would simply add a validate_length function to our changeset:
You can find the rest of the Ecto.Changeset functions here.
Ecto.Schema defines a struct that represents a model. If you want to add more fields to your Post model you would simply add them to your schema. This is an example of adding a user to our Post model:
We’ve added the user field to bother the schema and required fields. Now, if you go to use the post insert form it will fail. You’ll need to add a new form field before it will work:
The RethinkDB Ecto shim provides you with basic functions for dealing with the database but sometimes you may need to make more complex queries. This is where the RethinkDB.Query module comes in. If you import the query module you will have access to all of the native RethinkDB query functions. You can simply compose a query and then pass it to your connection. Here is an example from the docs:
The RethinkDB.Query module allows you to make beautiful and functional queries. If you are unfamiliar with RethinkDB functions, spend some time in the RethinkDB admin Data Explorer. It’s got excellent code completion that will allow you to see what options are available to you. Here is a screenshot of the data explorer:
This post went through the process of setting up RethinkDB in a Phoenix application and we converted the default generator controller code to work with our RethinkDB database. I also covered a few ways in which you could further use Ecto with RethinkDB.
I hope this post was helpful! Please let me know if you have any questions in the comments section and I’d be happy to help where I can.
Also, you can find the code to the app we built here.
Originally published at ryanswapp.com on January 2, 2016.