Active Model Serializers(AMS) let you customize and create custom object-oriented JSON output of Rails API responses. This way, you can define the serialization for the attribute of your model and take control over the data and include nested data from associated models. AMS uses adapters and intermediaries to convert the data into JSON format and improve API performance by making a single request to the backend.
The Active Model Serializer consists of two major components: Serializer and Adapters. Serializer describes which attributes should be serialized so that the relationship can be defined in the backend and can be translated for the frontend. Adapters define how objects, including their attributes and relationships, are converted into a format suitable for storage or transmission. Additionally, by selectively including required attributes or data, you can improve API performance.
In this blog, we are going to demonstrate the implementation of AMS in an organized way.
Implement Active Model Serializer with Rails API
An API should be well-structured and have clear endpoints and resource naming conventions to ensure usability. And implementation of serialization in Rails APIs notably improved performance for JSON responses. Rails already supports JSON rendering, but AMS allows you to customize the output, enabling more efficient and flexible responses with a single backend request. This customization allows you to define data, reduce redundancy, and even handle complex nested relationships cleanly. This customization allows each resource to be represented as a class inherited from AMS.
Let’s get started with the Movies and Reviews API project idea, a lightweight replication of popular review platforms like Rotten Tomatoes. This will allow users to fetch a list of movies, their details, and associated user reviews.
Here’s how you can implement AMS in an organized way:
- Set Up Your Rails API Project
The first requirement is to create a Rails project in API only mode so that the default Rails stack can be trimmed down for building an API.rails new movie_review_api --api - Add Required Gemfile
Next, add the Gemfile like Faker, which gives you all the serialization tools for generating mock data.- Update your Gemfile to include:
gem 'active_model_serializers' gem 'faker', group: [:development, :test] - Install the gems:
bundle install
- Update your Gemfile to include:
- Create Models and Set Up Associations
Think about the resources your API will expose. We will set up your models- Movie and Review, with the appropriate fields and relationships. A movie can have many reviews. A review belongs to a single movie.
Run the following generators:rails g model Movie title description genre release_year:integer rails g model Review reviewer_name comment rating:integer movie:references
Establish relationships in the models:
# app/models/movie.rbclass Movie < ApplicationRecord has_many :reviews, dependent: :destroy end
# app/models/review.rbclass Review < ApplicationRecord belongs_to :movie end - Database Migration
Once your models and associations are defined, don’t forget to run your database migrations.rails db:migrate - Seed the Database with Mock Data
It is always helpful to work with realistic data when developing an API. We will use Faker to create some sample data for movies and reviews, which will make testing endpoints easier and help observe how serializers behave.
# db/seeds.rb10.times do movie = Movie.create!( title: Faker::Movie.title, description: Faker::Lorem.paragraph, genre: Faker::Book.genre, release_year: rand(1980..2023) ) rand(2..5).times do movie.reviews.create!( reviewer_name: Faker::Name.name, comment: Faker::Lorem.sentence, rating: rand(1..10) ) end end
Seed the database:rails db:seed - Configure Routes
We’ll use versioned routes for scalability.
# config/routes.rbRails.application.routes.draw do namespace :v1 do resources :movies, only: [:index, :show] resources :reviews, only: [:index, :show] end end - Create Serializers
Now we are creating a corresponding serializer for the data of the specific model we want to customize the JSON output for. These serializers determine what attributes are included when the model is rendered as JSON.
# app/serializers/v1/movie_serializer.rbmodule V1 class MovieSerializer < ActiveModel::Serializer attributes :id, :title, :genre, :release_year, :average_rating, :review_count has_many :reviews def average_rating object.reviews.average(:rating)&.round(2) end def review_count object.reviews.count end end end
# app/serializers/v1/review_serializer.rbmodule V1 class ReviewSerializer < ActiveModel::Serializer attributes :id, :reviewer_name, :comment, :rating belongs_to :movie end end - Customize Your Controllers to Use Serializers
You can explicitly specify which serializer to use when rendering JSON using AMS.
# app/controllers/v1/movies_controller.rbmodule V1 class MoviesController < ApplicationController def index movies = Movie.includes(:reviews).all render json: movies, each_serializer: V1::MovieSerializer end def show movie = Movie.find(params[:id]) render json: movie, serializer: V1::MovieSerializer end end end
# app/controllers/v1/reviews_controller.rbmodule V1 class ReviewsController < ApplicationController def index reviews = Review.includes(:movie).all render json: reviews, each_serializer: V1::ReviewSerializer end def show review = Review.find(params[:id]) render json: review, serializer: V1::ReviewSerializer end end end - Example API Responses
GET /v1/movies/1 { "id": 1, "title": "The Shawshank Redemption", "genre": "Drama", "release_year": 1994, "average_rating": 8.7, "review_count": 4, "reviews": [ { "id": 12, "reviewer_name": "Jane Doe", "comment": "A timeless classic.", "rating": 9 }, { "id": 13, "reviewer_name": "John Smith", "comment": "Brilliant storytelling.", "rating": 10 } ] }GET /v1/reviews/13 JSON { "id": 13, "reviewer_name": "John Smith", "comment": "Brilliant storytelling.", "rating": 10, "movie": { "id": 1, "title": "The Shawshank Redemption" } } - Versioning Your API
Versioning is important for maintaining backward compatibility as your API evolves. With AMS, you can simply namespace your controllers and serializers without breaking existing clients. You can create a new version folder (v2) for controllers and serializers. - Test the API Endpoints
Now that everything is done, you can use tools such as Postman to test your API endpoints on the Rails server. You should see clean, structured JSON responses that match your serializer definitions.
This is a good time to check:- The correct attributes are exposed.
- Nested relationships are serialized as expected.
- No sensitive information is being leaked.
Conclusion
Using Active Model Serializers (AMS) in a Rails API project improves the structure and speed of your JSON responses. Serializers help eliminate redundancy, enable clean nested relationships, to maintain consistent formatting across endpoints. It is ideal for projects of any scale, from simple apps to enterprise systems.
At Atharva System, we leverage AMS to build robust, maintainable, and scalable APIs. We combine AMS with best practices. This way, our APIs provide optimized, secure, and frontend-friendly responses for our Rails projects. Our expert team can manage complex model relationships, customize outputs, and boost API performance while reducing unnecessary data exposure.
Want to improve your API development workflow with Active Model Serializers?
Partner with Atharva System—your trusted Ruby on Rails development company—to build efficient, scalable, and performance-optimized APIs tailored to your project needs.






