After converting a few applications back and forth between Rails and Sinatra I feel like there’s something to be said about where these frameworks excel the most, and the times when they’re just a bad fit.
Sinatra for APIs
Going through the topics in why use Rails for JSON APIs, I consider the vast majority to be unjustifiable:
Reloading/Development mode: anything that makes the development environment different than production is a disaster waiting to happen - be it STI issues, “expected foo.rb to define Foo” or
load_dependencyhell. Any serious Sinatra developer knows about Shotgun, and despite being a stale project I still find it more stable and reliable than Rails environments.
Security: I didn’t know about IP spoofing attacks either, not until the day my Rails app started throwing 500s at random, legit visitors. Turns out that once you have a big enough audience someone will visit your app on some weird ISP and then, guess what - you’ll have to know what IP spoofing is, and how to address it.
Parameter parsing: Great for those of you trying very hard not to design an API. The rest of us want to actually think about how to take input, decide between params or JSON encoded bodies, and render a 400 when appropriate.
Conditional GETs: it is also available in Sinatra, and made significantly simpler; in Rails I always find myself setting
response.last_modifiedand then passing that same date to the
stale?helper, whereas in Sinatra these steps are collapsed together.
THE RAILS ROUTER: So instead of thinking in terms of verbs and paths you can use a crazy DSL that hides everything that matters in your API from you.
So despite enjoying Rails and respecting all the bright minds and hard work that supports it, I still think that a leaner framework like Sinatra works better for pure API apps.
Web apps in Rails
If you ever built a sufficient complex web application in Sinatra you certainly ended up asking questions like:
- How do I separate my views in different folders?
- Do I really need to write all the HTML for forms?
- How can I protect my app against CSRF?
- How can I escape html to avoid XSS attacks?
- How the hell do I adapt my app to use Padrino?
All of these point out to the fact that Sinatra is not the best framework for web applications.
Certainly there are workarounds for these issues, but the end result is in my opinion less consistent and just not as appealing as your regular Rails application.
There’s no such thing as balance
When Rails 1.2 introduced
respond_to and other REST-related features, many thought it was the perfect solution for bringing APIs together with web apps. Me included.
But after a lot of trial and error I began to realize just how different these domains are, and why combining them is dangerous.
To mention some of the issues I’ve experienced in this front:
- Browser compatibility: trivial API changes like making JSON the default format becomes a nightmare when you have to take browsers into account.
- Browser specs: they make the whole suite significantly slower, while also adding pretty substantial dependencies like qt.
- Framework updates: Getting asset pipeline for designers doesn’t come without a lot of backend model adjustments from engineers.
- Security: It’s harder to get CSRF protection right when you have basic HTTP auth working in parallel to sessions.
- Code bloat: It’s also hard to attend the needs of both API clients and web browsers without turning your codebase into a mess. Rails doesn’t help here, as the suggestion that your application should be all contained within models, views and controllers is misleading.
In essence these issues are all telling us how the nature of a pure API app is radically different than the one of a web app:
- Web apps are typically developed by designers and front-end developers. They value things like browser tests and flexibility to change.
- APIs are typically developed by backend developers. They value things like a fast test suite and stable contracts.
And that merging these domains together has a huge cost to everyone involved.