Imagine you just bought a new house. The house itself has walls, a roof, and plumbing — that is Rails. But to make it livable, you need furniture, appliances, curtains, and a mailbox. In the Rails world, those furnishings are gems — pre-packaged libraries that add specific functionality to your application.
RubyGems is the package manager for Ruby. When you run bundle install, Bundler reads your Gemfile, resolves all dependencies, and installs exactly the versions you need. The gem ecosystem is one of Rails’ greatest strengths. Whatever problem you are trying to solve — authentication, background jobs, search, file uploads — there is almost certainly a gem that has already solved it.
But not all gems are created equal. Some are maintained by large teams and used by thousands of production apps. Others are side projects abandoned three years ago. Knowing which gems to reach for, and why, is a critical skill for any Rails developer.
Authentication — Devise is the most popular choice. It gives you a complete authentication system out of the box: user registration, login, logout, password recovery, remember-me tokens, and session management. OmniAuth handles third-party logins (Google, GitHub, Facebook) and is often used alongside Devise.
Authorization — Once a user is logged in, what are they allowed to do? Pundit uses plain Ruby classes to define policies per model. CanCanCan uses a single Ability class with can and cannot rules. Both work well; Pundit is more explicit, CanCanCan is more concise.
Background Jobs — Sidekiq processes jobs asynchronously using Redis as its backend. It handles mail delivery, image processing, data imports — anything that should not block the web request. It processes millions of jobs per day at companies like Shopify and Stripe.
Search and Pagination — Ransack builds complex search queries from simple form parameters. Pagy is the modern pagination gem, lightweight and fast. Kaminari is the older, more established option with themeable views.
File Uploads — Active Storage is built into Rails and handles uploads to cloud storage (S3, Google Cloud Storage) or local disk. Shrine is a more flexible alternative with pluggable backends and background processing.
API Serialization — jbuilder is included with Rails by default and lets you build JSON responses using a Ruby DSL in your view templates.
Testing — RSpec is the de facto testing framework. Factory Bot replaces fixtures with flexible factory definitions. Capybara simulates real user interactions in the browser for integration tests.
Monitoring — Sentry captures exceptions in real-time and gives you stack traces, breadcrumbs, and user context. It is free for small projects and scales well.
Think of an open-source project as a public park. Anyone can walk through it, enjoy it, and benefit from it. But parks only stay beautiful when people volunteer to pick up trash, plant flowers, and fix broken benches. The Rails community works the same way.
Rails is maintained by a core team, but the vast majority of improvements come from community contributors. You do not need to be an expert to contribute. Here are the main ways people give back:
Code contributions — The Rails repository on GitHub has thousands of open issues. Some are bug reports with reproduction steps. Some are feature requests with clear acceptance criteria. Pick one that interests you, write a failing test, implement the fix, and open a pull request. The core team reviews every PR.
Triaging issues — Not every contribution requires writing code. Reproducing bug reports, confirming issues on different platforms, and adding labels helps the core team prioritize their limited time.
Documentation — Rails Guides are open for edits. If you find a confusing explanation or a missing example, submit a pull request to the guides repository. Good documentation is as valuable as good code.
Teaching and mentoring — Rails Girls runs workshops around the world introducing women to programming through Rails. RailsBridge offers free workshops for underrepresented groups. Writing blog posts, giving conference talks, and mentoring junior developers all strengthen the ecosystem.
The Contributor Covenant — Rails has a Code of Conduct that applies to all community spaces: GitHub issues, mailing lists, chat rooms, and conferences. It sets expectations for respectful, inclusive behavior.
Rails follows semantic versioning (SemVer): MAJOR.MINOR.PATCH. Each number means something specific:
Rails releases a new minor version roughly every six months. Each major version gets about two years of regular support (bug fixes + security patches), followed by an extended security-only period of about a year and a half. After that, the version reaches end-of-life and receives no updates.
Rails 8 (released December 2024) represents a significant simplification of the framework. Key changes include:
The deprecation pipeline is how Rails handles removing old features. A feature is first deprecated with a warning in one minor release. It continues to work for at least two more minor releases before being removed. This gives you time to update your code.
The Rails ecosystem moves fast. New gems appear weekly, Rails releases every six months, and best practices evolve constantly. Staying current is not about reading everything — it is about having a few reliable sources that surface the most important changes.
Official sources — The Rails blog publishes release announcements and major feature highlights. The Rails Twitter/X account shares shorter updates. The Rails issue tracker is where new features are proposed and discussed.
Newsletters — Ruby Weekly is a weekly email digest of the best Ruby and Rails articles. It has been running since 2009 and consistently surfaces high-quality content.
Video — GoRails produces screencasts covering specific Rails features, gem tutorials, and deployment guides. RubyTapas (by Avdi Grimm) teaches Ruby fundamentals and advanced concepts in short, focused episodes.
Conferences — RailsConf (North America) and RubyConf are the two major annual conferences. Talks are recorded and published on YouTube for free. Regional conferences like EuRuKo (Europe), RubyConf AU (Australia), and RubyConf Taiwan also produce excellent content.
Core team members — Following people like DHH (creator of Rails), Aaron Patterson, Eileen Uchitelle, and Jean Boussier on Twitter/X gives you insight into the direction Rails is heading.
Where should you start? Where should you go next? Here is a curated list, ordered from beginner to advanced:
Beginner — The Rails Guides are the single best starting point. Written by the Rails team, they cover every major feature with working examples. Read them end-to-end once, then keep them as a reference.
Intermediate — The Rails API documentation is the authoritative reference. When you need to know exactly what parameters a method accepts, this is where you look. The Odin Project includes a Rails track that walks you through building multiple projects from scratch.
Advanced — “The Rails 7 Way” by Obie Fernandez is the definitive reference for Rails best practices. It covers patterns, anti-patterns, and the reasoning behind Rails conventions. Exercism’s Ruby track sharpens your Ruby skills with mentored exercises.
Practice — Build something real. A blog, a task tracker, an e-commerce prototype. Each project will expose you to new patterns and force you to solve problems that tutorials cannot anticipate.
Rails versions and Ruby versions are tightly coupled. Each Rails release has a minimum required Ruby version, and running older Ruby versions means missing out on performance improvements and security patches.
| Rails Version | Minimum Ruby | Recommended Ruby |
|---|---|---|
| Rails 7.0 | Ruby 2.7 | Ruby 3.1 |
| Rails 7.1 | Ruby 3.1 | Ruby 3.2 |
| Rails 7.2 | Ruby 3.1 | Ruby 3.3 |
| Rails 8.0 | Ruby 3.2 | Ruby 3.4 |
Why does this matter? Ruby 3.x introduced several performance improvements. YJIT (Yet Another Ruby JIT), built into Ruby 3.1+, compiles hot code paths to native machine code at runtime, giving 10-30% speedup for typical Rails workloads. Ruby 3.3 improved YJIT further and added a faster garbage collector.
Managing Ruby versions is handled by version managers. rbenv is the most popular — it lets you install multiple Ruby versions side by side and switch between them per-project using a .ruby-version file. rvm (Ruby Version Manager) is an alternative with similar functionality. asdf is a polyglot version manager that handles Ruby, Node, and other runtimes.
The .ruby-version file in your project root tells your version manager which Ruby to use. Commit this file to your repository so every developer on the team (and your CI server) uses the same Ruby version.
# Install a Ruby version
rbenv install 3.3.5
# Set the project Ruby version
rbenv local 3.3.5
# This creates .ruby-version
cat .ruby-version
# 3.3.5
When upgrading Rails, check the release notes for the minimum Ruby version. Upgrading Ruby first, then Rails, is the safest order.
Rails is an SUV — spacious, comfortable, handles almost any terrain, and comes loaded with features. But not every trip needs an SUV. Sometimes a motorcycle is more fun, or a pickup truck is more practical. Ruby has alternatives for different use cases.
Sinatra is a lightweight DSL for building web applications with minimal code. A complete web app can be 10 lines of Ruby. There is no ORM, no asset pipeline, no built-in testing framework — just routing and request handling.
require 'sinatra'
get '/' do
'Hello, World!'
end
get '/hello/:name' do
"Hello, #{params[:name]}!"
end
Choose Sinatra when you need a small API, a webhook handler, or a microservice. It is ideal when Rails’ conventions feel like overhead.
Hanami (formerly Lotus) takes the opposite approach from Rails. It enforces strict separation between application layers: each entity is a plain Ruby object, each repository handles persistence, and each view is a separate class. No Active Record magic, no global state.
Choose Hanami when you want clean architecture, explicit dependencies, and strong boundaries between components. It is more verbose but easier to test and reason about at scale.
Roda is a routing-focused framework. It uses a routing tree DSL and assumes nothing about your application structure. You bring your own ORM, your own view layer, your own everything.
Choose Roda when you want maximum control and minimal framework opinions. It is popular for API-only services and when you need to integrate with existing codebases.
| Feature | Rails | Sinatra | Hanami | Roda |
|---|---|---|---|---|
| Convention | Strong | None | Strong | None |
| ORM | Active Record | Bring your own | Hanami Model | Bring your own |
| Asset Pipeline | Yes | No | Yes | No |
| Best for | Full-stack apps | Microservices | Clean architecture | APIs, flexibility |
| Learning Curve | Medium | Low | High | Medium |
Most Rails developers never need an alternative. Rails handles 95% of web applications well. But knowing these alternatives exists helps you recognize when a different tool is the right choice.
You have built your Rails app, tested it locally, and it works. Now what? Getting your app from your laptop to a server where anyone on the internet can access it — that is deployment. It sounds simple, but it involves several moving parts.
Before deploying, make sure you have these covered:
.env files locally and set them on the server or in your deployment platform’s dashboard.rails db:migrate in the production environment after deploying new code.rails assets:precompile to compile and fingerprint your CSS, JavaScript, and image assets.credentials.yml.enc for encrypted secrets. Edit them with rails credentials:edit.Traditional — Heroku popularized the git-push-to-deploy workflow. AWS Elastic Beanstalk and DigitalOcean App Platform offer similar experiences. You push code, the platform builds it, and it runs.
Container-based — Docker packages your app and all its dependencies into a container image. Kubernetes orchestrates containers across multiple servers. Kamal (Rails 8’s recommended tool) deploys containers to a single server or a fleet with minimal configuration.
Modern PaaS — Render, Fly.io, and Railway offer the simplicity of Heroku with modern infrastructure. They handle SSL, auto-scaling, and background workers. Fly.io is particularly interesting for Rails apps because it deploys close to your users using edge servers worldwide.
A modern deployment pipeline looks like this: push code to Git, CI runs tests and linters, assets are compiled, the new release is deployed to the server, migrations run, the app restarts, and a health check confirms everything works. If anything fails at any stage, the pipeline stops and alerts you.
One of the most common questions in the Rails community: should I use Rails views, or should I add React/Vue on top? The answer depends on what you are building. There are three main approaches, each with different tradeoffs.
The classic approach. Rails renders HTML on the server using ERB templates. Turbolinks intercepts link clicks and replaces only the <body> content, making navigation feel faster without writing any JavaScript.
This is the fastest way to build a Rails application. No Node.js, no webpack, no JavaScript build step. You get server-rendered HTML (great for SEO), fast initial page loads, and the full power of Rails helpers in your views.
The downside is limited interactivity. If you need a rich, dynamic interface — drag-and-drop, real-time updates, complex state management — ERB templates will fight you.
Rails becomes a pure JSON API. A separate React or Vue application handles all UI rendering in the browser. The two communicate via REST endpoints or GraphQL.
This gives you the full power of the React/Vue ecosystem: component libraries, state management, animation libraries, and developer tools. You can reuse the API for a mobile app. Teams can work on frontend and backend independently.
The downside is complexity. You now have two codebases, two build processes, and two deployment pipelines. Authentication is more involved (token-based instead of session-based). SEO requires server-side rendering or pre-rendering. The initial page load is slower because the browser must download and execute JavaScript before showing anything.
Hotwire is the Rails team’s answer to the “do I need React?” question. Turbo (the core of Hotwire) sends HTML fragments from the server and swaps them into the page without a full reload. Stimulus adds lightweight JavaScript controllers for client-side behavior.
The result: you get interactivity that feels like a single-page app, but you are still writing Rails views and sending HTML from the server. No API serialization, no client-side state management, no Node.js build step.
This is the default in Rails 7+. Turbo Frames replace specific page sections. Turbo Streams push real-time updates over WebSocket. Turbo Drive handles fast page navigation. It handles 80% of what teams previously reached for React to solve.
The downside is less control over client-side state and limited animation capabilities compared to React/Vue.
| Factor | ERB + Turbolinks | API + React/Vue | Hotwire/Turbo |
|---|---|---|---|
| Development speed | Fastest | Slowest | Fast |
| Interactivity | Low | Highest | Medium-High |
| SEO | Excellent | Needs SSR | Excellent |
| Complexity | Lowest | Highest | Low |
| Team skills needed | Ruby/Rails | Ruby + React/Vue | Ruby/Rails |
| Mobile app reuse | No | Yes | No |
Most Rails applications should start with Hotwire/Turbo. It gives you enough interactivity for most use cases without the complexity of a separate frontend. Add React or Vue only when you have a specific need that Hotwire cannot meet — like a complex dashboard, a real-time collaboration feature, or a shared codebase with a mobile app.
# app/views/posts/index.html.erb
<%= turbo_frame_tag 'posts' do %>
<%= render @posts %>
<%= link_to 'Next page', posts_path(page: @posts.next_page),
data: { turbo_stream: true } %>
<% end %>
# app/views/posts/_post.html.erb (Turbo Stream)
<%= turbo_stream_from @post %>
<div id='<%= dom_id(@post) %>'>
<h2><%= @post.title %></h2>
<p><%= @post.body %></p>
<button onclick="this.closest('div').remove()">
Remove
</button>
</div>
# Turbo Streams for real-time updates
# app/controllers/posts_controller.rb
def create
@post = Post.create!(post_params)
respond_to do |format|
format.turbo_stream
end
endYou have reached the end of our journey through the Rails ecosystem. Here is a checklist to verify your understanding: