We will use --api argument to tell Rails that we want an API application.
Create a rails 5 api application by running -
$ rails new todos --api
Now, you can not that Make ApplicationController inherit from ActionController::API instead of ActionController::Base and it has not generated view files.
Now, generate a controller by using scaffold -
$ rails g scaffold User first_name last_name
We will responds with JSON and an HTTP status code 200 by default. For this we will write it in concern.
In app/controllers/concerns/response.rb
module Response
def json_response(object, status = :ok)
render json: object, status: status
end
end
Now, Suppose that we have to find a User by id. In this case where the record does not exist, ActiveRecord will throw an exception ActiveRecord::RecordNotFound. We'll rescue from this exception and return a 404 message.
Also, we will rescue ActiveRecord::RecordInvalid for the case of invalid record and it will return HTTP code 422.
So, make a module in app/controllers/concerns/exception_handler.rb -
module ExceptionHandler
extend ActiveSupport::Concern
included do
rescue_from ActiveRecord::RecordNotFound do |e|
json_response({message: e.message}, :not_found)
end
rescue_from ActiveRecord::RecordInvalid do |e|
json_response({message: e.message}, :unprocessable_entity)
end
rescue_from StandardError do |e|
json_response({message: e.message}, :unprocessable_entity)
end
end
end
Include these modules in the application controller.
class ApplicationController < ActionController::API
include Response
include ExceptionHandler
end
Now, in users controller we can use json_response helper for response.
class UsersController < ApplicationController
before_action :set_user, only: [:show, :update, :destroy]
# GET /users
def index
@users = User.all
json_response(@users)
end
# GET /users/1
def show
json_response(@user)
end
# POST /users
def create
@user = User.create!(user_params)
json_response(@user, :created)
end
# PATCH/PUT /users/1
def update
@user.update(user_params)
head :no_content
end
# DELETE /users/1
def destroy
@user.destroy
head :no_content
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
@user = User.find(params[:id])
end
# Only allow a trusted parameter "white list" through.
def user_params
params.permit(:first_name, :last_name)
end
end
Note that we are using create! instead of create because as we know that create! raise a exception.
You can customize the error message like this -
def create
user = User.new(user_params)
if user.save
json_response(user)
else
json_response({error: 'User has not created'}, :unprocessable_entity)
end
end
I've created this gem that uses a similar approach to handle errors for you:
ReplyDeletehttps://github.com/jamesstonehill/api_error_handler