Skip to content

Repository files navigation

JSON:API Server Example

This is an application that provides a simple example of a JSON:API compliant server written in Ruby on Rails. It's based on the cerebris/peeps application that is the demo of cerebris/jsonapi-resources.

Instructions

Follow these instructions to create the application.

  1. Create the rails app.

    rails new json_api_server_example --skip-javascript --skip-test-unit
  2. Create the database.

    bin/rake db:create
  3. Edit the Gemfile (the application's dependencies).

    • Remove unnecessary gems.
    • Add the jsonapi-resources to easily define an interface for our resources that complies with JSON:API specification.
    • Add rspec-rails, spring-commands-rspec, and shoulda-matchers for the test infrastructure.
    • Add factory_girl_rails to generate factories to make testing easier.
    # Gemfilesource"https://rubygems.org"gem"rails","4.2.0"gem"pg"gem"jsonapi-resources"group:development,:testdogem"byebug"gem"spring"gem"rspec-rails","~> 3.1.0"gem"spring-commands-rspec"gem"factory_girl_rails","~> 4.5.0"endgroup:testdogem"shoulda-matchers",require: falseend
    bundle install
    bin/rails generate rspec:install
    bundle exec spring binstub rspec
  4. Configure the environment.

    # config/environments/development.rb# avoids autoloading strangeness and thread safety issuesconfig.eager_load=true# don't generate helpers because we're not going to use themconfig.generators.helper=false
  5. Subclass ApplicationController from JSONAPI::ResourceController.
    This will give controllers that inherit from ApplicationController the ability to respond to JSON:API formatted requests.

    # app/controllers/application_controller.rbclassApplicationController < JSONAPI::ResourceControllerend
  6. Create the resources directory where we'll add our resources classes.

    mkdir app/resources
  7. Create a model, test that it worked, and add a factory.

    bin/rails g model Sport name:string
    bin/rake db:migrate Sports --skip-assets
    # spec/models/sport_spec.rbRSpec.describeSport,type: :modeldoit{is_expected.tohave_attribute:name}end
    # spec/factories/sports.rbFactoryGirl.definedofactory:sportdoname"Basketball"endend
  8. Create a resource.

    # app/resources/sport_resource.rbclassSportResource < JSONAPI::Resourceattributes:nameend
  9. Setup the routes.

    # config/routes.rbRails.application.routes.drawdojsonapi_resources:sportsend
  10. Test that the sports resource is accessible via the API. This is just a simple set of tests to show that everything works and will be updated later as we add additional functionality.

    # spec/controllers/sports_controller_spec.rbrequire'rails_helper'RSpec.describeSportsController,:type=>:controllerdodescribe"POST create"doit"responds with a 201 status"dopost:create,sports: FactoryGirl.attributes_for(:sport)expect(response.status).toeq201endenddescribe"GET show"doit"responds with a 200 status"doget:show,id: FactoryGirl.create(:sport)expect(response.status).toeq200endenddescribe"PUT update"dolet!:sportdoFactoryGirl.create(:sport)endit"updates the resource and responds with a 200 status"doexpect(sport.name).toeq"Basketball"put:update,id: sport,sports: {name: "basketball"}expect(sport.reload.name).toeq"basketball"expect(response.status).toeq200endenddescribe"GET index"doit"responds with a 200 status"doget:indexexpect(response.status).toeq200endenddescribe"DELETE destroy"doit"responds with a 200 status"dosport=FactoryGirl.create(:sport)delete:destroy,id: sportexpect(Sport.find_by(id: sport)).tobe_nilexpect(response.status).toeq204endendend
  11. Test that the sports resource is serialized into JSON with the correct format.

    First, to DRY up the code, create an example group that will be added to all resource specs.

    # spec/rails_helper.rb# This will require all files in the support directory.# ...Dir[Rails.root.join("spec/support/**/*.rb")].each{ |f| requiref}
    # spec/support/example_groups/resource_example_group.rbmoduleResourceExampleGroupextendActiveSupport::Concernincludeddorequire"jsonapi/resource_serializer"let:serializerdoJSONAPI::ResourceSerializer.new(described_class)endlet:modeldoFactoryGirl.build_stubbed(described_class._model_class.model_name.element,id: 1001)endlet:resourcedodescribed_class.new(model)endlet:serialized_hashdoserializer.serialize_to_hash(resource)endendRSpec.configuredo |config|
    config.include(self,type: :resource,file_path: %r(spec/resources))endend

    Then, test that the serialized sport resource matches our expectation.

    # spec/resources/sport_resource_spec.rbrequire"rails_helper"describeSportResourcedolet:expected_serialized_hashdo{"sports"=>{"id"=>1001,"name"=>"Basketball"}}endit"serializes the sport into the correct JSON format"doexpect(serialized_hash).toeq(expected_serialized_hash)endend
  12. Start a development server and try the API out via curl.

    bin/rails server
    curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X POST -d '{"sports": {"name": "Basketball"}}' http://localhost:3000/sports
    HTTP/1.1 201 Created
    X-Frame-Options: SAMEORIGIN
    X-Xss-Protection: 1; mode=block
    X-Content-Type-Options: nosniff
    Content-Type: application/json; charset=utf-8
    Etag: W/"51eb95f4b3dc2f26a423d3072646f26e"
    Cache-Control: max-age=0, private, must-revalidate
    X-Request-Id: 4dd8b179-366e-408f-a692-c87479979894
    X-Runtime: 0.028043
    Server: WEBrick/1.3.1 (Ruby/2.2.0/2014-12-25)
    Date: Fri, 09 Jan 2015 14:46:21 GMT
    Content-Length: 39
    Connection: Keep-Alive
    {"sports":{"id":1,"name":"Basketball"}}
    curl http://localhost:3000/sports/1
    {"sports":{"id":1,"name":"Basketball"}}
    curl -H "Accept: application/json" -H "Content-Type: application/json" -X PUT -d '{"sports":{"name": "basketball"}}' http://localhost:3000/sports/1
    {"sports":{"id":1,"name":"basketball"}}
    curl http://localhost:3000/sports
    {"sports":[{"id":1,"name":"basketball"}]}
    curl -i -X DELETE http://localhost:3000/sports/1
    HTTP/1.1 204 No Content

About

Example of a Ruby on Rails server with a json:api compliant API.

Resources

Stars

0 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages