Rails interviews test your understanding of convention over configuration, ActiveRecord internals, RESTful design, and how to build maintainable Ruby applications. This guide covers the 50 most common questions — with concise answers and working code examples.
Quick reference
| Topic | Most asked questions |
|---|---|
| Ruby fundamentals | Symbols, blocks, procs, lambdas, modules |
| MVC & Rails basics | Convention over configuration, request lifecycle |
| ActiveRecord | Associations, scopes, N+1, migrations |
| Routing | RESTful routes, nested resources, concerns |
| Performance | Caching, background jobs, query optimization |
| Security | CSRF, mass assignment, SQL injection |
| Testing | RSpec, FactoryBot, Capybara |
| Rails 7/8 | Turbo, Stimulus, import maps, Hotwire |
Ruby fundamentals
1. What is the difference between a symbol and a string in Ruby?
Symbols are immutable, interned identifiers — the same symbol always has the same object ID, making them ideal for hash keys and named constants. Strings are mutable objects with unique object IDs.
:name.object_id == :name.object_id # true — same object in memory
"name".object_id == "name".object_id # false — different objects
# Common use: hash keys
user = { name: "Ana", role: :admin }
# Symbols are garbage collected since Ruby 2.2 (dynamic symbols)
2. Explain blocks, procs, and lambdas — and their key differences.
| Feature | Block | Proc | Lambda |
|---|---|---|---|
| Object? | No | Yes (Proc.new) | Yes (lambda/->) |
| Stored? | No | Yes | Yes |
| Return behaviour | Returns from enclosing method | Returns from enclosing method | Returns from lambda only |
| Argument checking | Loose | Loose | Strict |
# Block — passed to a method, not a standalone object
[1, 2, 3].each { |n| puts n }
# Proc — storable, loose argument handling
double = Proc.new { |x| x * 2 }
double.call(5) # 10
# Lambda — strict argument checking, own return scope
square = ->(x) { x ** 2 }
square.call(4) # 16
3. What are Ruby modules used for?
Modules serve two roles: namespacing (grouping constants/classes) and mixins (sharing behaviour without inheritance).
# Namespace
module Payments
class Invoice; end
class Receipt; end
end
# Mixin
module Timestampable
def created_at_human
created_at.strftime("%B %d, %Y")
end
end
class Order < ApplicationRecord
include Timestampable
end
4. What is the difference between include, extend, and prepend?
| Method | Adds module methods as... | Lookup order |
|---|---|---|
include |
Instance methods | After class in ancestor chain |
extend |
Class methods | After singleton class |
prepend |
Instance methods | Before class (can override) |
module Greetable
def greet = "Hello, I am #{name}"
end
class Person
include Greetable # Person instances get #greet
extend Greetable # Person class gets .greet
end
5. What does yield do in Ruby?
yield calls the block passed to a method. block_given? checks if one was supplied.
def measure
start = Time.now
result = yield # executes the block
puts "Took: #{Time.now - start}s"
result
end
measure { sleep(0.1); 42 } # prints elapsed time, returns 42
MVC & Rails basics
6. What does "convention over configuration" mean in Rails?
Rails makes decisions for you — file names map to class names, table names map to model names, directory structure is predefined — so you write less configuration. Deviating is possible but requires explicit setup.
# Convention: model User → table users, file app/models/user.rb
# Convention: controller UsersController → file app/controllers/users_controller.rb
# Convention: views in app/views/users/
7. Describe the Rails request lifecycle.
- Router matches URL to a controller action
- Middleware stack processes the request (cookies, sessions, logging)
- Controller action runs — calls models, sets instance variables
- View renders (ERB/Haml) using instance variables
- Response is sent back through the middleware stack
8. What is the asset pipeline and how has it changed in Rails 7?
The asset pipeline (Sprockets) bundles CSS and JS. In Rails 7 it was largely replaced:
| Rails version | JS bundling | CSS |
|---|---|---|
| ≤ 6 | Webpacker / Sprockets | Sprockets |
| 7 | Import maps (default) or jsbundling-rails | cssbundling-rails / Propshaft |
| 8 | Same + Solid adapters | Same |
Import maps serve unbundled ES modules — no Node.js build step required for simple apps.
9. Explain Rails' MVC and where business logic belongs.
| Layer | Responsibility | Avoid |
|---|---|---|
| Model | Data, validations, associations, domain logic | HTTP/view concerns |
| View | Presentation only | Database queries, business logic |
| Controller | Orchestration — calls models, selects views | Business logic (fat controller anti-pattern) |
| Service Object | Complex business operations (not built-in) | — |
Thin controllers + fat models (or service objects) is the Rails way.
10. What are Rails concerns?
Concerns are modules that extract shared model or controller behaviour, living in app/models/concerns/ or app/controllers/concerns/.
# app/models/concerns/searchable.rb
module Searchable
extend ActiveSupport::Concern
included do
scope :search, ->(q) { where("name ILIKE ?", "%#{q}%") }
end
def highlight(term)
name.gsub(term, "<mark>#{term}</mark>")
end
end
class Product < ApplicationRecord
include Searchable
end
ActiveRecord
11. What are the ActiveRecord association types?
| Association | SQL equivalent | Use when |
|---|---|---|
belongs_to |
Foreign key on this table | Child model |
has_one |
Foreign key on the other table | One-to-one |
has_many |
Foreign key on the other table | One-to-many |
has_many :through |
Join table (explicit model) | Many-to-many with data on join |
has_and_belongs_to_many |
Pure join table | Many-to-many, no join model |
has_one :through |
Join table | One-to-one via join |
class Author < ApplicationRecord
has_many :books
has_many :genres, through: :books
end
class Book < ApplicationRecord
belongs_to :author
belongs_to :genre
end
12. What is the N+1 query problem and how do you solve it in Rails?
N+1 occurs when you execute one query to fetch N records, then N more queries for associated data.
# N+1 — 1 + N queries
posts = Post.all
posts.each { |p| puts p.author.name }
# Fix: eager loading
posts = Post.includes(:author) # 2 queries total
posts = Post.eager_load(:author) # 1 JOIN query
posts = Post.preload(:author) # 2 queries (like includes, no JOIN)
Use the bullet gem to detect N+1s automatically in development.
13. Explain ActiveRecord scopes.
Scopes are reusable, chainable query fragments defined on a model.
class Article < ApplicationRecord
scope :published, -> { where(published: true) }
scope :recent, -> { order(created_at: :desc) }
scope :by_author, ->(id) { where(author_id: id) }
end
# Chainable
Article.published.recent.by_author(3)
# SELECT * FROM articles WHERE published = true ORDER BY created_at DESC AND author_id = 3
14. What is the difference between destroy and delete in ActiveRecord?
| Method | Callbacks | Associations |
|---|---|---|
destroy |
Runs before_destroy, after_destroy |
Handles dependent: :destroy |
delete |
No callbacks | No cascade — raw SQL DELETE |
destroy_all |
Callbacks for each record | — |
delete_all |
No callbacks | Single SQL query |
15. How do Rails migrations work?
Migrations are version-controlled database schema changes stored in db/migrate/.
rails generate migration AddEmailToUsers email:string:index
class AddEmailToUsers < ActiveRecord::Migration[7.2]
def change
add_column :users, :email, :string
add_index :users, :email, unique: true
end
end
rails db:migrate runs pending migrations; rails db:rollback reverses the last one. The db/schema.rb always reflects the current state.
16. What is counter_cache and when should you use it?
counter_cache keeps a cached count column updated automatically, avoiding COUNT(*) queries.
class Comment < ApplicationRecord
belongs_to :post, counter_cache: true # increments posts.comments_count
end
# Migration needed:
add_column :posts, :comments_count, :integer, default: 0, null: false
# Usage — no extra query
post.comments_count # reads the cached integer
17. Explain validates vs database constraints.
| Model validation | Database constraint | |
|---|---|---|
| Location | Ruby code | Database level |
| Enforced by | Rails before save | DB always |
| Error display | model.errors |
ActiveRecord::StatementInvalid |
| Bypass risk | Yes (raw SQL, update_column) |
No |
| Best practice | Both — validate in model AND add DB constraint |
# Both
class User < ApplicationRecord
validates :email, presence: true, uniqueness: true
end
# Migration
add_index :users, :email, unique: true
18. What are callbacks in ActiveRecord and what are the risks?
Callbacks run at specific points in a model's lifecycle: before_validation, after_create, before_destroy, etc.
class Order < ApplicationRecord
after_create :send_confirmation_email
private
def send_confirmation_email
OrderMailer.confirmation(self).deliver_later
end
end
Risks: Callbacks create hidden side effects, make testing harder, and can cause unintended actions when records are created in tests. Consider service objects for complex logic.
Routing
19. What does resources generate in Rails routing?
resources :articles
# GET /articles → index
# GET /articles/new → new
# POST /articles → create
# GET /articles/:id → show
# GET /articles/:id/edit → edit
# PATCH /articles/:id → update
# DELETE /articles/:id → destroy
20. How do you define nested resources and when should you avoid deep nesting?
resources :authors do
resources :books # /authors/:author_id/books/:id
end
Rails recommends max 1 level of nesting. For deeper relationships, use shallow: or only nest the collection routes.
resources :authors do
resources :books, shallow: true
# shallow generates /books/:id instead of /authors/:author_id/books/:id
end
21. What is the difference between member and collection routes?
resources :photos do
member { get :preview } # /photos/:id/preview (single record)
collection { get :search } # /photos/search (no ID)
end
22. What are route constraints?
Constraints restrict which requests match a route — by format, subdomain, or custom logic.
constraints(subdomain: "api") do
namespace :api do
resources :users
end
end
get '/users/:id', to: 'users#show', constraints: { id: /\d+/ }
Controllers & Views
23. What is strong parameters and why is it needed?
Strong parameters prevent mass assignment vulnerabilities by requiring explicit whitelisting of permitted attributes.
class UsersController < ApplicationController
def create
@user = User.new(user_params)
# ...
end
private
def user_params
params.require(:user).permit(:name, :email, :password)
# :admin, :role are NOT permitted — cannot be set via form
end
end
Without this, a malicious user could POST user[admin]=true.
24. Explain the before_action filter.
before_action runs a method before specified controller actions — common for authentication, loading shared resources, setting locale.
class ArticlesController < ApplicationController
before_action :authenticate_user!
before_action :set_article, only: [:show, :edit, :update, :destroy]
private
def set_article
@article = Article.find(params[:id])
end
end
25. What are Rails helpers and decorators (Draper)?
Helpers are modules for view-level utility methods available in templates. Decorators (Draper gem) wrap model objects with presentation logic.
# Helper — global, in any view
module ApplicationHelper
def format_price(cents)
number_to_currency(cents / 100.0)
end
end
# Draper decorator — model-specific presentation
class ProductDecorator < Draper::Decorator
delegate_all
def display_price
h.number_to_currency(model.price_cents / 100.0)
end
end
Performance
26. How does Rails caching work?
Rails provides multiple caching layers:
| Type | What it caches | How |
|---|---|---|
| Page caching | Full HTTP response | Nginx serves static file |
| Action caching | Controller action output | Middleware |
| Fragment caching | Parts of views | cache do ... end in ERB |
| Low-level caching | Arbitrary data | Rails.cache.fetch |
| HTTP caching | ETags / Last-Modified | fresh_when / stale? |
# Fragment cache in a view
<% cache @product do %>
<%= render @product %>
<% end %>
# Low-level
user_count = Rails.cache.fetch("user_count", expires_in: 1.hour) do
User.count
end
27. What is Russian Doll caching?
Nested fragment caches where each cache key includes the parent's timestamp — a change to a child automatically busts the parent.
# Parent cache key includes child updated_at
<% cache @post do %>
<%= @post.title %>
<% cache @post.comments do %>
<%= render @post.comments %>
<% end %>
<% end %>
28. How do you run background jobs in Rails?
Active Job provides a unified interface; adapters (Sidekiq, Solid Queue, GoodJob) do the actual processing.
class WelcomeEmailJob < ApplicationJob
queue_as :default
def perform(user_id)
user = User.find(user_id)
UserMailer.welcome(user).deliver_now
end
end
# Enqueue
WelcomeEmailJob.perform_later(user.id)
WelcomeEmailJob.set(wait: 1.hour).perform_later(user.id)
Rails 8 ships Solid Queue as the default — uses the database as a queue, no Redis required for simple setups.
29. How do you detect and fix slow queries in Rails?
# Development: log slow queries
# config/environments/development.rb
config.log_level = :debug # All SQL logged
# bullet gem for N+1 detection
# rack-mini-profiler for request profiling
# In console
User.where(active: true).explain # show query plan
# Fix: add index
add_index :users, :active
add_index :orders, [:user_id, :created_at] # composite
30. What is connection pooling in Rails?
Rails maintains a pool of database connections (default: 5 per process) to avoid the overhead of creating a new connection per request.
# config/database.yml
production:
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
checkout_timeout: 5
With Puma (multiple threads), set pool equal to RAILS_MAX_THREADS.
Security
31. How does Rails protect against CSRF?
Rails includes an authenticity token in forms and verifies it on non-GET requests. The protect_from_forgery method (included in ApplicationController by default) raises ActionController::InvalidAuthenticityToken if the token is missing or invalid.
# Automatically added to forms by form_with / form_for
<input type="hidden" name="authenticity_token" value="..." />
# For API controllers (token-based auth)
class ApiController < ActionController::API
# protect_from_forgery not included in ActionController::API
end
32. What is SQL injection and how does Rails prevent it?
ActiveRecord uses parameterized queries by default. String interpolation in WHERE clauses is dangerous.
# VULNERABLE — never do this
User.where("name = '#{params[:name]}'")
# Safe — parameterized
User.where(name: params[:name])
User.where("name = ?", params[:name])
User.where("name = :name", name: params[:name])
33. What are permitted/forbidden attributes (mass assignment)?
See question 23. In addition: use attr_readonly for truly immutable attributes and avoid update_columns (bypasses validations and callbacks).
34. How do you store secrets in Rails?
Rails provides credentials encrypted with a master key:
rails credentials:edit # opens encrypted credentials.yml.enc
# Inside credentials
database_password: super_secret
stripe:
secret_key: sk_live_...
# Access
Rails.application.credentials.stripe[:secret_key]
Rails.application.credentials.database_password
The master key lives in config/master.key (not committed) or the RAILS_MASTER_KEY env var.
Testing
35. What testing frameworks are used with Rails?
| Framework | Role |
|---|---|
| RSpec | Describe/it BDD test syntax (most popular) |
| Minitest | Built-in Rails test framework |
| FactoryBot | Test data factories (replaces fixtures) |
| Faker | Fake data generation |
| Capybara | Integration / system tests (browser simulation) |
| WebMock / VCR | Stub HTTP requests |
| SimpleCov | Test coverage |
36. Show a basic RSpec model spec.
# spec/models/user_spec.rb
require "rails_helper"
RSpec.describe User, type: :model do
describe "validations" do
it { is_expected.to validate_presence_of(:email) }
it { is_expected.to validate_uniqueness_of(:email).case_insensitive }
end
describe "associations" do
it { is_expected.to have_many(:posts).dependent(:destroy) }
end
describe "#full_name" do
it "joins first and last name" do
user = build(:user, first_name: "Ana", last_name: "Lopes")
expect(user.full_name).to eq("Ana Lopes")
end
end
end
37. What is a FactoryBot factory and how does it differ from fixtures?
# spec/factories/users.rb
FactoryBot.define do
factory :user do
sequence(:email) { |n| "user#{n}@example.com" }
first_name { Faker::Name.first_name }
last_name { Faker::Name.last_name }
password { "password123" }
trait :admin do
role { :admin }
end
end
end
# Usage
user = create(:user) # persisted
admin = create(:user, :admin) # with trait
guest = build(:user) # not persisted
Factories are code (flexible, composable); fixtures are static YAML files.
38. How do you write a request spec (integration test)?
# spec/requests/articles_spec.rb
RSpec.describe "Articles", type: :request do
let(:user) { create(:user) }
describe "GET /articles" do
it "returns a list of articles" do
create_list(:article, 3, user: user)
get articles_path
expect(response).to have_http_status(:ok)
expect(response.body).to include("articles")
end
end
describe "POST /articles" do
context "with valid params" do
it "creates an article" do
sign_in user
expect {
post articles_path, params: { article: { title: "Hello", body: "World" } }
}.to change(Article, :count).by(1)
expect(response).to redirect_to(article_path(Article.last))
end
end
end
end
Rails 7 / 8 features
39. What is Hotwire (Turbo + Stimulus)?
Hotwire is Rails 7's default frontend approach — HTML-over-the-wire instead of JSON + heavy JS framework.
| Component | Purpose |
|---|---|
| Turbo Drive | AJAX page navigation without full reload |
| Turbo Frames | Update isolated page regions |
| Turbo Streams | Server-pushed partial updates (via WebSocket or SSE) |
| Stimulus | Lightweight JS controllers for sprinkles of behaviour |
<%# Turbo Frame — only this section reloads %>
<%= turbo_frame_tag "comment_form" do %>
<%= render "comments/form", post: @post %>
<% end %>
40. What is Action Cable?
Action Cable integrates WebSockets into Rails — used for real-time features: chat, notifications, live counters.
# app/channels/chat_channel.rb
class ChatChannel < ApplicationCable::Channel
def subscribed
stream_from "chat_#{params[:room]}"
end
def speak(data)
ActionCable.server.broadcast("chat_#{params[:room]}", message: data["message"])
end
end
41. What's new in Rails 8?
| Feature | Description |
|---|---|
| Solid Queue | Database-backed job queue (default, no Redis) |
| Solid Cache | Database-backed cache store |
| Solid Cable | Database-backed Action Cable adapter |
| Authentication generator | rails generate authentication — session-based auth out of the box |
| Kamal 2 | Deployment to bare VPS via Docker |
| Asset improvements | Propshaft as default for simple apps |
42. What are import maps?
Import maps (default in Rails 7+) allow using ES modules in browsers without a JavaScript bundler — the browser resolves bare module specifiers via a JSON map.
<script type="importmap">
{
"imports": {
"@hotwired/turbo-rails": "/assets/turbo.js",
"stimulus": "/assets/stimulus.js"
}
}
</script>
No Webpack, no Node.js build step needed for simple apps.
Architecture & patterns
43. What are service objects and when should you use them?
Service objects encapsulate complex business operations that don't belong in models or controllers.
# app/services/user_registration_service.rb
class UserRegistrationService
def initialize(params)
@params = params
end
def call
ActiveRecord::Base.transaction do
user = User.create!(@params)
WelcomeEmailJob.perform_later(user.id)
SubscriptionService.new(user).create_trial!
user
end
end
end
# Controller
def create
user = UserRegistrationService.new(user_params).call
redirect_to user, notice: "Welcome!"
rescue ActiveRecord::RecordInvalid => e
render :new, status: :unprocessable_entity
end
44. What is STI (Single Table Inheritance)?
STI stores multiple model classes in one database table with a type column.
# One table: vehicles (type, speed, capacity, ...)
class Vehicle < ApplicationRecord; end
class Car < Vehicle; end
class Truck < Vehicle; end
class Motorcycle < Vehicle; end
Car.create!(speed: 200)
# INSERT INTO vehicles (type, speed) VALUES ('Car', 200)
Use STI when subclasses share most columns. Use separate tables (polymorphic associations or separate models) when they differ significantly.
45. Explain polymorphic associations.
A polymorphic association lets one model belong to multiple other models via a single association.
class Comment < ApplicationRecord
belongs_to :commentable, polymorphic: true
end
class Article < ApplicationRecord
has_many :comments, as: :commentable
end
class Video < ApplicationRecord
has_many :comments, as: :commentable
end
# Migration
create_table :comments do |t|
t.text :body
t.references :commentable, polymorphic: true # commentable_type + commentable_id
end
46. What is the decorator pattern in Rails context?
The decorator (often using the Draper gem or plain Ruby objects) separates presentation logic from domain logic.
class UserDecorator < SimpleDelegator
def display_name
[first_name, last_name].compact.join(" ").presence || email
end
def avatar_url
gravatar_hash = Digest::MD5.hexdigest(email.downcase)
"https://www.gravatar.com/avatar/#{gravatar_hash}"
end
end
decorated = UserDecorator.new(user)
decorated.display_name # delegates to user for unknown methods
Common interview scenarios
47. How would you design a multi-tenant Rails app?
Two main approaches:
| Approach | How | Pros / Cons |
|---|---|---|
| Shared schema | tenant_id on every table; global scope via default_scope or acts_as_tenant |
Simpler, less overhead; data isolation is logic-level |
| Separate schemas (PostgreSQL) | One schema per tenant; Apartment gem switches schemas per request |
Strong isolation; more complex migrations |
# Shared schema with acts_as_tenant
class ApplicationController < ActionController::Base
set_current_tenant_through_filter
before_action :set_tenant
def set_tenant
current_tenant = Account.find_by(subdomain: request.subdomain)
set_current_tenant(current_tenant)
end
end
48. How would you add authentication to a Rails app?
| Option | Description |
|---|---|
| Rails 8 generator | rails generate authentication — built-in, session-based |
| Devise | Full-featured gem: registration, confirmation, 2FA, omniauth |
| Rodauth | More secure, Ruby idiomatic, less Rails-magic |
| JWT (API) | Stateless — use devise-jwt or custom before_action |
# Rails 8 — generates User, Session, Password models + controllers
rails generate authentication
rails db:migrate
49. How do you handle file uploads in Rails?
# Active Storage — built-in since Rails 5.2
class User < ApplicationRecord
has_one_attached :avatar
has_many_attached :documents
end
# Controller
def update
@user.update(user_params)
# params[:user][:avatar] is automatically handled
end
# View
<%= image_tag @user.avatar if @user.avatar.attached? %>
Files can be stored locally, on S3 (via activestorage-s3), or GCS. Use Direct Upload for large files.
50. What are common Rails anti-patterns?
| Anti-pattern | Problem | Fix |
|---|---|---|
| Fat controller | Business logic in controllers | Move to service objects / models |
| Fat model | God model with 2000+ lines | Extract concerns, service objects, query objects |
| N+1 queries | Hidden in views | includes/eager_load + bullet gem |
| Callbacks for side effects | Hidden coupling, hard to test | Service objects |
update_column / save(validate: false) |
Bypasses validations | Understand when appropriate; audit usage |
| Rendering JSON in controllers manually | Maintenance burden | Jbuilder / serializers (blueprinter) |
| Time-based tests | Flaky | travel_to / freeze_time in ActiveSupport |
| Long-running synchronous jobs | Request timeout | perform_later via Active Job |
Common mistakes
| Mistake | Why it's wrong | Correct approach |
|---|---|---|
User.find in a loop |
N queries | Use where(id: ids) to batch-fetch |
Using default_scope |
Global scope causes surprising behaviour everywhere | Explicit named scopes |
| Business logic in views | Untestable, violates SRP | Helpers or decorators |
| Not using transactions | Partial data on failure | ActiveRecord::Base.transaction |
rescue Exception |
Catches SignalException, SystemExit |
rescue StandardError |
| Exposing raw IDs in URLs | Enumerable, predicts resource IDs | UUIDs or hashid |
| Synchronous email sending | Blocks requests | deliver_later |
Rails vs other frameworks
| Feature | Ruby on Rails | Django (Python) | Laravel (PHP) | Spring Boot (Java) |
|---|---|---|---|---|
| Philosophy | Convention over config | Explicit is better | Convention + config | Annotations-heavy |
| ORM | ActiveRecord | Django ORM | Eloquent | JPA / Hibernate |
| Migrations | Built-in | Built-in | Built-in | Flyway / Liquibase |
| Background jobs | Active Job + Sidekiq | Celery | Queue / Horizon | Spring Batch |
| Admin panel | ActiveAdmin / Administrate | Django Admin | Nova / Filament | — |
| API support | ActionController::API |
DRF | Sanctum / Passport | Spring MVC |
| Asset handling | Sprockets / Import Maps | WhiteNoise | Vite/Mix | Spring Resources |
| Learning curve | Medium (Ruby + conventions) | Medium | Low-medium | High |
FAQ
Q: Is Ruby on Rails still worth learning in 2025?
Yes. Rails powers large-scale apps (Shopify, GitHub, Basecamp, Airbnb historically). Its developer productivity is unmatched for CRUD apps, and Rails 8 with Hotwire removes the need for a separate frontend framework in many cases.
Q: What's the difference between find and find_by?find takes an ID (or array of IDs) and raises ActiveRecord::RecordNotFound if not found. find_by takes conditions and returns nil if not found — use it when the record may not exist.
Q: How does Rails autoloading work?
Rails uses Zeitwerk (since Rails 6) for constant autoloading — file names must match class names exactly (app/models/user.rb → User). Files are loaded on demand; eager_load! in production loads everything upfront.
Q: What is the difference between render and redirect_to?render sends a response immediately (renders a view without a new request). redirect_to sends an HTTP 302/301 and the browser makes a new GET request. Use redirect_to after successful mutations (PRG pattern) to prevent double-form-submission.
Q: What is touch in ActiveRecord?touch updates the updated_at timestamp of a record (or specified columns), which is used to bust associated cache keys in Russian Doll caching.
Q: How do you upgrade a Rails app to a new major version?
- Update the Rails version in
Gemfileincrementally (e.g., 6.0 → 6.1 → 7.0 → 7.1) - Run
rails app:updateto update config files - Fix deprecation warnings one version at a time
- Update gems (
bundle update) and check compatibility - Run full test suite after each step