Recently, I have been exploring options for creating RESTful APIs in the Ruby. Concurrently, I have been investigating Sinatra and its father-framework padrino to create a lighter weight web app. While Sinatra in itself is a suitable solution for APIs, grape is a micro-framework specifically geared towards creating them. It also mounts well alongside Sinatra apps so it follows that it should play well with padrino. Below, I present a method for setting up a grape API in padrino and two methods for testing the API one using plain rspec with rack-test and another using airborne. The complete repo for this process can be found here at padrino-grape-example.
Mounting grape in padrino
Generate a new padrino app:
Note: If you are certain you would like to use plain rspec over airborne for testing you may add the following flag to simplify your setup:
To the Gemfile we add the
grape dependency and additionally we are going to use the gem
grape-padrino which allows Grape APIs to be mounted easily in padrino. This gem adds in class
methods to the stock grape API class that allows it to match up to the Padrino app class and therefore be
bundle install, we can then add an api folder and our
api.rb within it.
Notice the inclusion of
include PadrinoGrape, this is the addition of the class methods touched
Finally, mount this file in Padrino by opening
config/apps.rb and adding the following line:
This will mount the API to
/api/, which can be tested by running the padrino app and visiting
Adding individual resources
Presumably, we will have an API with multiple resources, so to create a sane structure lets separate individual resources into their own files. In order to do this we must autoload the files within the API directory. Open
config/boot.rb and add the following within the
We can then add a new resource by adding a file to the api directory such as
Notice, that we are merely adding to the existing API class so that a new route
exists on the api of
Versioning the API
An important aspect of APIs that we must consider before heading to far down the rabbit hole is how we can version an API. Turns out this is fairly easy with grape, but lets make sure it works.
foo.rb and add the following line within the class:
Saving the file and reloading the server allows us to see that
is no longer accessible, rather it has moved to
/api/v1/foo/hello. So far, so
good, lets create a new version of the foo api at
We can save and restart the server and see that visiting
gives us our desired message. This indicates that versioning works fine. Most
likely we would want the two versions in separate folders but this is merely a
proof of concept.
Testing with rspec and rack-test
To set up basic rspec testing with
rack-test we add the following to the
Additionally you will want to add the boilerplate helpers that are
generated by padrino for
spec/spec.rake or you can
copy them out of this
commit. These merely allow the padrino app to be mounted by rack-test during testing.
This allows us to write a basic test for our hello end point at
This runs and passes and is a perfectly acceptable way to test the API. However,
lets turn to testing with
airborne which I feel is slightly more elegant
Testing with Airborne
Airborne is a gem for testing API that is built upon rspec. It provides a set of helper methods that look extremely promising for testing an API.
We can add it to the Gemfile and run bundle install:
This allows us to write tests such as the following at
Obviously everything up to the describe block could be moved to
is all done in one file for demonstration purposes. We require the gem, load the
padrino app, and configure airborne to use the padrino app. This allows us to
make simple requests as we did in the
rack-test. Much of the airborne
documentation shows tests that hit a FQD, presumably running on a separate server
from the tests themselves. This is useful to remember if we are testing non-rack based
APIs, but in our case we would much prefer it all be handled by rack.
So there we have it, a simple grape API mounted within a padrino app and tested
without our choice of
airborne or simple rspec+rack-test . In brief, we
mounted a single Grape API at the endpoint point
/api/. We then extended
created files for each resource and re-opened by the API class to add them.
Finally, we showed two methods of testing our API via rspec.