If you’ve used Ruby on Rails for any decent amount of time, chances are that you’re pretty comfortable working within the Model-View-Controller architectural pattern, but may be feeling the constraints of using ERB templates for your views. While ERB serves the purpose of templating the front-end of a basic web app just fine, writing entirely in embedded Ruby can still feel cumbersome and confusing at times, especially as your app grows.
At this point is when you will likely reach for a more robust and streamlined front-end framework like React, Angular, or Vue, which will bring some much appreciated modularity to the V in your MVC app (hello reusable components!). In this article, I’ll walk you through setting up your Ruby on Rails back-end as a RESTful JSON API, which you can then use to power your app’s new-and-improved front-end.
First things first, to spin up a new Rails API you’ll turn to your old friend, the ‘rails new’ command! But since you want to create a Rails app in API mode, you’ll use a slight variation of the classic command, seen below:
rails new my_app --api
Per the Rails documentation, running this command will do generate the base of your app, minus the stuff you don’t need when you aren’t utilizing views (more minimal middleware, no views/helpers/assets generated when creating a resource). And as with the non-API ‘rails new’ command, you can always add certain flags to control what exactly is auto-generated for you, which can help keep unnecessary files to a minimum. For example, I’m a big fan of skipping the auto-generated test files like so:
rails new my_app --api -T
Now that the foundation for your Rails API has been laid, it’s time to run a few more generators to create your models, controllers, routes, and database migrations. Luckily, Rails has another extremely convenient console command to do most of the ground work for you! Let’s say your app will have a User model with a username and secure password, and you’re ready to begin implementation. The following command takes care of the aforementioned steps:
rails g scaffold Users username:string password_digest:string
Because we’re running Rails in API mode, you’ll notice that using the scaffold generator does not create views for this resource. This is because our back-end will solely be serving up JSON data and not rendering any HTML/ERB. If you take a look in the controller that has been generated for you, you’ll see that the render calls in each action look a bit different:
render json: @collections
As I’m sure you guessed, including the ‘json:’ argument here will render… JSON! Don’t you just love declarative programming?
At this point, once you create your database, run your migrations, and add any other resources your app will need, your API is pretty much good to go. But let’s take it one step further and serialize our JSON data so that with each call to the API, we’re only sending exactly the data needed to fulfill that request and nothing more.
First, you’ll want to add the following to your Gemfile:
Make sure to run the ‘bundle’ command to install this new dependency.
Now, you can use another ‘rails g’ command to generate a serializer for your JSON data. Let’s generate one for our User resource.
rails g serializer User
Once this command is run, you’ll notice a new ‘Serializers’ directory located in your APIs app folder. In the UserSerializer.rb file that was created, you can then specify what model attributes or associations you want to be included in your JSON data.
If you just want to return the User’s ID and username, for instance, your UserSerializer would look like this:
class UserSerializer < ActiveModel::Serializer attributes :id, :usernameend
For a slightly more complex example, let’s say you have some model associations established. Imagine our app allows users to create collections of GIFs, with a collection having many GIFs and a collection belonging to a user. In this case, you’ll need to specify the association in order to return nested JSON data, like so:
class CollectionSerializer < ActiveModel::Serializer attributes :id, :name has_many :gifs belongs_to :userend
Doing so will return beautifully nested JSON that includes the attributes specified by your serializers, allowing you to access data from associated resources more easily and efficiently.
There’s a lot more to discover when it comes to using a Rails API, so consider this article just the tip of the iceberg. But by following this guide, you’ll be able to spin up a well-designed RESTful API in mere minutes!