Rails JSON API Tutorial – Using JSONAPI Resources Gem

rails json api tutorial
Standard

Rails JSON API Tutorial Introduction

In this Rails JSON API tutorial, we will discuss how to quickly build a JSON API that is JSONAPI spec compliant using Ruby on Rails and jsonapi-resources gem.

This tutorial assumes that you already have Ruby and Ruby on Rails installed on your computer and you already have a basic understanding how APIs work. This tutorial uses Ruby 2.1.2 and Rails 4.2.0.

JSONAPI spec is a specification for building APIs in JSON. The spec covers how a client should request that resources be fetched or modified, and how a server should respond to those requests.

JSONAPI spec is pretty big! But take note that we don’t have to implement all the things that the spec covers to make our Rails API JSONAPI spec compliant.

Building an API that is JSONAPI spec compliant is a lot of work especially if you need many of the features that it covers. In this tutorial, we will use a Rails library called jsonapi-resources to help us quickly build a JSONAPI spec compliant API.

What will we build?

We will build a very simple Todo API that is JSONAPI compliant and has the following features:

  • Create a todo
  • View a todo
  • Update a todo
  • Delete a todo

Creating a Ruby on Rails Application and Installing JSONAPI-Resources

Create a Ruby on Rails application by running this command in your terminal:

rails new todo-json-api

The command above will create a folder named todo-json-api. Go inside the folder using this command:

cd todo-json-api

Next, add json-api resources to the application’s Gemfile:

gem 'jsonapi-resources'

And then run this command in your terminal:

bundle

You now have now successfully created a Rails app and installed jsonapi-resources.

Creating a Model

Our app needs to be able to create, read, update and delete a todo in the database. Let’s create a Todo model with a title and a description.

rails generate model Todo title:string description:text

The command above will create the model and the database migration file. Now let’s run the migration by running this command in the terminal window:

rake db:migrate

Creating a Resource

In jsonapi-resources, resources define the public interface to your API. A resource defines which attributes are exposed, as well as relationships to other resources.

We can use a generator for creating a jsonapi-resources resource. Run this command in your terminal:

rails generate jsonapi:resource todo

The command above will create a todo_resource.rb file under todo-json-api/app/resources directory. The resources folder will be automatically created if it doesn’t yet exist.

Any of a resource’s attributes that should be accessible must be explicitly declared. So we have to add this in todo_resource.rb:

attributes :title, :description

The todo resource should now look like this:

class TodoResource < JSONAPI::Resource
  attributes :title, :description
end

Creating the Resource Controller

There is a generator for creating jsonapi-resources’ resource controller but for some reason it doesn’t work when I tried to use it. The command is:

rails generate jsonapi:controller todos

If it also doesn’t work for you, just create the resource controller manually. To create the resource controller manually, create a file under todo-json-api/app/controllers and name the it todos_controller.rb and add the code below to the file:

class TodosController < JSONAPI::ResourceController

end

We now have a resource controller for our todos resource. JSONAPI-Resources’ resource controllers by default gives you a fully functional controller it automatically expose endpoints for creating, reading, updating and deleting a resource. That means we now have API endpoints for creating, reading, updating and deleting a todo with very minimal effort! That’s what makes the combination of Rails and jsonapi-resources awesome!

Start the server by running this command in your terminal window:

rails server

 

Using the JSON API

We can now use our JSON API.

To create a todo:

POST /todos

Content-Type: application/vnd.api+json
Accept: application/vnd.api+json

{
  "data": {
    "type": "todos",
    "attributes": {
      "title": "Sample title",
      "description": "Sample description"
    }
  }
}

To read a todo:

GET /todos/

Content-Type: application/vnd.api+json
Accept: application/vnd.api+json

To update a todo:

PUT /todos/

Content-Type: application/vnd.api+json
Accept: application/vnd.api+json

{
  "data": {
    "type": "todos",
    "id": "1",
    "attributes": {
        "title": "New title"
    }
  }
}

To read/fetch a todo:

GET /todos/

Content-Type: application/vnd.api+json

{
    "data": {
        "id": "1",
        "type": "todos",
        "links": {
            "self": "http://localhost:3000/todos/1"
        },
        "attributes": {
            "title": "Sample title",
            "description": "Sample description"
        }
    }
}

To delete a todo:

DELETE /todos/

Content-Type: application/vnd.api+json
Accept: application/vnd.api+json

To fetch a list of todos:

GET /todos

Content-Type: application/vnd.api+json
Accept: application/vnd.api+json

