A Guru‘s Guide to Ruby Web Frameworks

So you want to build your next web application using the superb Ruby language? With so many framework options out there, how do you know which one is the best fit?

As an app architect and Ruby aficianado, let me guide you through the top frameworks worth considering…

Why Care About Frameworks Anyway?

Before diving into the tools, let‘s chat briefly about why Ruby frameworks even matter.

You see, as a developer you want to spend time building app features that delight users rather than bogged down writing common stub code needed by all apps. Stuff like:

  • Setting up routing between URLs and code (boring!)
  • Wrangling database access with giant SQL queries (no fun!)
  • Building user login, permissions etc (generic plumbing!)
  • Rendering JSON APIs from objects (tedious!)

Building this generic stuff from scratch is time wasting you could instead spend creating value for app users.

Frameworks eliminate this waste by providing pre-built structures and tools that handle the common boring stuff – freeing you to focus on app-specific logic. They guide you in smart ways to structure apps that are readable and maintainable long-term.

Choosing the right framework for your use case can help you be insanely more productive. The wrong pick can weigh you down needlessly.

Alright, now that you know why frameworks matter, let‘s explore your options…

The Cream of The Crop

Ruby offers a ton of frameworks – from micro to full-stack. I‘ve narrowed things down to the top 10 covering a variety of specialties:

Ruby Framework Mindmap

Let‘s check each one out…

1. Ruby on Rails

For Rapid Full-Stack Web Apps

If you‘ve heard of using Ruby for web dev before, chances are it involved Ruby on Rails. This opinionated full-stack framework rocketed Ruby to fame helping developers build robust apps incredibly quickly.

Rails uses MVC architecture – cleanly separating data, UI display, and business logic concerns into models, views and controllers. This keeps code better organized as apps scale.

For storing and finding data fast, Rails utilizes ActiveRecord – an ORM that translates database rows into usable Ruby objects. This eliminates hundreds of lines of SQL code developers would otherwise need to write manually!

Helper modules provide shortcuts for common tasks like mailing and background jobs – further reducing boilerplate code. Rails also offers integrated unit testing harnessing the RSpec and Minitest frameworks.

With so much built-in out of the box, Rails allows creating functional apps in just days without needing to wire together many separate components by hand. The tradeoff is less flexibility configuring every nitty gritty aspect.

For medium complexity web apps that can work within its assumptions, Rails remains a pioneer in accelerating development.

# Fetch all Article models 
@articles = Article.all

# Pass to view template
erb :articles, :locals => { articles: @articles }

Good for: Medium complexity web apps needing integrated stack

Notable Users: GitHub, Shopify, Basecamp + many more

2. Sinatra

For Lightweight Web Apps and Services

Prefer minimalism over kitchen-sink components? Enter Sinatra. Where Rails provides every imaginable feature, Sinatra offers only bare essentials – routing, de/serialization, and view rendering.

On this foundation developers build up just what‘s needed for their apps using Sinatra‘s elegant middleware and plugin architecture. Need user auth? Plugin Praxis. Database support? Include ActiveRecord. Cucumber tests? Drop them in too.

This modular flexibility allows creating lightweight microservices and API backends callable from any front-end stack. Sinatra imposes little – so you architect things adhering to your app domain‘s needs rather than a predefined way.

For larger apps, Sinatra helps break things into reusable components keeping concerns separated. This maintainability shines for internal tools, admin screens, service APIs.

# Super simple API endpoint
get ‘/api/status‘ do
  json({status: ‘ok‘}) 
end

Good for: Lightweight services, micro frontends, simple APIs

Notable Users: Apple, BBC, Heroku

3. Hanami

For Serious Apps Deserving Rock Solid Architecture

Hanami modernizes conventions established in Rails while optimizing for readability, modularity, testability and just plain awesomeness.

It splits apps into isolated components like activities, services, subscribers etc – promoting coherent single responsibility principles. Test stubs get generated automatically allowing TDD.

Database access utilizes a Repository pattern for supremely clean data fetching/persisting without leaks elsewhere. Hanami configs promote separating technical concerns from business rules.

While opinionated in places, Hanami won‘t hide magic or make decisions on your behalf. Apps built this way signal their intent explicitly making reasoning easy. Fewer surprises means more engineer happiness!

If your app deserves finely crafted architecture set to sustain growth for years, Hanami delivers maintainability in spades.

# Fetch user profile data
profiles = UserRepository.new.all

# Return to controller 
profiles 

Good for: Apps requiring sound architecture

Notable Users: Teams.ai, 10Pines

4. Cuba

For Lightning Fast Microservices

While Hanami focuses on elegant code, Cuba optimizes for raw speed. As a microframework, it provides super lean routing and view helpers on a foundation of pure Ruby (no abstraction layers).

This means SBR (single base Ruby) apps without framework interpretation overhead at runtime. The result allows pushing serious traffic through Cuba backed services.

Cuba won‘t wire out of the box functionality like Rails. But macros simplify adding just what‘s needed for your service like JSON handling, sessions etc. Keep things distant with dumb pipes and smart endpoints.

When microsecond latency and horizontal scale matters above all, Cuba delivers the speed.

Cuba.define do
  on get do
    on "greet" do
      res.write "Hello world!" 
    end
  end 
end

Good for: High throughput microservices

Notable Users: thoughtbot

5. Padrino

For Sinatra Apps With Rails Power-Ups

If given the choice between extreme flexibility or prescribed conventions, many developers would choose… both!

This best-of-both-worlds combo gets delivered by Padrino – an elegant Ruby framework merging Sinatra‘s core simplicity with Rails-like structure baked in if you want it.

