Build a TDD RESTful JSON TODO-List API (pt.1)

I’ve found this awesome Tutorial on how to create a API, that is also test driven. It’s going to be a easy ToDo-List where users can menage their ToDo-Lists and ToDo-Items.

Let’s start:


With Rails version 5, it’s possible to do a API only application, which means:

  • slim set of middlewear
  • ApplicationController > Application::API instead of Application::Base
  • no view files generated


The API will expose following RESTfull endpoints:


Endpoint Functionality
POST /signup Signup
POST /auth/login Login
GET /auth/logout Logout
GET /todos List all todos
POST /todos Create a new todo
GET /todos/:id Get a todo
PUT /todos/:id Update a todo
DELETE /todos/:id Delete a todo and its items
GET /todos/:id/items Get a todo item
PUT /todos/:id/items Update a todo item
DELETE /todos/:id/items Delete a todo item


Creating the App:

$ rails new todos-api --api -T


The –api -T part sets up for only API featured app, while -T excludes minitests. We won’t test with minitests but with RSpec instead.   This App will have the following Gems:

  • rspec-rails – Testing framework


  • factory girl rails  – replacing fixtures with an easier syntax



  • shoulda matchers  – provides RSpec with additional matchers



  • database cleaners  – cleans the test database



  • faker  – A library for fake data




Installing the Gems:

RSpec Rails: To begin with an error for windows machines and the ‘rails generate rspec:install‘ command. Windows and RSpec doesn’t seem to like each other. Even none of the RSpec Developers work with Windows. The generator creates 3 files:

  • rspec -in the root of our application


  • rails_helper.rb – under spec/folder



  • spec_helper.rb – spec/folder



I just copied the code what would have been generated for us, manually. ( source: ) we have to include the Gem into our gemfile under the :developement and :test group.

group :development, :test do
  gem 'rspec-rails', '~> 3.5'


For the other gems aswell but this time create a new :test only group for:

group :test do

gem 'factory_girl_rails', '~> 4.0'

gem 'shoulda-matchers', '~> 3.1'

gem 'faker'

gem 'database_cleaner'


configure our gems in spec/rails_helper.rb:

# require database cleaner at the top level
require 'database_cleaner'

# [...]
# configure shoulda matchers to use rspec as the test framework and full matcher libraries for rails
Shoulda::Matchers.configure do |config|
  config.integrate do |with|
    with.test_framework :rspec
    with.library :rails

# [...]
RSpec.configuration do |config|
  # [...]
  # add `FactoryGirl` methods
  config.include FactoryGirl::Syntax::Methods

  # start by truncating all the tables but then use the faster transaction strategy the rest of the time.
  config.before(:suite) do
    DatabaseCleaner.strategy = :transaction

  # start the transaction strategy as examples are run
  config.around(:each) do |example| do
  # [...]




Creating the ToDo-Model and the Item-Model


rails g model Todo title:string created_by:string

rails g model Item name:string done:boolean todo:references


todo:references : will add a foreign key in the database and make a belongs_to Todo association in the model


> rails db:migrate


Creating a Models Test with RSpec


for the Todo Model:

# spec/models/todo_spec.rb
require 'rails_helper'

# Test suite for the Todo model
RSpec.describe Todo, type: :model do
  # Association test
  # ensure Todo model has a 1:m relationship with the Item model
  it { should have_many(:items).dependent(:destroy) }
  # Validation tests
  # ensure columns title and created_by are present before saving
  it { should validate_presence_of(:title) }
  it { should validate_presence_of(:created_by) }


and for the Item Model:

require 'rails_helper'

# Test suite for the Item model
RSpec.describe Item, type: :model do
 # Association test
 # ensure an item record belongs to a single todo record
 it { should belong_to(:todo) }
 # Validation test
 # ensure column name is present before saving
 it { should validate_presence_of(:name) }

bundle exec rspec


Results in:


Finished in 0.96329 seconds (files took 4.07 seconds to load)
5 examples, 4 failures

Failed examples:

rspec ./spec/models/item_spec.rb:10 # Item should validate that :name cannot be empty/falsy
rspec ./spec/models/todo_spec.rb:7 # Todo should have many items dependent => destroy
rspec ./spec/models/todo_spec.rb:10 # Todo should validate that :title cannot be empty/falsy
rspec ./spec/models/todo_spec.rb:11 # Todo should validate that :created_by cannot be empty/falsy





Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s