Why I chose Rails::Api over Grape

First of all, choosing a technology must be done by writing down your needs and looking for the most fitting tech.

That’s what I’ve done, I’m building multiple APIs for an early-stage product to be commercialized soon, small team, big expectations, you know that feeling, right ?

By being the only back-end dev in the team, I wanted something that I can replicate for the services built, beginning with the same framework. I mean, who wants to write the same base configuration over and over in such a short period of time ?

The project will consist in 3 APIs: one for the authentication, one for the mutualized data and the last one is for our clients (one by client, + they have their own DB).

The development process does not change across the services, especially when they belong to one same project. Here, we are doing TDD and API documentation.

Some of the gems I will be using for theses APIs: ActiveRecord, Rspec, FactoryGirl, Bullet, Webmock, Rubocop, Dotenv, Oj, Guard, DatabaseCleaner, Rack::Attack, Puma.

First try: Grape

I’ve built some apps on top of Grape a couple years ago, it felt light and easy to learn, at first glance, this was the one framework to choose.

Yet, to start a new project with Grape was a pain in the ass.

ActiveRecord issue

I decided to start the base configuration with ActiveRecord.

Let’s start ! gem ‘activerecord’, ‘~> 5.1’ in Gemfile, check. Bundle install, check. Database.yml, check. config/activerecord.rb, check. Require in application.rb, check.


What could go wrong ?

$ rake generate migration CreateUsers first_name:string
Don't know how to build task 'generate'

DAMN! I’m not using rails… no migration generator. Well, let’s see if I can find one on the internet… YES! Saved me some time. Let’s continue…

$ rake db:create_migration NAME=create_users
$ emacs db/migrate/20170519123546_create_users.rb
$ rake db:migrate
Don't know how to build task 'db:migrate'

What the …

I required and added the tasks in my Rakefile, everything was working… except… THE POOLING.

Did you know the connection management middleware was removed from AR5 ? Well it has been… Take a look at this: Rails Issue#26947

I had to seek, copy and paste the corresponding old middleware.

Do you get the point ? Everything is like this with Grape, I won’t even talk about grape-swagger, the tool used to auto-document the API. The syntax was never the same depending of examples and implementations, the generated documentation was either broken or incomplete depending of the builder (slate, markdown, html etc..).


Build now, optimize later.

The choice of Grape was mainly driven by the need of a light API, we design microservices, not macroservices. Since the project is to be commercialized soon, it must also be finished soon. The Grape thing made me loose 3 days of learning and config. 3 APIs: Multiply by 3 the pain.

Optimization is a second time issue, once you encounter those problems, that means your product is used, we started new projects from scratch 4x internally to fit our (evolving) needs, think about the time I could have lost by caring too much about optimization ? The 4th version is the one to be commercialized, but it does not mean we won’t change things a bit again, maybe not starting from scratch but still.

Product used = cash. You buffer the performance issue by adding some Dynos if you are on heroku, Instances for AWS or Google Cloud. And you have now more time to add a cache, optimize your queries, and so on..

Focus on the speed of development

Rails allows me to start an API in less than a day. I can give front end devs a working microservice in less than a week, this is Rails.

$ rails new project_name --api --skip-javascript --skip-turbolinks --skip-test --skip-sprockets --skip-yarn --database=postgresql

I added the gems listed above. Bundle install…

$ rails g rspec:install
Running via Spring preloader in process 20207
create .rspec
create spec
create spec/spec_helper.rb
create spec/rails_helper.rb
$ rails g scaffold user first_name:string last_name:string #etc...
Running via Spring preloader in process 29829
invoke active_record
create db/migrate/20170519133252_create_users.rb
create app/models/user.rb
invoke rspec
create spec/models/user_spec.rb
invoke factory_girl
create spec/factories/users.rb
invoke resource_route
route resources :users
invoke scaffold_controller
create app/controllers/users_controller.rb
invoke rspec
create spec/controllers/users_controller_spec.rb
create spec/routing/users_routing_spec.rb
invoke rspec
create spec/requests/users_spec.rb

Ain’t it beautiful?