Need helper methods, reasonably opinionated MVC, handy form builders, mailer integrations, admin dashboard generators? Padrino can help with all that while avoiding heavyweight baggage.

Under this optional structure remains Sinatra‘s simple elegance – promoting modular componentization giving superpowers absent in classical Rails.

For projects that have outgrown Sinatra‘s purity but don‘t require Rails kitchen sink, Padrino is your friend.

# Fetch all People
@people = Person.all

# Render index page
render ‘people/index‘

Good for: Lightweight web apps benefiting from conventions

Notable Users: CrowdHired, The Audacious Project

6. Grape

For Building Elegant APIs

Increasingly teams prefer serving data via clean REST-ish JSON APIs consumed by diverse front-end apps written in React, Vue etc rather than server-rendered pages.

For this usage, Grape shines – providing a slim Ruby framework tailored specifically for composing representational state transfer style APIs.

It handles routing, request serialization, params/header validation, versioning, namespaces and more – providing just what‘s needed to serve structured data fast while staying out of your way otherwise.

Grape also supports auto generating interactive OpenAPI documentation so front end developers know how to interact with your API endpoints.

If your app vision includes an API foundation with multiple agnostic clients, Grape helps expedite robust services.

# Define API version
version ‘v1‘, using: :path  

# Create namespaced endpoint
namespace :users do

  # Validate params  
  params do
    requires :id, type: Integer 
  end

  # Return user profile
  get ‘:id‘ do
    User.find(params[:id])
  end

end 

Good for: Crafting elegant and maintainable APIs

Notable Users: GitHub, GitLab, Coinbase

Alright, those are my top recommendations if your goal is browser-based web applications…

Going Beyond Websites

While traditional user-facing apps remain common, modern systems often deal with additional specialized background processes:

  • Async job queues (email delivering, image encoding etc)
  • Web scraping results
  • Realtime analytics/reporting engines
  • API consumption mashups
  • Machine learning job orchestration
  • IoT messaging pipelines

Specialized frameworks exist for these alternative use cases – optimized for throughput and resilience without needing traditional request/response flows.

Let‘s check out two great options…

7. Sidekiq

For Robust Background Job Processing

Most web apps require async work unrelated to serving user requests like delivering emails outside request flow.

Sidekiq provides a robust queue and scheduler for offloading this work so web processes remain speedy under load.

Internally it uses threads and processes for parallel work execution. Failed jobs auto-retry with exponential backoff. Web dashboards give transparency into queues, jobs and stats.

By bridging async jobs with HTTP apps, Sidekiq enables building scalable apps with offloaded workflows.

# Enqueue sending welcome email
WelcomeEmailWorker.perform_async(user.id)

# Define worker job
class WelcomeEmailWorker
  include Sidekiq::Worker

  def perform(user_id)
    user = User.find(user_id)
    Mailer.send_welcome(user)
  end
end

Good for: Offloading tasks from web apps

Notable Users: Shopify, AirBnB, Heroku

8. Sneakers

For Integrating External Services

Beyond internal app code, external services often need integrating whether that‘s payment gateways, logistics APIs, inventory databases etc.

Sneakers provides a production ready framework for interfacing with external APIs and message queues – enabling building data pipelines or workflows requiring complex orchestration.

It utilizes RabbitMQ under the hood for message delivery, retry handling, acknowledgements etc. néakers apps subscribe to input queues then translate messages into external API calls with reliable outputs posted to destination queues.

By providing foundational machinery needed for industrial strength integration, Sneakers simplifies orchestrating disparate processes into cohesive systems.

# Subscribe to queue
queue = opts[:queue]
handler do |msg|

  # Decode message  
  order = JSON.parse(msg)   

  # Call external API
  shipper = shippo.create_shipment(order)

  publish shipper, to: :logistics
end

Good for: Message queueing and orchestration

Notable Users: Neighborland, TheRealReal


With website-centric and background processing frameworks covered, you‘ve now seen top options across common domains.

Before rushing to choose one however, let‘s recap how to make sure you‘re setting yourself up for success…

Choosing Your Dream Framework(s)

With so many options, how do you narrow things down to match your app needs?

The easiest way is forgetting about frameworks initially and instead start by modeling domains and flows. Focus on the jobs you need to accomplish:

  • What data needs storing?
  • What processes happen over this data?
  • What events drive actions?
  • How is work executed/coordinated?
  • How do entities communicate?

Thinking in terms of domain entities and behaviors first allows properly matching tools after – rather than cramming every problem to be a web request handler mismatch.

With core app functionality logically modeled, vet potential frameworks against requirements choosing the best fit across areas like:

  • Problem domain/use cases
  • Performance needs
  • Team skills + preferred patterns
  • Feature set + libraries
  • Testing abilities
  • Long term maintainability

For many apps, multiple frameworks working together provide the best results.

Maybe Hanami for complex write-heavy web flows + Sidekiq for background jobs? Or Cuba microservices glued to shared datastores?

Choose barebones frameworks for pure logic domains while leaning on batteries-included opinionated kits for UX flows. Let frameworks enhance your architecture – not distractingly dictate it.

Time To Get Building!

Hopefully you now feel empowered to choose amazing Ruby frameworks tailored precisely to the needs of your app domains and user experiences!

No more cramming round pegs into square holes or overbuilding generic capabilities needing specialization. Each framework shines for certain situations.

Remember – frameworks exist to accelerate development by providing prebuilt commonly needed capabilities so you can focus on app specific logic. Lean on them for the boring commodity stuff and spend your precious time delighting users!

Now – quit reading and go transform an idea into working software awesomeness! 🚀 I can‘t wait to see what you build…

Happy coding my friend!