Yodatra

Build Status Coverage Status Gem Version Code Climate Dependency Status

Backend development you shall do. And yodatra you shall use.

A minimalistic framework built on top of Sinatra it is.

The power of ActiveRecord it gives you and the simplicity of a Sinatra app. And all sort of small helpers.

Instantly deploy your API

Based on your ActiveRecord models an API will be exposed very simply. For every resource you want to expose, you will need to create a controller that inherits from the Yodatra::ModelsController.

For example, given a User model

class User < ActiveRecord::Base
# Your model definition
end

Creating a controller as simple as

class UsersController < Yodatra::ModelsController
  # limit read_scope
  def read_scope
    { only: [:id, :name] }
  end

  # whitelist assignable attributes
  def user_params
    params.permit(:name)
  end
end

will expose all these routes:

GET /users

retrieves all users (attributes exposed are limited by the read_scope method defined in the controller)

GET /users/:id

retrieves a user (attributes exposed are limited by the read_scope method defined in the controller)

POST /users

creates a user (attributes assignable are limited by the user_params method defined in the controller as advised here http://guides.rubyonrails.org/action_controller_overview.html#strong-parameters)

PUT /users/:id

updates a user (attributes assignable are limited by the user_params method defined in the controller as advised here http://guides.rubyonrails.org/action_controller_overview.html#strong-parameters)

DELETE /users/:id

deletes a user

If your model is referenced by another model (with a has_many, has_one or belongs_to relationship), nested routes are also created for you. And you don't need to worry about the references/joins, they are done automaticaly!

For example, imagine a Team model that has many Users

class Team < ActiveRecord::Base
  has_many :users
end

the following routes will be exposed by the UsersController controller:

GET /team/:team_id/users
GET /team/:team_id/users/:id
POST /team/:team_id/users
PUT /team/:team_id/users/:id
DESTROY /team/:team_id/users/:id

Note

You can disable any of these actions by using the ::disable class method and providing the list of actions you want to disable

class UsersController < Yodatra::ModelsController
  disable :read, :update, :delete, :nested_read_all, :nested_delete
end

Extra

You can enable a special "search" action by using the ::enable_search_on class method

class UsersController < Yodatra::ModelsController
  enable_search_on :name
end

What it also provides for free

  • Logger: Logs inside <your_project>/log in an environment named file env.err.log for all errors and env.log only for access logs.
  • Boot: loads automaticaly all <your_project>/app/models/**/*.rb files and <your_project>/app/controllers/**/*.rb files. Establish a connection with a database by reading the <your_project>/config/database.yml file

For that create a sinatra app that inherits from Yodatra::Base instead of Sinatra::Base.

Other useful modules

  • Throttling: To fight against the dark side, an API throttling you will need. Example: allow only 10 requests/minute per IP: ruby use Yodatra::Throttle, {:redis_conf => {}, :rpm => 10} warning: this module requires redis
  • ApiFormatter: this middleware will help you to format all your replies. Example: wrap all you replies within a {data: <...>} object: ruby use Yodatra::ApiFormatter do |status, headers, response| body = response.empty? ? '' : response.first response = [{:data => body}] [status, headers, response] end