The api that we created also supports sorting even if we haven’t written any code for it.

GET /todos?sort=title

Content-Type: application/vnd.api+json
Accept: application/vnd.api+json

Adding Pagination

To add pagination support to our API, create a file under todo-json-api/config/initializers/ and name it jsonapi_resources.rb then copy and paste the code below:

JSONAPI.configure do |config|
  # built in paginators are :none, :offset, :paged
  config.default_paginator = :paged

  config.default_page_size = 10
  config.maximum_page_size = 20
end

Feel free to modify config.default_page_size and config.maximum_page_size.

Now we are done adding a paged pagination to our API. It’s that easy!

To use the pagination feature:

GET /todos?page%5Bnumber%5D=1&page%5Bsize%5D=1

Content-Type: application/vnd.api+json
Accept: application/vnd.api+json

You can use Curl or a Google Chrome extension called PostMan to easily test the API.

Here’s a sample curl command for creating a todo:

curl -H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-X POST -d '{"data": {"type": "todos", "attributes": { "title": "Sample title", "description": "Sample description" }}}' http://localhost:3000/todos -i

And here’s a curl command for fetching a list of todos:

curl -H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
http://localhost:3000/todos -i

Here’s a screenshot when using PostMan to create a todo:

rails-json-api

Adding Validation

You might notice that we are able to create a todo that has no title and description. What if we want to make sure that a todo can’t be saved without a title? We will use a validator. Add this code in the Todo model.

In todo-json-api/app/models/todo.rb:

validates :title, presence: true

Our todo model should now look like this:

class Todo < ActiveRecord::Base
  validates :title, presence: true
end

Now if you try to create a todo with an empty title, the server will respond with 422 status code and this payload:

{
    "errors": [
        {
            "title": "can't be blank",
            "detail": "title - can't be blank",
            "id": null,
            "href": null,
            "code": 100,
            "source": {
                "pointer": "/data/attributes/title"
            },
            "links": null,
            "status": "422",
            "meta": null
        }
    ]
}

Conclusion

Ruby on Rails framework and JSONAPI-Resources library enables us to quickly build APIs that are JSONAPI spec compliant with very minimal effort.

We learned how to add API endpoints for creating, reading, updating and deleting a resource. We also learned how to add sorting and pagination support and a simple validation.

In future tutorials, we might cover how to add things like complex validations, authentication, authorization, relationships etc…

Feel free to provide a feedback or share your thoughts about the topic by leaving a comment below. If you find this Rails JSON API tutorial useful, please share it 🙂

The source code of the tutorial is on Github.

Learn Ruby from scratch. Build and launch a web app. Start learning for FREEhttp://treehouse.7eer.net/c/245500/245636/3944

You can follow me on Twitter: https://twitter.com/johnkevinmbasco

Are you looking for a remote/home based job? Visit http://digitalnomadgigs.com/

Looking for a developer? I’m accepting web/mobile development projects. Shoot me an email: [email protected]

  • xiuren

    Hi! thanks for the very helpful tutorial~

    Just one point though, maybe the step to add the routing would be helpful to some readers 🙂

    • Thanks for the feedback.

      I forgot to add the step for adding the route. I’ll update the post. Thanks 🙂

      • khalidh12

        please add step by step process, i am not understand the get/todo post/todo process

  • Javier Ojeda

    Dude this is very awesome! I’m new in Rails development and I found this post very very helpful.

    ¡I like Rails, but now I love it!

    For those who have the routing problem, here is the solution: Just add this line to the config/routes.rb file

    resources :todos # this will make it work!

    • Hi Javier, I’m glad you find it useful 🙂

      Thanks for sharing your solution about the routing issue. I haven’t had the chance to update the post. Been very busy recently.

  • Halley Rios

    Hello a question what is the advantage or difference USE f JSON- API- resources from the rails – API ?

  • khalidh12

    how to create post todo, get todo ? where to create post, get todo ? please add step by step process, i am not understand the get/todo post/todo process

  • Also one more tip,
    If you use Google Chrome, you can use Postman add-on, which makes your life easier than going to black screen and hit curl cmd.
    https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop?hl=en

  • Jacob Giberson

    Hey thanks for the tutorial, I’m not sure why it wont work for me, I am getting this error
    {
    “errors”: [
    {
    “title”: “Param not allowed”,
    “detail”: “id is not allowed.”,
    “code”: “105”,
    “status”: “400”
    }
    ]
    }
    any ideas?