Roda + Mutations + Jbuilder = Perfect fit for JSON API

RubyI have been a big Ruby fan for many years and during my Ruby journey I have used various frameworks like Rails, Sinatra and Cuba.

When we started to develop Kontena, a tool to manage and deploy Docker containers, we needed some a simple framework to handle our server-side API. Cuba seemed to fit perfectly to our needs, since it is lightweight and benchmark results have been quite impressive. Then we found Roda framework. Roda is originally a fork from Cuba and seems to solve some Cuba pain points.

The main difference between Roda and Sinatra is that Roda uses a routing tree instead of list of routes. Because of this Roda is 2.5 times faster than Sinatra for small applications.

What is especially nice on Roda, it has a plugin system and all parts of Roda can be overridden by plugins.

How Roda framework is used on Kontena

We are using Roda framework on a Kontena Server component. Kontena Server is a component that controls what is happening on Docker host nodes. We have structured our code quite a conventional way:

app/
….jobs/
….models/
….mutations/
….routes/
….services/
….views/
config/
spec/
config.ru
server.rb

The backbone of application consists of API endpoints that are handled by Roda routes. If you have lots of API endpoints, your route file might grow relatively large. To avoid this issue, we have used Roda’s multi_route plugin to keep route files small and clean:

# /v1/services/:id/containers
r.on ':id/containers' do |id|
  load_grid_service(id)
  r.route 'service_containers'
end
V1::ServicesApi.route('service_containers') do |r|
  # GET /v1/services/:id/containers
  r.get do
    r.is do
      @containers = @grid_service.containers
      render('containers/index')
    end
  end
end

Also in order to keep our route files small and simple, we have used mutations gem to handle business logic of operations. By using mutations gem we achieve thin routes and thin active models and separate business logic into testable units that we can test easily

Since our API returns JSON, we are using Roda’s JSON plugin for simple responses. The JSON plugin allows match blocks to return arrays or hashes, and have those arrays or hashes be converted to JSON, which is used as the response body.

For more complicated responses we are using Jbuilder gem, which works also with Roda framework very well.

base.plugin :render, engine: 'jbuilder', ext: 'json.jbuilder', views: 'app/views/v1'
r.get do
  r.is do
    @grid_service = grid_service
    render('grid_services/show')
  end
  ...
end

So far Roda, Mutations and Jbuilder combination has been worked very well for our needs. We have gain clean code structure, testable code base and good performance for our needs.

Kontena is 100% open source. If you have ideas, bug fixes, improvements,  all contributions are welcome!

Advertisements

How to start multiple rails projects just by one command

If you do serious Rails programming, you may have multiple projects for your application. For example you may have one project for an API and another for a web UI. You might also use some background processing like sidekiq etc. Every time you need to launch these services on a development environment, you have to launch all projects in separate consoles manually.

Fortunately there is a better way to do it. By using a gem ‘subcontractor’ together with ‘foreman’ gem, you can define all the projects and services that you want to launch in the ‘Procfile’, for example:

Then you can launch all the projects and services just by one command:

foreman start