Ruby on Rails
Build web applications with Rails - ActiveRecord patterns, generators, Hotwire for modern UIs, background jobs with Sidekiq, and Rails conventions.
skill: Ruby on Rails category: Backend tags: [Ruby, Rails, ActiveRecord, MVC, Convention over Configuration] readingTime: 5
Rails is the original convention-over-configuration framework - it makes CRUD applications the fastest to build by eliminating decisions through opinionated defaults. For teams that fit its conventions, Rails remains one of the most productive frameworks. The pitfall: straying too far from the conventions erodes the productivity benefit.
Workflow
- Use ActiveRecord effectivelyActiveRecord is Rails' ORM - its conventions (table names from class names, primary keys as "id") reduce boilerplate. But N+1 queries and missing indexes are common pitfalls.
- Generate and migrate with Rails generatorsRails generators create models, controllers, migrations, and tests in seconds. They enforce conventions and wire all pieces together automatically.
- Build modern UIs with HotwireHotwire (Turbo + Stimulus) delivers SPA-like UX without writing JavaScript frameworks. Server renders HTML; Turbo updates the page; Stimulus handles JavaScript behavior.
- Run background jobs with SidekiqLong-running tasks (emails, image processing, API calls) should not run in the web request cycle. Sidekiq processes them asynchronously using Redis.
- Cache effectively in RailsRails caching reduces database queries and improves response times. Fragment caching, low-level caching, and HTTP caching all have their place.
Output Format
Rails: ActiveRecord with includes for N+1 prevention, generators for scaffolding, Hotwire Turbo Frames for partial page updates, Sidekiq for async jobs, and fragment + low-level caching.
ActiveRecord: User.includes(:orders).where(active: true)
Migration: create_table + add_index
Hotwire: <turbo-frame id="user_N"> for partial updates
Sidekiq: perform_later(id) + retry_on + queue_as
Cache: Rails.cache.fetch("key", expires_in: 5.minutes) { query }Examples
Edge Cases & Gotchas
- Callbacks and service objects - Rails after_create, before_save callbacks make models hard to test and reason about. Extract complex logic into service objects or form objects rather than piling it into model callbacks.
- Database connection pool - Each Rails web worker needs its own DB connection. With 3 Puma workers × 5 threads = 15 connections needed. Set pool: 15 in database.yml or use PgBouncer.
- Sidekiq job idempotency - Sidekiq at-least-once delivery means jobs may run multiple times (worker crash). Jobs must be idempotent. Use find_or_create_by instead of create, and check before sending emails.
- Asset pipeline vs. Vite - Rails 7+ ships with import maps (no bundler) or jsbundling-rails (webpack/esbuild/Vite). For React/Vue-heavy apps, use vite-rails for the best DX.
When to Break These Rules
- Use Next.js or Nuxt instead of Rails when your team is JavaScript-first and building a heavily client-side application - Rails views add friction when the frontend is a separate SPA.
- Use FastAPI or Express when you need to expose a pure API (no server-rendered HTML) - Rails's full stack is overkill for API-only services.
Reference Files
https://guides.rubyonrails.org/https://hotwired.dev/