Rails building json API responses with JBuilder
Rails is a MVC web application framework which supports building complex websites without writing any APIs. But, client side libraries are evolving at brisk pace with wide-spread use of React JS, AngularJS, VuJS etc. Thus, building API endpoints is a very important tasks these days.
Rails has been pretty adoptive when it comes to supporting what community is up to. Rails started supporting API only application from Rails 5. There are quite a few options to build json response in Rails application. Listing down a couple of widely used gems to build them.
Both of them have their pros and cons to consider. In this article, we will just consider building json API response with jbuilder.
JBuilder
Jbuilder is quite useful when it comes to generating and rendering JSON responses for API requests in Rails. This article helps understand, how to render JSON responses in general. Jbuilder is particularly good at following things:
- Reusable JSON API responses through partials
- View helpers available when generating API responses
- Convention over configuration principle in action
We will also take a look at rendering json reopnses from controller with JBuilder. Then, reusing same JSON reponse in jbuilder view file and models.
Rails API only application
Rails API only application is a slimmed down version of Rails application. It does not contain gems that are usually required for front-end specific implementation. For e.g. coffee rails, turbolinks etc.
Ruby / Rails Versions
Versions used in building this application are listed below.
- Ruby: 2.5.3
- Rails: 5.2.1
1. Create Rails API only application
Let us create an API only Rails application with the help of command given below.
rails new build-api-with-jbuilder --api
-
--api
option takes care of setting up Rails application to beapi
only application. -
This command also performs bundle install to resolve dependencies and install them in order to run the application.
2. Add jbuilder gem
Rails API only app that is generated in Step 1, has following lines in commented format as given below.
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
# gem 'jbuilder', '~> 2.5'
In order to use jbuilder to build/format json, we need to uncomment those two lines or add
gem 'jbuilder', '~> 2.5'
to Gemfile.
Bundle install to install the gem.
3. Create Data Model
In order to demonstrat how to build APIs with API only Rails application, let us create a few tables and insert data into them.
rails g model Category name:string
rails g model Source name:string
rails g model Article title:string url:string source:belongs_to category:belongs_to
Once, we run generators to create migrations and models, let’s run these migrations.
rails db:migrate
4. Insert data
We will use faker to quickly add some dummy data to the data model that we created in Step 3.
Add gem faker to Gemfile.
# Gemfile
gem 'faker', '~> 1.9.1', group: [:development, :test]
We will just use faker gem to generate some fake data in development and test environments. Then, perform
bundle install
to install faker gem and to use it with our application.
We will add fake data using seeds.rb
# seeds.rb
# Create Categories
10.times { Category.create!(name: Faker::Lorem.word) }
# Create sources
10.times { Source.create!(name: Faker::Company.name) }
# Create Articles
50.times {
category = Category.all.sample
source = Source.all.sample
Article.create!(
title: Faker::Lorem.sentence,
url: Faker::Internet.url,
category: category,
source: source
)
}
Run database seed data generation with the command given below.
rails db:seed
Render JSON responses with JBuilder
Now that we have Rails API only application ready with jbuilder and some data in place, we can use jbuilder to repond with json to API requests.
Render array in API response with JBuilder
Let’s say we want a list of categories in an API request.
Step 1. Create categories controller.
rails g controller categories
Step 2. Setup route for API endpoint
# config/routes.rb
resources :categories
This step will setup RESTful routes for categories resource.
Step 3. Create controller action
# app/controllers/categories_controller.rb
class CategoriesController < ApplicationController
def index
@categories = Category.all
end
end
Step 4. Create index.json.jbuilder file in category views
Create a directory categories
if it does not exist.
Run the command given below from project root.
mkdir -p app/views/categories
Create a file index.json.jbuilder in app/views/categories directory.
# app/views/categories/index.json.jbuilder
json.array! @categories do |category|
json.id category.id
json.name category.name
json.created_at category.created_at
end
Step 5. JSON response from jbuilder
To verify the response.
- Start the rails server.
rails s
- Request to categories API endpoints
curl -X GET http://localhost:3000/categories.json
JSON response will be something like,
[
{"id":11,"name":"perspiciatis","created_at":"2018-11-10T12:17:21.678Z"},
{"id":12,"name":"fugit","created_at":"2018-11-10T12:17:21.683Z"}
]
Obviously, the above listed json is a trimmed down version of the original response.
Rendering Partials in API response with JBuilder
We can use partials to render json response which is required in multiple APIs.
Let’s say, we want a list of articles in an API endpoints.
Step 1 Create ArticlesController
Create ArticlesController with the help of Rails generator with command given below.
rails g controller articles
Step 2: Setup Routes for articles resource
Setup routes for *Article resource with the help of command given below.
# config/routes.rb
resources :articles
Step 3. Create controller action
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def index
@articles= Article.all
end
end
Step 4. Create index.json.jbuilder file in articles views
Create a directory articles if it does not exist . Run the command given below from project root.
mkdir -p app/views/articles
Create a file index.json.jbuilder in app/views/articles directory.
# app/views/articles/index.json.jbuilder
json.array! @articles do |article|
json.id article.id
json.title article.title
json.url article.url
json.created_at article.created_at
end
Step 5. JSON response from jbuilder
To verify the response.
- Start the rails server.
rails s
- Request to categories API endpoints
curl -X GET http://localhost:3000/articles.json
JSON response will be something like,
[
{
"id": 1,
"title": "Sint maxime et unde.",
"url": "http://mante.io/travis_klocko",
"created_at": "2018-11-10T12:21:20.376Z"
},
{
"id": 2,
"title": "Soluta est beatae cum.",
"url": "http://blick.biz/alexis",
"created_at": "2018-11-10T12:21:20.381Z"
}
]
Note: The response given above is limited to 2 articles.
Next, let us add a category for each article in json with partial in Jbuilder
Step 6 Create partials jbuilder for category
Create a partial view file in app/views/categories directory, by name _category.json.jbuilder
# app/views/categories/_category.json.jbuilder
json.id category.id
json.name category.name
json.created_at category.created_at
Step 7 Render partial in Article json jbuilder file
We can call partial in jbuilder to generate json as given below.
json.array! @articles do |article|
json.id article.id
json.title article.title
json.url article.url
json.category do
json.partial! 'categories/category', category: article.category
end
json.created_at article.created_at
end
This will render category for each article, when articles.json is called.
curl -X http://localhost:3000/articles.json
Response:
[
{
"id": 1,
"title": "Sint maxime et unde.",
"url": "http://mante.io/travis_klocko",
"category": {
"id": 13,
"name": "ut",
"created_at": "2018-11-10T12:17:21.685Z"
},
"created_at": "2018-11-10T12:21:20.376Z"
},
{
"id": 2,
"title": "Soluta est beatae cum.",
"url": "http://blick.biz/alexis",
"category": {
"id": 20,
"name": "animi",
"created_at": "2018-11-10T12:17:21.700Z"
},
"created_at": "2018-11-10T12:21:20.381Z"
}
]
Note: Response is limited to 2 results.
As we can see, each article node in the json response contains category node with details of the category. This gets rendered by the jbuilder partial which was generated for category.
Feel free to comment down with your thoughts. Thanks for reading!
References:
Subscribe to Ruby in Rails
Get the latest posts delivered right to your inbox
