Rebuilding LoreScroll: Building A Simple API

The first major task in my attempt to build a better, more efficient and React-based version of my favorite project LoreScroll was to set up my backend. I needed an API to store the Story, Setting and Character data generated by my users that I could later fetch and display using JavaScript and React.

The following is an explanation of my process and not necessarily meant for instructional purposes. That said, feel free to glean whatever you can from it.

Creating My App

I’ve used Ruby On Rails quite a bit and already have the pre-requisites installed. As such, to get started, all I had to do was cd into my LoreScrollV2 directory and run the following code in my terminal to build out the foundation of the app.

I realized after generating my backend that I could have also added the api tag to the end of my code, which would have formatted my app to optimize for API functionality and likely saved me some time. That said, I wanted a bit more control over the process, so this method worked for me in the long run.


Before I jumped into coding, I wanted to give myself access to a few things that I knew would be necessary as I continued to develop LoreScroll.

I entered my Gemfile and made a number of changes:

  • In order to allow for password encryption for my users, I uncommented the bcrypt gem.
  • To assist with making AJAX calls, I added the rack-cors gem.
  • To simplify serializing my data, I added the fast-jsonapi gem.

To complete my configuration, I also added the following middleware code to my cors initializer — changing the origins to my server: localhost:3000.

Modeling and Migrating

With my foundation laid, I began building the base models for my minimum viable product (there will likely be many more before I’m done): User, World, Setting and Character. I did this using the Model generator discussed in my previous post. This provided me with four empty models and four migrations that would allow me to construct my database.

Relationships and Validations

You’ll notice that when I generated my Models and Migrations, I included foreign keys on each of my tables to allow for table relation. That’s because I had already done some legwork before I started coding and determined the logic of my relationships.

  • A User has many Stories and has many Settings. This is relatively self explanatory.
  • A Story belongs to a User and belongs to a Setting. At this point, I’m not allowing for any kind of collaboration, so a Story belongs to a single user. The reason a Story belongs to a Setting — instead of the other way around — is because a setting can be featured in multiple stories. For example, Tatooine appears multiple times throughout the Star Wars saga. Setting will be the overarching object that ultimately includes many more specific types of setting objects.
  • A Setting has many Stories and has many Characters. It belongs to a User. This set up will eventually allow a Character to have many Stories through Setting, though that is a relationship I have yet to develop.
  • A Character belongs to a setting. This is also self explanatory. A character exists in a setting and exists in a story through that setting.

The next step was to include these relationships within my models.

Beyond the relationships, I also included has_secure_password, a feature of bcrypt, in my User model to allow for password encryption. F

Finally, I added some basic validations to prevent any bad data from getting entered into the database — i.e. if I’m displaying a story’s title, I don’t want there to be no information to pull from. In the case of User, a username must be present, it must be unique and it must have a minimum of seven characters. In the case of Story, Setting and Character, they must have an identifying name or title present.

This will all come in handy when creating forms for data entry, which I’ll likely go over in a future blog.


With my basic Models, Migrations and Relationships complete, I was able to migrate my tables (rails db:migrate) and create my ActiveRecord database. The next thing to think about was routing and building controllers to handle any routing actions.

To start, I added my routes paths to the routes.rb file in my config directory. I elected to stick with three simple routes to start for each of my models: index, show and create. While I will eventually add an option to edit and delete content, I want to get the rest of my API up and running first.

I also decided to namespace my routes as an :api, since that is the primary function of this Rails application. This means that when I call a route in my browser it will need to be preceded with ‘/api’: (i.e. https://localhost:3000/api/stories).

Serializing Data

Serializers allow us to create a custom structure for our data, helping us to improve upon the suboptimal default that Rails provides for APIs. For example, we know that each User object is going to have several associated Stories. Serializers give us the ability to access assigned data for those stories directly from the User object, which is much easier way of grabbing that data.

Since I knew I wanted to serialize my data, I elected to create my serializers before my controllers. With the fast-jsonapi gem already installed, I was able to access generators to speed up this process.

There files will appear in the serializers folders within the app directory.

We’ll see how all of this turns out once we’ve got our controller up and running, but the important thing to understand is that relational data is now nested and stored with an object. For example, if we are looking at the json of a Setting object, the Story and Character objects related to that setting will be nested and made available for easy access. This is an incredibly useful tool!

Building Controllers

The last big step in building our API is to create our controllers, which will provide the code necessary to complete the action defined in our routes: index, show and create.

To ensure our namespacing functions correctly, we want to create an api folder within our controllers directory. This is where we’ll place all of our files. We also want to make sure to precede our class names with “Api::” as this will give us access to render json data.

Rather than show you every controller I’ve created, let’s focus on a single one — as the information contained within each is fairly similar when constructing an API.

Let’s break down our controller action methods:

  • Index: This is designed to render all of the stories in our database. We assign Story.all to an instance variable called stories. Then, we render json using our newly created StorySerializer with the method .new and pass in our stories variable.
  • Show: This is designed to render a single instance of a Story object. We find the Story using its id parameter and assign it to an instance variable called story. Then, as with index, we render json using — this time passing in the story variable.
  • Create: This allows us to add a new Story object to our database. Eventually we’ll build a form in React that utilizes this action. First we create a new Story object and pass in our story_params (which we will discuss in a second), assigning what’s return to an instance variable of story. If our story saves successfully, we’ll render json using and pass in the story variable. If it doesn’t save, it will throw an error.
  • Story_Params: Finally, within a private method, we’ll create our strong params — which is necessary to maximize the security of data that we pass through forms, which we know we’ll want to do eventually. Story_Params will include all of the attributes we know we’ll want the user to have access to.

There’s room to expand our controller with edit and destroy actions, but this looks great to start with!

Wrapping It Up

We’re almost done! To test out my API and ensure it was working properly, I seeded the database with some dummy data using “rails db:seed” and ran “rails server” to test out the results.

Let’s see what we’ve got:

There’s our json! Our API is up and running successfully!

We can really see the impact of the serializers when viewing this file. Not only do we have access to all of the Story’s attributes, we also have access to the attributes of the associated User and Setting objects.

Building an API with Ruby On Rails is fairly simple once you’ve got a handle on the process. While it will certainly grow with the rest of LoreScroll as I add features, this is enough to get started on my front end. We’ll discuss that next week!



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store