I have been using Rails for a while now, and I love every bit of it, Rails is considered an end to end framework, what does that mean? well, It means that you can use it to build the server side of your application (back-end) and the client side (front-end) as well.
But we live in times where as much as we want to simplify tasks, as a developer you might be asked to build your back-end using rails because it’s awesome! and the client side might be done using a different framework such as Angular Js, and in order to connect one with the other, you are going to need end points.
End Points
An end point is simply a unique URL that represents an object or a collection of objects, where you simplify client access to data from other applications.
Let’s say you ask facebook to let you use all their users data for some app you are building (good luck with that!), imagine the process of typing that manually, or if they send you an email with a database file in god knows what format, but lets say you manage to parse and use that data, what happens when this data gets updated? as data constantly does, would you like to keep requesting for data update emails on every single data change?… if your answer was “Hell no!!” (as it should be), then you are going to love API end points, they allow you to access real-time data in a serialized format called JSON.
What is JSON?
JSON is short for JavaScript Object Notation, and is a way to store information in an organized, easy-to-access manner. In a nutshell, it gives us a human-readable collection of data
that we can access in a really logical manner.
This is to say, that if you have a ruby User object with some attributes, you can extract that data in JSON format so it can be used by other frameworks, like so:
#Ruby
jason = User.new
jason.name = "Jason"
jason.last_name = "Voorhees"
jason.dob = "June 13, 1946"
jason.status = "Open to a relationship"
jason.favorite_day = "Friday"
jason.favorite_number = 13
#Ruby Object
<User:0x007fd6e30152b8 @name="Jason", @last_name="Voorhees",
@dob="June 13, 1946", @status="Open to a relationship",
@favorite_day="Friday", @favorite_number=13>
Turned into JSON:
const jason = {
"name" : "Jason",
"last_name" : "Voorhees",
"dob" : "June 13, 1946",
"status" : "Open to a relationship",
"favorite_day" : "Friday",
"favorite_number" : "13"
}
Neat right? now the data is formatted to be used by a front-end framework or to respond to AJAX calls, you name it, but how do we get ruby data formatted into beautiful JSON? That’s where Active Model Serializers come in.
Active Model JSON Serializer (AMS)
Provides a basic serialization to a serializable_hash for your objects, it returns a hash representing the model. – Rails API
Meaning, it takes ruby objects and turns them into JSON, but how?
Let’s say we are building a blog app with posts and authors, and a post has a title, and a description, while an author has a name.
class Post < ApplicationRecord
belongs_to :author
end
class Author < ApplicationRecord
has_many :posts
end
# Create Author
stephen = Author.new
stephen.name = "Stephen King"
stephen.save # stephen.id = 1
# Create Post post = Post.new post.title = "A Blog Post By Stephen King" post.description = "This is a blog post by Stephen King. It will probably be a movie soon." post.author = stephen post.save # post.id = 1
First, we need to add the gem to our Gemfile:
# Gemfile
#...
gem 'active_model_serializers'
Run bundle install
to activate the gem.
Create an app/serializers directory:
mkdir serializers
├── Gemfile
├── Gemfile.lock
├── Rakefile
├── app
│ ├── serializers
│
Now we need to generate an ActiveModel::Serializer
for our Post
. Thankfully, the gem provides a generator for that. Drop into your console and run:
rails g serializer post
If we look at the generated post_serializer.rb
, inside the serializers directory, it should look something like this:
class PostSerializer < ActiveModel::Serializer
attributes :id
end
We want to get some more information out of it, so let’s add a couple attributes.
class PostSerializer < ActiveModel::Serializer
attributes :id, :title, :description
end
To make use of our new serializer, we need to let our controller know that it can use it.
# posts_controller.rb
def show
@post = Post.find(params[:id])
respond_to do |format|
format.html { render :show } # Render post in HTML format
format.json { render json: @post} # Render post in JSON format
end
end
But wait? what is that format.json { render json: @post }
madness? well, here we are simply creating an end point, meaning that now you can visit two URL’s, one will render your good old HTML (www.myapp.com/post/1), and another the will render a JSON formatted object (www.myapp.com/post/1.json), calling render json: @post
would implicitly use the new ActiveModel::Serializer
to render the post to JSON.
Let’s see it in action. Restart your Rails server and browse to /posts/1.json
and look at the results. It should look like this:
{
post: {
id: 1,
title: "A Blog Post By Stephen King",
description: "This is a blog post by Stephen King. It will probably be a movie soon."
}
}
Worked like a charm!
Pro-Tip: You can use JSONView chrome app to render JSON in your browser window in a much nicer way.
What’s missing ? The author name. So how do we do that?
We need to create a new AuthorSerializer
.
rails g serializer author
And add the author name to the list of attributes:
class AuthorSerializer < ActiveModel::Serializer
attributes :id, :name
end
Now to test this out, let’s modify our authors_controller#show
action to handle a JSON request:
class AuthorsController < ApplicationController
def show
@author = Author.find(params[:id])
respond_to do |f|
f.html { render :show }
f.json { render json: @author }
end
end
end
And load up /authors/1
.json
.
We should see something that looks like this:
{
author: {
id: 1,
name: "Stephen King"
}
}
But how to add the author name to our post JSON?
We add a has_one :author
to our PostSerializer
:
class PostSerializer < ActiveModel::Serializer
attributes :id, :title, :description
has_one :author
end
Top-tip: You might notice that we’re using
has_one
in our serializer, when in the model, the post -> author relationship is actually abelongs_to
. This can be confusing at first, but AMS is only concerned with the number of the relationship, not the direction. So it only knowshas_one
andhas_many
. This is because it’s not describing a data/model relationship, but the relationship as defined by the JSON.
Reload /posts/1.json
we will now see our author information.
{
post: {
id: 1,
title: "A Blog Post By Stephen King",
description: "This is a blog post by Stephen King. It will probably be a movie soon.",
author: {
id: 1,
name: "Stephen King"
}
}
}
Now we have all our post information formatted to JSON, meaning our data can be accessed now by your favorite front-end framework.
Yay we did it!
Resources
Flatiron School Online Learn Program
JSON: What It Is, How It Works, & How to Use It
- Installing phpcs on a Mac ft. VSCode & WordPress, The Really Simple Guide - May 8, 2021
- How To Set Up Your WordPress Development Environment with a Large Database ft. MAMP & Mac, The Really Simple Guide - April 24, 2020
- Next.js ▲ + Typescript + Storybook The Really Simple Guide 2019 - November 25, 2019