Welcome to the first of four Ruby on Rails Developer Series. In this series, the goal is to outline how to strengthen your API with Postgres, how to dockerize your project and add security layers to mitigate attacks to your application. In this article, we'll cycle through building a quick API-only application uses the JSON API from Active Model Serializer. Then construct a basic CRUD Controller API example on retrieving the User information. While the process is outlined and best practices are used. The goal of the series is to make you feel confident as an engineer in building a structured project with Ruby on Rails.
Let's Begin
Let's start off by using the --api
command in the console to provision an api only preset.
rails new rails-json-api-test --api
This will generate the following:
app/controllers app/assets app/helpers app/models config
Objective CRUD
Our goal is to use the ActiveModel::Serializer - JSON API - which is included by default in your Gemfile when you create an application using the --api
directive. We will then work toward spinning up a basic CRUD endpoint for a user.
Below is the endpoint we plan to implement and http methods we plan to send to the API.
Path: /api/v1/users
GET POST PUT DELETE
Next, we need to generate the basic User Model that we want to create using the rails generate command for Models:
First, we need to set up our database. In this example, we will be using PG (Postgres) and will set up the minimum requirement to allow us to proceed to build our API and come back to this in the next article.
gem pg
Then we need to set up our database.yml
file
default: &default adapter: postgresql host: localhost port: 5432 encoding: utf8 pool: 5 database: rails-json-api username: development password: development development: &default adapter: postgresql host: localhost port: 5432 encoding: utf8 pool: 5 database: rails-json-api-dev username: development password: development
Then we're ready to create the database and build our table.
rake db:create
rails g model User first_name:string last_name:string email:string
That should generate something like this:
invoke active_record create db/migrate/20190521020122_create_users.rb create app/models/user.rb invoke test_unit create test/models/user_test.rb create test/fixtures/users.yml
Now let's work on the serializer side of things of how the API will respond to the request.
We will want to uncheck this in the gemfile:
gem 'active_model_serializers', '~> 0.10.0'
When we make the controller we will need the namespaces to be setup:
For the namespace to change fromApi::V1::UsersController
to API::V1:UsersController
we need to modify the inflection file which was generated in config/initializers/inflections.rb
. We will then need to uncomment and add this to the file:
ActiveSupport::Inflector.inflections(:en) do |inflect| inflect.acronym 'API' end
Lock down your routes to ONLY ALLOW
these method requests.
Rails.application.routes.draw do namespace :api, path: '' do namespace :v1 do resources :users, only: [:index, :show, :create, :update, :destroy] end end end
This is what our controller looks like to be able to support our methods:
class API::V1::UsersController < ApplicationController rescue_from ActiveRecord::RecordNotFound, with: :record_not_found def index users = User.all render json: users, each_serializer: UserSerializer, adapter: :json_api, status: 200 end def show user = User.find(params[:id]) render json: user, serializer: UserSerializer, adapter: :json_api, status: 200 end def create user = User.new(user_params) render json: user, serializer: UserSerializer, adapter: :json_api, status: 200 if user.save! end def update user = User.find(params[:id]) render json: user, serializer: UserSerializer, adapter: :json_api, status: 200 if user.update(user_params) end def destroy user = User.find(params[:id]) render json: user, serializer: UserSerializer, adapter: :json_api, status: 200 if user.destroy! end private def record_not_found render json: { message: 'Record Not Found!'}, adapter: :json_api, status: 404 end end
Responding with JSON
JSON API is a format that works to optimize http(s) requests mainly to promote more productivity and efficiency. JSON API comes with strong caching functionality as data changes affect fewer resources.
You can simply add this to the Serializer to implement basic key-based cache expiration:
cache key: 'user', expires_in: 3.hours
Conclusion
We have just spun up a JSON API in a few minutes for our User Table. We have left some items for the next part of the series to strengthen our API-based application. In the next article, we will further work on building a strong JSON API and using Postgres to your advantage.
This project is available on my repo here
Additional resources
Learn how to tame the Jenkins JSON API with Depth and "Tree."
How do JSON and XML compare? Find out here.
Discover what JSON Schema is and what role it plays.