93 Ruby on Rails Interview Questions and Answers (2026)

Blog / 93 Ruby on Rails Interview Questions and Answers (2026)
Ruby on Rails interview questions

Rails is having a moment. As more teams lean on it to ship APIs and AI/ML backends fast, interviewers expect real fluency, not buzzwords. Walk in shaky on associations, request lifecycle, or query performance and you'll lose the offer to someone who isn't.

This is your fix: 93 questions with tight, interview-ready answers and code where it counts. They're ordered Junior to Mid to Senior, so you build from fundamentals up to the deep architecture and performance questions. Work through them and you'll have an answer ready for whatever they throw.

Q1.
Explain the principle of Convention over Configuration. Give an example of how Rails uses this to speed up development.

Junior

Convention over Configuration means Rails assumes sensible defaults based on naming and structure, so you only write code where you deviate from the norm. Follow the conventions and large amounts of wiring happen automatically with zero config.

  • The principle:

    • Less boilerplate: no XML/config mapping every class to a table or route.

    • Consistency: any Rails dev can navigate any Rails app because layout is predictable.

  • Example: ActiveRecord naming:

    • A model User maps automatically to the users table (pluralized, snake_case).

    • A column id is assumed as the primary key, and user_id is the foreign-key convention for associations.

  • Other examples:

    • A UsersController#show automatically renders app/views/users/show.html.erb.

    • You override only when needed (e.g. self.table_name = "legacy_users").

Q2.
What is the difference between has_one and belongs_to? How do you decide which model holds the foreign key?

Junior

They are two halves of the same one-to-one (or one-to-many) relationship: belongs_to goes on the model that holds the foreign key, and has_one (or has_many) goes on the other side. The foreign key always lives on the belongs_to side.

  • belongs_to: Declares that this table has the _id column pointing to the owner.

  • has_one:

    • Declares the inverse: the owner expects exactly one matching record on the other table.

    • It does not add a column to this model; the key is elsewhere.

  • Deciding who holds the foreign key:

    • Ask "which record can't exist without the other / is owned by the other?": that dependent record gets belongs_to and the foreign key.

    • Example: a User has_one :profile and Profile belongs_to :user, so profiles.user_id holds the key.

  • Practical note: Only the belongs_to side can validate presence of the association easily, since it owns the key.

Q3.
What is an Active Record enum, and what problem does it solve?

Junior

An Active Record enum maps a symbolic name to an integer (or string) column value, letting you work with readable names in code while storing a compact value in the database.

  • Declaration: You declare enum status: { active: 0, archived: 1 } and Active Record persists the integer but lets you use the symbol.

  • What it solves:

    • Readability: code reads post.active! instead of post.update(status: 0).

    • Eliminates magic numbers scattered across the codebase.

  • Free helper methods: Predicates (post.active?), bang setters (post.archived!), and scopes (Post.active).

  • Caveats:

    • Prefer an explicit hash over an array so reordering values doesn't silently remap data.

    • An unknown value raises ArgumentError; string-backed enums are clearer in the DB but use more space.

ruby

class Post < ApplicationRecord enum status: { draft: 0, published: 1, archived: 2 } end post.published! # sets status post.published? # => true Post.published # scope

Q4.
What is the difference between create, new, and build when working with Active Record objects and associations?

Junior

They differ in whether the object is saved and whether it's linked to an association: new builds an unsaved object, create builds and saves it, and build is the association-aware version of new.

  • new: Instantiates an object in memory only; no SQL runs until you call save.

  • create: Does new plus save in one step and returns the object even if validation fails (use create! to raise).

  • build:

    • Called on an association (user.posts.build); like new but pre-sets the foreign key linking it to the parent.

    • For has_many it's effectively an alias of new; on the association it sets the relationship automatically.

  • Rule of thumb: Use build/new when you want to set attributes before saving; use create for a one-shot persist.

Q5.
What is the conceptual difference between render and redirect_to, and how does each affect the browser's URL and the request-response cycle?

Junior

render produces a response body in the current request, while redirect_to tells the browser to make a brand-new request to a different URL. One keeps the cycle going; the other starts a fresh one.

  • render:

    • Renders a view/template and returns it directly: a single request-response cycle.

    • The URL in the browser stays whatever was requested (it does not change).

    • Instance variables set in the action are available to the view.

  • redirect_to:

    • Sends a 3xx response with a Location header; the browser then issues a second, separate request.

    • The URL changes to the redirect target.

    • Instance variables are lost; pass data via flash or query params.

  • When to use which:

    • render to re-show a form with errors after a failed save.

    • redirect_to after a successful create/update to follow the Post-Redirect-Get pattern and avoid duplicate submissions.

  • Common gotcha: Calling both in one action raises DoubleRenderError; add return after a render/redirect.

Q6.
Explain the purpose of before_action filters. How can they be used to handle authentication or authorization?

Junior

A before_action is a controller filter that runs a method before one or more actions, making it the natural place to enforce cross-cutting concerns like authentication and authorization before any action logic runs.

  • Purpose:

    • DRY up shared setup: load a record, check a session, set defaults.

    • Scope with only: / except: to choose which actions it runs for.

  • Authentication: A filter checks whether a user is logged in; if not it can redirect_to login.

  • Authorization: A later filter verifies the logged-in user may perform this action and aborts if not.

  • Halting the chain: If a before_action renders or redirects, the action and remaining filters are skipped: this is how it blocks access.

ruby

class PostsController < ApplicationController before_action :require_login before_action :authorize_owner, only: [:edit, :update, :destroy] private def require_login redirect_to login_path unless current_user end def authorize_owner redirect_to root_path unless @post.user == current_user end end

Q7.
How do layouts work in Rails views, and what is the role of yield and content_for?

Junior

A layout is a wrapper template holding shared page structure (head, nav, footer), and the action's view is injected into it at the point marked by yield; content_for lets a view push named chunks into other regions of the layout.

  • Layouts: By default Rails uses app/views/layouts/application.html.erb; you can override per controller or per action.

  • yield:

    • Plain yield marks where the action's rendered view is inserted.

    • yield(:name) renders a named region defined elsewhere.

  • content_for:

    • In a view, content_for :name do ... end captures markup to be rendered at the matching yield(:name).

    • Common for injecting page-specific titles, sidebar content, or extra <script> tags into the layout's <head>.

erb

<!-- layout --> <head><title><%= yield(:title) %></title></head> <body><%= yield %></body> <!-- view --> <% content_for :title do %>My Page<% end %> <h1>Hello</h1>

Q8.
What is form_with, and how does it differ from the older form_for and form_tag helpers?

Junior

form_with is the unified form helper (Rails 5.1+) that replaced both form_for and form_tag. It works with both model objects and plain URLs, and defaults to remote (AJAX-driven) submission.

  • One helper for two old jobs:

    • form_for was model-bound (built fields from an object); form_tag was for plain forms without a model.

    • form_with handles both: pass model: for object-backed forms or url: for standalone ones.

  • Block uses a form builder: You access fields via the builder (e.g. f.text_field :name) consistently in both modes.

  • Remote by default: Submits via JS unless you set local: true; this pairs naturally with Turbo/Hotwire.

  • Smart URL inference: Given a model, it infers the route and HTTP verb (POST for new, PATCH for persisted).

erb

<%= form_with model: @article do |f| %> <%= f.text_field :title %> <%= f.submit %> <% end %>

Q9.
Why were Strong Parameters introduced, and what specific security vulnerability like Mass Assignment do they prevent?

Junior

Strong Parameters force you to explicitly whitelist which request attributes may be assigned to a model, preventing Mass Assignment: an attacker submitting extra form fields to set attributes you never intended (like admin: true).

  • The vulnerability they close: Mass Assignment: Model.new(params[:user]) blindly assigns every submitted key, so a crafted role=admin param could escalate privileges.

  • Why moved into the controller: Older Rails used model-level attr_accessible; Rails 4 moved filtering to the controller since that's where untrusted request data actually arrives.

  • How they work:

    • require demands a top-level key be present; permit lists the allowed attributes.

    • Passing an unpermitted params object to update/create raises ForbiddenAttributesError.

ruby

def user_params params.require(:user).permit(:name, :email) # :role is NOT permitted, so it can't be mass-assigned end

Q10.
What is the difference between flash and flash.now?

Junior

Both put a message in the flash, but flash persists to the next request (it survives a redirect), while flash.now is only available in the current request (it's used when you render directly without redirecting).

  • flash: Stored across one redirect, then cleared; use it after redirect_to (e.g. "Saved successfully").

  • flash.now: Lives only for the current render; use it after render (e.g. showing validation errors on a re-rendered form).

  • Common bug: Setting plain flash before a render leaves the message hanging into the next request, showing it twice.

ruby

if @user.save redirect_to @user, notice: "Created" # flash survives redirect else flash.now[:alert] = "Fix the errors" # only for this render render :new end

Q11.
What is the purpose of the schema.rb file, and why should you never modify it directly?

Junior

schema.rb is an auto-generated snapshot of your database's current structure: it's the canonical representation of every table, column, and index, used to set up a fresh database without replaying every migration. You never edit it by hand because Rails regenerates it from your migrations.

  • What it represents:

    • A Ruby DSL description of the schema as of the latest migration that has run.

    • Used by rails db:schema:load to build a database instantly instead of running all migrations.

  • Why it's auto-generated:

    • It is rewritten every time you run rails db:migrate, so manual edits are silently overwritten.

    • Migrations are the source of truth; schema.rb is the derived output.

  • Why commit it: Teammates and CI load it directly, guaranteeing everyone shares the same structure.

  • Caveat: database-specific features: The Ruby format can't capture triggers, stored procedures, or custom types; switch to schema_format = :sql (a structure.sql) when you need them.

Q12.
What does it mean for a Rails route to be RESTful? Explain how resources :users maps to the standard CRUD actions.

Junior

A RESTful route maps HTTP verbs and URLs to controller actions that represent operations on a resource, so the URL identifies the thing and the verb identifies what you do to it. resources :users expands into seven conventional routes covering the full CRUD lifecycle.

  • REST core idea: Resources are nouns (users); verbs (GET, POST, PATCH, DELETE) express intent rather than putting actions in the URL.

  • The seven routes from resources :users:

    1. GET /usersindex (list)

    2. GET /users/newnew (form)

    3. POST /userscreate

    4. GET /users/:idshow

    5. GET /users/:id/editedit (form)

    6. PATCH/PUT /users/:idupdate

    7. DELETE /users/:iddestroy

  • Bonus: it generates named helpers: like users_path and user_path(@user), and you can limit with only: / except:.

Q13.
Explain the difference between a 'Member' route and a 'Collection' route in a RESTful resource.

Junior

Both add custom routes to a resource, but a member route acts on a single record (it includes an :id), while a collection route acts on the resource as a whole (no :id).

  • Member route:

    • Operates on one instance; URL is /users/:id/action.

    • Example: /users/1/activate to activate a specific user.

  • Collection route:

    • Operates on the whole set; URL is /users/action with no id.

    • Example: /users/search or /users/export.

  • Rule of thumb: Need a record? member. Acting across all records? collection.

ruby

resources :users do member do post :activate # /users/:id/activate end collection do get :search # /users/search end end

Q14.
When would you use find_each instead of all.each?

Junior

Use find_each when iterating over a large table: it loads records in batches (1000 by default) instead of pulling every row into memory at once, which is what all.each does.

  • all.each loads everything: Instantiates every matching record in one query and holds it all in memory, risking bloat or crashes on big tables.

  • find_each batches:

    • Fetches a batch, yields each record, then fetches the next batch, keeping memory roughly constant.

    • Tune with batch_size:; use find_in_batches if you want the whole batch as an array.

  • Caveats:

    • It orders by primary key internally, so any custom order is overridden.

    • For small result sets, all.each is simpler and just as fast.

Q15.
Explain the difference between find, find_by, and where.

Junior

All three retrieve records, but they differ in what they look up by and what they return: find fetches by primary key and raises if missing, find_by fetches the first match for arbitrary conditions and returns nil if none, and where returns a relation of all matches.

  • find: Looks up by id (or ids); raises ActiveRecord::RecordNotFound if not found. Returns a single object.

  • find_by: Takes attribute conditions, returns the first match or nil. Equivalent to where(...).first.

  • where: Returns an ActiveRecord::Relation (possibly empty), which is lazy and chainable.

  • Choosing: Use find when a missing record is an error (e.g. controllers raising 404); use find_by when absence is acceptable; use where for collections or further chaining.

Q16.
What is the difference between save and save!? When is it appropriate to use one over the other in a production environment?

Junior

Both persist a record, but save returns true/false on success or failure, while save! raises ActiveRecord::RecordInvalid when validations fail. The choice depends on whether failure is expected and handled, or genuinely exceptional.

  • save:

    • Returns a boolean; you must check it (if @user.save) or the failure passes silently.

    • Good in controller actions where you branch on success and re-render the form on failure.

  • save!: Raises on failure, so it fails loud and fast: ideal inside transactions, background jobs, seeds, and service objects where a failure should abort everything.

  • Production guidance:

    • Use save! when a failure means a bug or broken invariant you want surfaced in error tracking.

    • Use save when failure is a normal, expected outcome (user input) you handle gracefully.

    • The dangerous pattern is calling save and ignoring its return value: data silently fails to persist.

Q17.
What is a 'database migration' in Rails, and why is it important to make them reversible?

Junior

A migration is a versioned Ruby file that describes a change to the database schema (creating tables, adding columns, indexes, etc.), letting schema changes be applied, tracked, and shared like code. Reversibility matters so you can cleanly roll back a bad change with rails db:rollback.

  • What they are:

    • Timestamped classes inheriting ActiveRecord::Migration; Rails records applied versions in schema_migrations.

    • Database-agnostic DSL (create_table, add_column, add_index) instead of raw SQL.

  • Why reversible:

    • A faulty deploy can be backed out predictably without manual SQL.

    • Most use change, where Rails infers the inverse automatically.

    • For non-invertible operations (raw SQL, dropping data), define explicit up and down methods, or raise ActiveRecord::IrreversibleMigration.

ruby

class AddPublishedToPosts < ActiveRecord::Migration[7.1] def change add_column :posts, :published, :boolean, default: false, null: false end end

Q18.
What are Active Record validations, and what are some common built-in validation helpers Rails provides?

Junior

Active Record validations are model-level rules that check a record's data before it is saved, populating errors and blocking persistence when they fail. Rails ships a set of declarative helpers you attach with validates.

  • Common built-in helpers:

    • presence: value must not be blank.

    • uniqueness: no duplicate value (queries the DB; pair with a unique index).

    • length: minimum/maximum/in character bounds.

    • numericality: must be a number, with options like greater_than, only_integer.

    • format: match a regex via with:.

    • inclusion/exclusion: value must be in (or out of) a given set.

    • confirmation: matches a _confirmation field (passwords, emails).

  • Useful options:

    • allow_nil, allow_blank, on: :create, and conditional if:/unless:.

    • Custom logic via validate methods or a validates_with validator class.

ruby

class User < ApplicationRecord validates :email, presence: true, uniqueness: true, format: { with: URI::MailTo::EMAIL_REGEXP } validates :age, numericality: { greater_than_or_equal_to: 18 } end

Q19.
What are the differences between the development, test, and production environments in Rails, and how does Rails manage configuration for each?

Junior

Rails ships with three default environments that tune the framework for different goals: development optimizes for feedback, test for isolation and speed, and production for performance and safety. Rails selects one via RAILS_ENV and loads matching configuration.

  • Development: Code reloads on each request, errors show full stack traces, eager loading and caching are off for fast iteration.

  • Test: Runs against a separate test database, often wrapping tests in transactions for isolation, with caching off and deterministic behavior.

  • Production: Eager loads all code at boot, enables caching, serves generic error pages, and assumes assets are precompiled.

  • How config is managed:

    • Shared settings live in config/application.rb; per-environment overrides live in config/environments/<env>.rb.

    • Secrets use encrypted credentials and ENV variables; the active environment comes from RAILS_ENV (defaulting to development).

Q20.
What are "Concerns" in Rails, and when should you extract logic into a Concern vs. a Service Object?

Mid

A Concern is a Ruby module (extending ActiveSupport::Concern) that mixes shared behavior into models or controllers, with clean handling of dependencies and class-level macros. Use a Concern to share stateful behavior that belongs to an object; use a Service Object to encapsulate a multi-step business process that isn't naturally one object's responsibility.

  • Reach for a Concern when:

    • Behavior is shared across models and is intrinsic to the object (e.g. Taggable, Archivable).

    • It uses class macros like has_many or scope: included do ... end makes this clean.

  • Reach for a Service Object when:

    • You're orchestrating a workflow across several models (e.g. CheckoutOrder, RegisterUser).

    • The logic has its own collaborators, transactions, or external calls and doesn't belong on one record.

  • Key distinction:

    • A Concern adds behavior TO an object via inclusion; a Service is a standalone object you call.

    • Warning: Concerns can hide complexity and still bloat the model since methods become part of it. Prefer extraction (Service/PORO) when logic is a process, not a trait.

Q21.
What is the difference between a 'Skinny Controller' and a 'Fat Model,' and why is the latter often considered a code smell in modern Rails?

Mid

"Skinny Controller, Fat Model" was advice to keep request-handling code thin and push business logic into models instead. It's a good first step away from logic-in-controllers, but blindly fattening models is now seen as a smell because models accumulate too many responsibilities and violate the Single Responsibility Principle.

  • Skinny controller:

    • Job is HTTP plumbing: parse params, invoke domain logic, choose a response (render/redirect).

    • No business rules or persistence logic inline.

  • Fat model:

    • Originally: persistence + validations + business logic on the AR model.

    • The problem: a User with 1000 lines, dozens of callbacks, and mixed concerns becomes hard to test and change.

  • Why it's a smell today:

    • Violates SRP: the model handles data AND every workflow that touches it.

    • Callback-heavy models create hidden side effects and brittle tests.

  • Modern guidance: Keep controllers skinny, but extract logic into Service Objects, form objects, query objects, and POROs rather than piling it all on the model.

Q22.
What are Rails Concerns? When would you use a Concern versus a standard Ruby module for code sharing?

Mid

A Concern is a module that includes ActiveSupport::Concern, giving you a clean way to package mixin behavior, including class-level macros and dependency management. Use a Concern (over a plain module) when your shared code needs to run class methods at inclusion time or declare dependencies on other modules.

  • What Concern adds over a plain module:

    • included do ... end: run class-level code (e.g. scope, validates, has_many) in the including class automatically.

    • class_methods do ... end: define class methods cleanly without a nested ClassMethods module and manual extend.

    • Dependency handling: if it includes another Concern, the chain is resolved correctly.

  • Use a Concern when:

    • Sharing model/controller behavior that triggers Rails macros at include time.

    • You want the standard Rails idiom that other devs recognize (in app/models/concerns).

  • Use a plain Ruby module when:

    • You only need to share simple instance methods or namespacing constants, with no class-level hooks.

    • The code is framework-agnostic (no Rails magic), keeping it lighter and more portable.

ruby

module Archivable extend ActiveSupport::Concern included do scope :archived, -> { where.not(archived_at: nil) } end def archive! update!(archived_at: Time.current) end class_methods do def archive_all! update_all(archived_at: Time.current) end end end

Q23.
What is the purpose of Active Support and how does it extend core Ruby classes for the Rails framework?

Mid

Active Support is the Rails component that provides utility classes and extensions to Ruby's core and standard library. It supplies the convenience methods (and concurrency, caching, and instrumentation tools) that the rest of Rails is built on, monkey-patching core classes so common tasks read cleanly.

  • Core class extensions: Adds methods to String, Array, Hash, Integer, etc. (e.g. "post".pluralize, 5.days.ago, hash.deep_merge).

  • Time and date handling: Time zones, TimeWithZone, and duration arithmetic that plain Ruby lacks.

  • Reusable framework utilities: ActiveSupport::Concern for clean mixins, ActiveSupport::Notifications for instrumentation, caching, and callback infrastructure.

  • How it loads: Extensions are opt-in via require "active_support/core_ext"; Rails loads them automatically so the whole framework can rely on them.

  • Tradeoff to acknowledge: It monkey-patches core classes globally, which is powerful but can surprise developers expecting pure Ruby behavior.

Q24.
Explain the difference between dependent: :destroy and dependent: :delete_all. Which one triggers Active Record callbacks?

Mid

Both options delete associated records when the parent is destroyed, but dependent: :destroy loads each child and runs its Active Record callbacks, while dependent: :delete_all issues a single bulk SQL DELETE and skips callbacks entirely.

  • dependent: :destroy:

    • Instantiates each associated record and calls its destroy, firing before_destroy/after_destroy callbacks and cascading its own dependents.

    • Use when children have important callbacks or nested dependents that must run (cleanup, further cascades).

    • Cost: slower, N+1 deletes for large sets.

  • dependent: :delete_all:

    • Runs one efficient SQL statement; no objects loaded, no callbacks, no cascade.

    • Use for performance when children are "dumb" and have no callbacks or further associations to clean up.

    • Risk: orphaned grandchildren and skipped side effects.

  • Which triggers callbacks: Only :destroy triggers Active Record callbacks; :delete_all bypasses them.

Q25.
What is a counter_cache and what problem does it solve? What is the risk of manual database updates when using one?

Mid

A counter_cache stores the number of associated records in a column on the parent so you can read a count without running a COUNT query every time. It solves the performance problem of repeatedly counting children (especially in lists where each row triggers its own count).

  • How it works:

    • You add a column like comments_count and declare belongs_to :post, counter_cache: true on the child.

    • Active Record auto-increments/decrements it on create and destroy of the child.

  • Problem solved: Avoids N+1 COUNT queries (e.g. showing comment totals next to many posts).

  • The risk with manual DB updates:

    • The counter only stays correct when records change through Active Record callbacks.

    • Bulk operations that skip callbacks (delete_all, update_all, raw SQL, import) leave the cached count stale and wrong.

    • Fix drift with Post.reset_counters(id, :comments).

Q26.
What is the difference between has_many :through and has_and_belongs_to_many, and when would you choose one over the other?

Mid

Both model many-to-many relationships, but has_many :through uses an explicit join model (a real model and table), while has_and_belongs_to_many (HABTM) uses a bare join table with no model. Prefer has_many :through in almost all cases; reach for HABTM only for the simplest pure-link case.

  • has_and_belongs_to_many:

    • Just a join table (e.g. projects_users) with the two foreign keys, no model class.

    • No place for extra columns, validations, or callbacks on the relationship itself.

  • has_many :through:

    • Goes through a real join model (e.g. Membership) that can hold its own attributes (role, joined_at), validations, and callbacks.

    • Lets you treat the relationship as a first-class entity and query it directly.

  • When to choose which:

    • Use HABTM only when the link truly carries no data and never will.

    • Use has_many :through whenever the join might gain attributes, needs validations, or should be reasoned about on its own (which is most real apps).

ruby

class User < ApplicationRecord has_many :memberships has_many :projects, through: :memberships end class Membership < ApplicationRecord belongs_to :user belongs_to :project # join model can hold extra data: # role:string, joined_at:datetime end

Q27.
When would you use a before_action filter, and what are the risks of overusing them in a large controller?

Mid

Use a before_action when several actions share the same preparatory or guard logic, but overusing them creates hidden control flow that makes a controller hard to read and debug.

  • Good uses:

    • Loading a resource for several actions (set_post).

    • Authentication and authorization guards.

    • Setting shared defaults or locale.

  • Risks of overuse:

    • Hidden state: an action depends on instance variables set far away, hurting readability.

    • Order dependence: filters run in declaration order, so a subtle reorder can break behavior.

    • Conditional sprawl: many only:/except: options become hard to trace.

  • Mitigation: Keep filters few and well-named; push complex logic into service objects or policy classes (e.g. Pundit).

Q28.
What is the difference between before_action, around_action, and after_action?

Mid

All three are action callbacks, differing in when they run relative to the action: before_action runs before, after_action runs after, and around_action wraps the action with logic on both sides via yield.

  • before_action: Runs before the action; can halt the chain by rendering or redirecting (used for auth, loading records).

  • after_action: Runs after the action, but only if it wasn't halted; used for logging or cleanup. Can't stop the action since it already ran.

  • around_action:

    • Wraps the action; you call yield to execute it, with code before and after.

    • Useful for things needing setup and teardown around the action: timing, transactions, exception handling.

ruby

around_action :with_timing def with_timing start = Time.now yield # runs the action ensure Rails.logger.info("took #{Time.now - start}s") end

Q29.
What is the purpose of respond_to in a controller, and how does Rails handle content negotiation for different formats like HTML and JSON?

Mid

respond_to lets one action serve multiple representations of the same resource (HTML, JSON, XML), branching on the format the client requested so Rails can perform content negotiation.

  • How the format is chosen:

    • Rails inspects the URL extension (.json) or the Accept header to determine the requested MIME type.

    • It then runs the matching block inside respond_to.

  • The block:

    • Each format.html / format.json defines how to respond for that type.

    • If no format matches, Rails raises ActionController::UnknownFormat.

  • Defaults: With no block, HTML renders the matching template; JSON can be returned simply with render json:.

ruby

def show @post = Post.find(params[:id]) respond_to do |format| format.html # renders show.html.erb format.json { render json: @post } end end

Q30.
What is the difference between using Rails Fixtures and a library like FactoryBot? What are the trade-offs regarding test speed and maintainability?

Mid

Fixtures are static YAML records loaded once into the test database; FactoryBot builds objects on demand in Ruby. Fixtures are faster but brittle and global; factories are slower but expressive and locally explicit.

  • Fixtures:

    • Loaded into the DB once per test run, so they're very fast.

    • Downside: a shared global dataset; a change to one fixture can silently break unrelated tests, and the relevant data isn't visible in the test itself.

    • They bypass model validations and callbacks (inserted as raw SQL).

  • FactoryBot:

    • Each test builds exactly the objects it needs, so intent is explicit and local.

    • Supports traits, sequences, and associations for flexible variations.

    • Downside: slower (validations/callbacks run on each create) and can hide N+1-style object explosions if associations cascade.

  • Trade-off summary:

    • Speed favors fixtures; readability and maintainability favor factories.

    • Use build_stubbed or build instead of create to recover speed when you don't need DB persistence.

Q31.
In a modern Rails app, what is the difference between a System Test and an Integration Test, and which would you use to test a Hotwire-heavy feature?

Mid

An Integration Test exercises HTTP requests through the full stack without a browser; a System Test drives a real (or headless) browser so JavaScript actually runs. For a Hotwire-heavy feature you need a System Test, because Turbo Streams and Stimulus only execute in a browser.

  • Integration Test (ActionDispatch::IntegrationTest):

    • Makes requests like get/post and asserts on responses, redirects, and rendered HTML.

    • Fast and no browser, but JavaScript never runs.

  • System Test (ApplicationSystemTestCase):

    • Uses Capybara plus a real browser driver (e.g. headless Chrome via Selenium).

    • Tests behavior as a user: clicking, filling forms, and seeing JS-driven updates.

    • Slower and flakier, but the only way to verify real interactivity.

  • For Hotwire: Turbo Frames, Turbo Streams, and Stimulus controllers depend on the browser executing JS, so an Integration Test would miss the actual update; choose a System Test.

Q32.
What is Action Cable, and how does it enable WebSocket functionality in a Rails application?

Mid

Action Cable is Rails' framework for real-time features, integrating WebSockets with the rest of your Rails app so you can push data to clients without polling. It manages persistent connections and organizes messaging through channels and a pub/sub backend.

  • Core concepts:

    • Connection: one per WebSocket client, where you authenticate the user.

    • Channel: like a controller; clients subscribe and receive broadcasts (e.g. a chat room).

    • Broadcasting: the server pushes a message to all subscribers of a stream.

  • How it works under the hood:

    • Holds a long-lived WebSocket connection instead of HTTP request/response.

    • Uses a pub/sub adapter to fan out messages across processes: traditionally Redis, now Solid Cable (database-backed) by default in Rails 8.

  • Typical use: Often paired with Turbo Streams to push live HTML updates to the browser with minimal JavaScript.

Q33.
What is Active Storage, and how does it manage file uploads and attachments to cloud services?

Mid

Active Storage is Rails' built-in framework for attaching files (images, PDFs, etc.) to Active Record models and storing them in local disk or cloud services like S3, GCS, or Azure. It abstracts the storage backend so your model code stays the same regardless of where files live.

  • Declaring attachments: has_one_attached for a single file, has_many_attached for collections.

  • How it tracks files: Metadata lives in two tables, active_storage_blobs (the file's identity/key) and active_storage_attachments (the join to your model); the bytes live in the storage service.

  • Pluggable backends: Configured in config/storage.yml; switch from disk in dev to S3 in production without changing model code.

  • Extra features: Image variants/transformations (via image_processing), and direct uploads from the browser straight to the cloud to offload the server.

Q34.
What is the difference between namespace and scope in Rails routing, and when would you use each?

Mid

Both group routes under a path prefix, but namespace prefixes the URL, the controller module, and the route helper names all at once, while scope lets you control each of those independently. Use namespace when everything lines up; use scope when you need finer control.

  • namespace :admin:

    • URL /admin/users, controller Admin::UsersController, helper admin_users_path.

    • Ideal for a self-contained admin section where path, module, and naming should all match.

  • scope is flexible:

    • scope path: '/admin': change the URL only, leaving controllers and helpers unprefixed.

    • scope module: 'admin': route to controllers in the Admin:: module without changing the URL.

    • scope as: 'admin': prefix only the helper names.

  • Mental model: namespace = scope with path, module, and as all set together; reach for scope to decouple them.

Q35.
What is the N+1 query problem in Active Record, and how do you identify and solve it using includes, preload, or eager_load?

Mid

The N+1 problem is when you load a collection with one query, then trigger a separate query for each record's association: 1 query for the parent plus N for the children. You fix it by eager loading the associations up front.

  • What it looks like: Iterating Post.all and calling post.author inside the loop fires one query per post.

  • How to identify it:

    • Watch the development log for repeated near-identical queries.

    • Use the bullet gem, which flags N+1s and unused eager loads automatically.

  • The fix: eager load:

    • includes: lets Rails decide between two strategies (separate queries or a join).

    • preload: always uses separate queries, one per association.

    • eager_load: always uses a single LEFT OUTER JOIN.

ruby

# N+1: 1 + N queries Post.all.each { |p| puts p.author.name } # Fixed: 2 queries total Post.includes(:author).each { |p| puts p.author.name }

Q36.
What is an Active Record scope? How does it differ from a class method, and why is it preferred for filtering data?

Mid

A scope is a named, chainable query defined on a model with scope, used to encapsulate common query logic. Functionally it is almost identical to a class method, but it is more concise for filtering and guarantees a relation is returned.

  • Definition: scope :published, -> { where(published: true) } creates a reusable query fragment.

  • Chainable and composable: Scopes return an ActiveRecord::Relation, so they chain: Post.published.recent.

  • Difference from a class method:

    • A scope always returns a relation, even if the lambda returns nil (it falls back to all), so chaining never breaks.

    • A class method returning nil breaks the chain with a NoMethodError.

  • When to prefer a class method: Complex conditional logic reads better as a class method; trivial filters read better as scopes.

Q37.
Explain the difference between joins and includes. When would you use one over the other?

Mid

joins performs a SQL INNER JOIN to filter records by associated data without loading those associations, while includes eager loads associations into memory to prevent N+1 queries. Use joins to filter, includes to use the associated data.

  • joins:

    • Builds an INNER JOIN; it does not load the associated objects, so accessing them later still triggers queries.

    • Ideal for filtering: User.joins(:orders).where(orders: { paid: true }).

  • includes:

    • Eager loads the associated records so iterating over them adds no extra queries.

    • Ideal when you will read the association: rendering each user's orders.

  • Rule of thumb: Only filtering by the association, use joins; reading the association data, use includes; doing both, use includes with references.

Q38.
What is default_scope, and why is it often considered dangerous in a Rails application?

Mid

default_scope sets a query condition applied automatically to every query on a model. It's considered dangerous because that implicit condition silently affects all reads, creates, and sometimes writes, leading to surprising bugs that are hard to trace.

  • What it does: default_scope { where(active: true) } injects that condition into every query unless explicitly unscoped.

  • Why it's risky:

    • It's invisible: developers forget it exists and waste time debugging missing records.

    • It leaks into new and create: Model.new inherits the scope's attributes (e.g. sets active: true).

    • It can override order unexpectedly and complicate unscoped usage across associations.

  • Safer alternatives: Use explicit named scopes (scope :active) so the filtering is visible at the call site.

Q39.
What is the difference between pluck, select, and map when retrieving data from the database?

Mid

They operate at different layers: pluck pulls specific columns directly into a plain Ruby array (no model objects), select limits which columns the SQL returns but still builds model instances, and map is pure Ruby that transforms already-loaded objects.

  • pluck:

    • Runs SELECT column and returns raw values as an array, skipping model instantiation: fast and memory-light.

    • User.pluck(:email) gives ["a@x.com", ...].

  • select: Limits the columns fetched but returns ActiveRecord objects (partial records); accessing an unselected attribute raises MissingAttributeError.

  • map: A Ruby Enumerable method: it loads all records, then iterates in memory, so User.all.map(&:email) instantiates every object first (wasteful vs. pluck).

  • Rule of thumb: Need only raw column values, use pluck; need lightweight model objects, use select; need to transform records you already have loaded, use map.

Q40.
Why are Active Record query results lazily evaluated, and when does an Active Record relation actually execute the SQL query?

Mid

Active Record relations are lazy so you can chain conditions, ordering, and limits without paying for multiple queries: the SQL is built up and only sent to the database when you actually need the data.

  • Why lazy:

    • Methods like where, order, and limit return an ActiveRecord::Relation, not records, so you can compose them and run one optimal query.

    • This avoids loading rows you might further filter, and enables query reuse and scoping.

  • When it executes:

    • On enumeration or materialization: each, map, to_a, first, last.

    • On terminal/aggregate methods: count, sum, exists?, pluck, find_by.

    • When inspected in console (because inspect loads records to display them).

  • Caching: Once loaded, the relation caches its results; re-enumerating reuses them. Call reload to force a fresh query.

  • Trap: Laziness can hide N+1 queries; combine with includes to eager load associations.

Q41.
How does Rails protect against Cross-Site Request Forgery (CSRF)? Explain the role of the authenticity token.

Mid

Rails defends against CSRF by requiring every non-GET request to carry an unpredictable, per-session authenticity token that an attacker's forged request can't know, so requests that don't include the valid token are rejected.

  • The attack: A malicious site tricks a logged-in user's browser into submitting a state-changing request using the user's existing session cookie.

  • The authenticity token:

    • Rails embeds a token (tied to the session) in forms via form_with/form_tag and in a <meta> tag (csrf_meta_tags) for JS.

    • On unsafe requests (POST, PUT, PATCH, DELETE) Rails compares the submitted token to the session; a mismatch raises ActionController::InvalidAuthenticityToken.

    • The token is masked per request to prevent BREACH-style attacks but still validates.

  • How it's enabled:

    • protect_from_forgery is on by default; forgery_protection_strategy can reset the session (default) or raise an exception.

    • GET requests are exempt because they should be safe/idempotent.

  • APIs: Token-based APIs that don't use cookie sessions typically skip CSRF, since the attack relies on automatically sent cookies.

Q42.
What is the purpose of the credentials.yml.enc file, and how does Rails manage secrets across different environments?

Mid

credentials.yml.enc is an encrypted YAML file that stores secrets (API keys, tokens) safely in version control; Rails decrypts it at runtime using a master key that is never committed.

  • How encryption works:

    • The file is encrypted with the key in config/master.key (or the RAILS_MASTER_KEY env var).

    • master.key is gitignored; only the encrypted file is committed, so secrets stay safe in the repo.

  • Editing and reading: Edit via rails credentials:edit; access in code with Rails.application.credentials.some_key.

  • Per-environment secrets:

    • Rails 6+ supports environment-scoped credentials: rails credentials:edit --environment production creates config/credentials/production.yml.enc with its own production.key.

    • In production you usually supply the key via RAILS_MASTER_KEY rather than shipping the file.

  • Why over plain ENV: Secrets are versioned, encrypted, and structured, removing the need to manage many separate environment variables.

Q43.
How does Rails handle session storage by default, and what are the trade-offs of using CookieStore versus a database-backed session store?

Mid

By default Rails stores the session in an encrypted, signed cookie (CookieStore): all session data lives in the client's browser. A database (or cache) store instead keeps the data server-side and puts only a session ID in the cookie.

  • CookieStore (default):

    • Pros: no server-side storage, fast (no DB lookup), scales easily across servers since there's no shared state.

    • Cons: limited to ~4KB, all data travels on every request, and you can't truly invalidate a session server-side (only expire/rotate keys).

    • Data is encrypted and signed so users can't read or tamper with it, but it's still client-held.

  • Database-backed store (ActiveRecordStore):

    • Pros: stores large amounts of data, keeps it off the client, and lets you revoke sessions server-side.

    • Cons: a DB read/write per request, requires cleanup of stale rows, and adds a shared dependency to scale.

  • Rule of thumb: Keep small, non-sensitive identifiers in the default cookie store; switch to a DB or cache_store (Redis) when you need large or server-revocable sessions.

Q44.
How does Rails protect against SQL Injection when using the Active Record query interface?

Mid

Active Record protects against SQL injection by parameterizing queries: when you pass conditions as hashes or as placeholders with separate values, the values are escaped/bound by the database adapter instead of being concatenated into the SQL string.

  • Safe forms:

    • Hash conditions: where(email: params[:email]).

    • Placeholder/array conditions: where("email = ?", params[:email]) or named where("email = :e", e: params[:email]).

    • These send user input as bound parameters, so it's treated as data, never executable SQL.

  • The dangerous form: String interpolation builds raw SQL: where("email = '#{params[:email]}'") lets an attacker inject SQL.

  • Watch the edges: Methods that take raw SQL fragments (order, select, group, pluck) can't parameterize column/SQL names: validate against an allowlist.

ruby

# Safe: value is bound User.where("name = ?", params[:name]) # Unsafe: interpolated into SQL User.where("name = '#{params[:name]}'") # Allowlist for unparameterizable inputs col = %w[name created_at].include?(params[:sort]) ? params[:sort] : "name" User.order(col)

Q45.
How does the allow_browser method in Rails 7.2/8 work, and what are the trade-offs of enforcing modern browser versions at the framework level?

Mid

allow_browser is a controller-level guard (Rails 7.2+) that blocks requests from browsers older than versions you specify, by parsing the request's User-Agent and rendering a 406 "not acceptable" page to unsupported clients.

  • How it works:

    • Declared in a controller: allow_browser versions: :modern uses a built-in baseline of browsers supporting modern features (WebP, ES6 modules, CSS nesting, etc.).

    • You can set explicit minimums: allow_browser versions: { safari: 16, chrome: 119 }.

    • It's a before_action, so it supports only:/except:; unknown agents are allowed by default.

  • Why do it at the framework level: Lets you safely ship modern HTML/CSS/JS without polyfills or fallbacks for ancient browsers.

  • Trade-offs:

    • User-Agent sniffing is unreliable: strings can be spoofed, frozen, or missing, so detection isn't perfect.

    • Risks excluding legitimate users (corporate/locked-down browsers, accessibility tools); the block is coarse rather than feature-based.

    • Feature detection in JS is more accurate but runs client-side; allow_browser trades precision for a simple, central server-side gate.

Q46.
How do signed and encrypted cookies work in Rails, and why would you use them over plain cookies?

Mid

Signed cookies attach a tamper-proof signature so the server can verify the value wasn't altered, while encrypted cookies go further and make the value unreadable to the client; both use the app's secret key base, so users can't forge trusted data.

  • Plain cookies: cookies[:x] stores readable, editable text: never trust it for anything security-sensitive.

  • Signed cookies:

    • cookies.signed[:x] appends an HMAC signature; the value is still readable but tampering invalidates it.

    • Use when the value can be public but must be trustworthy (e.g. a user ID).

  • Encrypted cookies:

    • cookies.encrypted[:x] both encrypts and authenticates: the client can neither read nor alter it.

    • Use for confidential data; this is what backs the default session CookieStore.

  • Mechanics:

    • Keys are derived from secret_key_base; rotating it invalidates existing signed/encrypted cookies.

    • Note they're still client-stored: prefer short expirations and don't put irrevocable secrets in them.

ruby

cookies.signed[:user_id] = current_user.id # readable, tamper-proof cookies.encrypted[:token] = secret_token # unreadable + tamper-proof cookies.encrypted[:token] # => decrypted value, or nil if tampered

Q47.
How do database transactions work in Rails, and what happens if an exception is raised inside a transaction block?

Mid

A transaction wraps multiple statements into one atomic unit: either all succeed or none do. In Rails, ActiveRecord::Base.transaction opens a transaction and, if any exception propagates out of the block, the whole thing is rolled back.

  • Atomicity by exception: If the block raises, Rails issues a ROLLBACK and re-raises the exception; if it returns normally, it COMMITs.

  • The special case: ActiveRecord::Rollback: Raising it triggers a rollback but is swallowed, so the transaction call returns nil instead of propagating the error.

  • Bang methods auto-raise: Use save!/create! inside transactions so a validation failure raises and rolls back; plain save just returns false and the transaction still commits.

  • In-memory state is not reverted: Rollback undoes the DB, but Ruby object attributes keep their changed values unless you reload.

ruby

ActiveRecord::Base.transaction do account.withdraw!(100) # save! raises on failure recipient.deposit!(100) # if this raises, the withdraw is rolled back too end

Q48.
Explain the difference between database-level constraints and Active Record validations. Why are both necessary?

Mid

Active Record validations run in Ruby before a record hits the database, while database constraints are enforced by the database engine itself. You need both because validations give friendly errors but can be bypassed, and constraints guarantee integrity no matter what writes the data.

  • Active Record validations:

    • Live in the model (validates :email, presence: true), produce user-facing error messages, and run on save.

    • Bypassed by update_column, raw SQL, insert_all, other apps, or concurrent requests.

  • Database constraints:

    • NOT NULL, unique indexes, foreign keys, check constraints: enforced for every write, always.

    • The only reliable defense against race conditions (e.g. two requests inserting the same unique email simultaneously).

  • Why both:

    • Validations for UX and rich error messages; constraints for true data integrity as a safety net.

    • Pair a uniqueness validation with a unique index: the validation handles the common case, the index catches the race.

Q49.
What is the difference between update, update_attribute, and update_column, and how do they interact with validations and callbacks?

Mid

They differ in how much of the persistence machinery (validations, callbacks, timestamps) they run: update runs everything, update_attribute skips validations but fires callbacks, and update_column bypasses both and goes straight to SQL.

  • update (and update!):

    • Assigns attributes, runs validations, fires callbacks, updates updated_at, and saves.

    • Returns true/false; the bang version raises on invalid records. This is the default safe choice.

  • update_attribute:

    • Skips validations but still runs callbacks and touches updated_at.

    • Can save an invalid record: dangerous if you rely on validations for integrity.

  • update_column / update_columns:

    • Issues a direct UPDATE, skipping validations, callbacks, and updated_at (unless you set it explicitly).

    • Fast and side-effect-free: good for migrations, counters, or breaking callback loops, but easy to corrupt data with.

  • Rule of thumb: Prefer update; reach for the others only when you deliberately want to skip part of the lifecycle and understand the consequences.

Q50.
When should you use a View Partial versus a View Helper, and what are the performance implications of overusing partials?

Mid

Use a partial when you are reusing or organizing markup (HTML structure), and a helper when you are computing or formatting a value used inside markup. Partials are heavier because each render involves template lookup and a new rendering context, so overusing them, especially in loops, hurts performance.

  • View Partial: chunks of view:

    • Best for reusable or large blocks of HTML (a card, a form, a list item).

    • Renders through the template engine and gets its own local variable scope.

  • View Helper: a Ruby method:

    • Best for logic and formatting: building a CSS class, formatting currency, conditionally returning text.

    • Cheap to call and easy to unit test in isolation.

  • Performance of overusing partials:

    • Each render has overhead; rendering a partial per row in a large collection multiplies it.

    • Mitigate with collection rendering (render partial: 'row', collection: @rows) which is optimized, and with fragment caching.

  • Rule of thumb: Repeated markup, use a partial; repeated logic, use a helper.

Q51.
If you were reviewing a Pull Request and saw a complex database query inside a View, why would you flag it, and where would you suggest moving it?

Mid

I'd flag it because it violates separation of concerns: views should display data, not fetch it. A query in the view also tends to trigger N+1 problems, makes the code untestable, and re-runs on every render including cached scenarios.

  • Why it's a problem:

    • Breaks MVC: business/data logic leaks into the presentation layer.

    • N+1 queries: a query inside a loop in the view hits the DB once per iteration.

    • Hard to test and cache: you can't unit-test a query buried in ERB, and fragment caching may mask or duplicate it.

  • Where to move it:

    • Into the controller as an instance variable, ideally via a model scope (@posts = Post.published.includes(:author)).

    • Use includes to eager-load associations and kill N+1.

    • For complex shaping, push it into the model, a query object, or a presenter/decorator.

Q52.
What is the difference between low-level caching and fragment caching, and when would you use Rails.cache.fetch?

Mid

Fragment caching stores rendered view markup, while low-level caching stores arbitrary Ruby values (query results, computed numbers, API responses). Rails.cache.fetch is the workhorse for low-level caching: read a key, or compute and store it if missing.

  • Fragment caching:

    • Caches a chunk of rendered HTML via the cache helper in views.

    • Keyed on a model and its timestamp, expiring automatically when the record changes.

  • Low-level caching:

    • Caches data, not markup: anything serializable.

    • You manage the key and expiration yourself.

  • Rails.cache.fetch:

    • Returns the cached value if present, otherwise runs the block, stores the result, and returns it.

    • Use it for expensive computations or external calls; add expires_in for time-based invalidation.

ruby

stats = Rails.cache.fetch("dashboard/stats", expires_in: 1.hour) do expensive_aggregation_query # only runs on a cache miss end

Q53.
How does internationalization (I18n) work in Rails, and how do you manage translations and locales?

Mid

I18n in Rails is provided by the i18n gem, which looks up translation keys in locale files for the current locale and substitutes them into your views. You externalize all user-facing text into YAML files keyed by locale and fetch them with t (and localize dates/numbers with l).

  • Locale files:

    • Stored in config/locales/*.yml, one tree per language (en.yml, fr.yml).

    • Look up keys with t('hello'); pass variables for interpolation and counts for pluralization.

  • Setting the current locale:

    • I18n.locale defaults to I18n.default_locale; set it per request from params, subdomain, or the Accept-Language header.

    • Use an around_action with I18n.with_locale so it resets safely after each request.

  • Helpful conventions:

    • "Lazy" lookup: t('.title') in a view resolves the key scoped to that view's path.

    • localize (l) formats dates, times, and numbers per locale.

ruby

# config/locales/en.yml en: greeting: "Hello, %{name}!" # in a view <%= t('greeting', name: @user.name) %>

Q54.
What is Active Job, and why does Rails provide an abstraction layer for background processing instead of using Sidekiq or Resque directly?

Mid

Active Job is Rails' framework for declaring and running background jobs through a uniform API, independent of the queue backend behind it. Rails provides the abstraction so your application code stays decoupled from any single library, letting you swap Sidekiq, Resque, or others without rewriting jobs.

  • What it gives you:

    • A common job class (ApplicationJob) with perform_later / perform_now.

    • Built-in features: retries, callbacks, queue naming, and GlobalID serialization of Active Record arguments.

  • Why an abstraction layer:

    • Portability: switch backends by changing config.active_job.queue_adapter, not your job code.

    • Integration: framework features like ActionMailer's deliver_later rely on a single shared interface.

    • Onboarding: one consistent API regardless of which queue the team chooses.

  • The trade-off:

    • It's a thin wrapper; backend-specific features (Sidekiq batches, unique jobs) may require talking to the library directly.

    • You still need a real adapter in production: the default async adapter is in-process and loses jobs on restart.

ruby

class WelcomeEmailJob < ApplicationJob queue_as :default def perform(user) UserMailer.welcome(user).deliver_now end end WelcomeEmailJob.perform_later(user) # enqueued on whatever adapter is configured

Q55.
What is Action Mailer, and how does Rails handle sending emails synchronously versus asynchronously?

Mid

Action Mailer is Rails' framework for composing and delivering email, structured like a controller: mailer classes define methods that set up variables and render view templates. Rails can send the message immediately or push delivery into a background job.

  • Structure: A mailer inherits from ApplicationMailer; each method calls mail(to:, subject:) and renders matching HTML/text templates.

  • Synchronous delivery: deliver_now sends in the current thread, blocking the request until the SMTP server responds.

  • Asynchronous delivery: deliver_later enqueues an Active Job (ActionMailer::MailDeliveryJob) so a worker sends it, keeping requests fast and resilient to mail-server slowness.

  • Why prefer async:

    • Email I/O is slow and can fail; offloading avoids blocking users and gives automatic retries via the job queue.

    • Caveat: deliver_later needs a working queue adapter and worker; in tests the test adapter captures jobs instead.

ruby

# Synchronous UserMailer.welcome(user).deliver_now # Asynchronous (enqueues a background job) UserMailer.welcome(user).deliver_later

Q56.
How does the Rails Console interact with 'Sandbox' mode, and why is this useful for debugging production data safely?

Mid

Sandbox mode runs the console inside a database transaction that is rolled back when you exit, so any changes you make are discarded automatically. This lets you inspect and experiment with real data without permanently altering it.

  • How to start it: Launch with rails console --sandbox; Rails opens a transaction at boot and rolls it back on exit.

  • Why it's safe for production data: You can run creates, updates, and destroys to reproduce a bug, then quit and leave the database untouched.

  • Limitations to know:

    • Only protects the database wrapped in the transaction: side effects like sent emails, queued jobs, or external API calls are NOT rolled back.

    • It holds an open transaction the whole session, which can cause locking or bloat if left running on a busy production database.

  • Use case: Debugging or verifying data-mutating logic against real records when you want zero risk of permanent change.

Q57.
Explain the difference between a Turbo Frame and a Turbo Stream. When would you use a Stream instead of just replacing a Frame?

Mid

A Turbo Frame is a region of the page that updates itself: a request returns a matching <turbo-frame> and Turbo swaps just that frame. A Turbo Stream is a server-sent set of instructions that can update many elements anywhere on the page in one response, by ID, with explicit actions.

  • Turbo Frame: scoped, single-target:

    • Wraps content in <turbo-frame id="...">; navigation/forms inside it only replace that one frame.

    • Declarative and simple: one frame in, one frame out, same DOM location.

  • Turbo Stream: multiple targets, explicit actions:

    • Carries actions like append, prepend, replace, update, remove targeting elements by ID.

    • Can be delivered over a form response or pushed via WebSocket (Action Cable) for live updates.

  • Use a Stream instead of a Frame when:

    • One action must change several disconnected parts (e.g. add a row to a list AND clear the form AND update a counter).

    • You need to append/prepend rather than replace.

    • You want real-time broadcasts to many clients without a page request.

erb

<%# Stream: do several things in one response %> <turbo-stream action="append" target="messages"> <template><%= render @message %></template> </turbo-stream> <turbo-stream action="update" target="new_message"> <template><%= render "form", message: Message.new %></template> </turbo-stream>

Q58.
What is Hotwire, and how does it differ from the traditional Single Page Application (SPA) approach like React or Vue?

Mid

Hotwire (HTML Over The Wire) is Rails' default front-end approach: the server renders HTML and sends HTML fragments over the wire, while small JS libraries (Turbo and Stimulus) handle swapping and sprinkles of interactivity. SPAs instead ship a large JS app that renders the UI client-side and talks to the server via JSON APIs.

  • Where rendering happens:

    • Hotwire: server renders HTML; the browser just swaps it in.

    • SPA: client renders from JSON; the server is a data API.

  • The pieces of Hotwire:

    • Turbo Drive (fast navigation), Turbo Frames (scoped updates), Turbo Streams (targeted/real-time updates).

    • Stimulus: a modest JS framework for behavior tied to existing HTML.

  • Tradeoffs vs SPA:

    • Hotwire keeps logic in one language/codebase, less JS, no duplicate validation/state.

    • SPAs offer richer client state and offline/native-like UX but more complexity, build tooling, and API surface.

  • Rule of thumb: Hotwire fits CRUD-heavy, server-driven apps; SPAs fit highly interactive, client-state-heavy UIs.

Q59.
Explain the lifecycle of a Stimulus controller. What are the connect() and disconnect() methods used for?

Mid

A Stimulus controller is connected to the DOM via a data-controller attribute. Stimulus watches the DOM and calls lifecycle callbacks as matching elements appear and disappear, so your JS automatically initializes and tears down without manual wiring.

  • Lifecycle callbacks (in order):

    1. initialize(): called once when the controller is first instantiated.

    2. connect(): called every time the controller's element is attached to the DOM.

    3. disconnect(): called whenever the element leaves the DOM.

  • connect() is for setup: Start timers, open connections, instantiate third-party widgets, add listeners on non-controlled elements.

  • disconnect() is for cleanup: Clear intervals, remove external listeners, destroy widgets: prevents leaks, especially with Turbo swapping DOM in/out.

  • Why it matters with Turbo: Turbo replaces page content without a full reload, so the same controller can connect and disconnect many times; idempotent setup/teardown is essential.

javascript

import { Controller } from "@hotwired/stimulus" export default class extends Controller { connect() { this.timer = setInterval(() => this.refresh(), 1000) } disconnect() { clearInterval(this.timer) // avoid leaks when the element is removed } }

Q60.
What is the difference between Turbo Drive, Turbo Frames, and Turbo Streams?

Mid

They are three layers of Turbo, from broadest to most surgical: Drive accelerates full-page navigation, Frames scope updates to a region, and Streams deliver targeted, multi-element (and real-time) changes.

  • Turbo Drive:

    • Intercepts link clicks and form submits, fetches the new page, and swaps the <body> without a full reload (keeps <head> assets).

    • Makes the whole app feel SPA-fast with zero custom code.

  • Turbo Frames:

    • Scope navigation to a <turbo-frame>: only that region updates, the rest of the page stays put.

    • Great for inline editing, tabs, lazy-loaded sections.

  • Turbo Streams:

    • Send HTML fragments with actions (append, replace, remove...) to update multiple elements by ID.

    • Can be pushed over WebSockets for live, multi-client updates.

  • Progression: Drive (page), Frame (region), Stream (any number of elements, possibly real-time).

Q61.
When would you use a Stimulus controller instead of a Turbo Frame?

Mid

Use a Turbo Frame when you want to update server-rendered HTML for a region; use a Stimulus controller when you need client-side behavior that doesn't require a round-trip to the server. They solve different problems and often work together.

  • Reach for a Turbo Frame when:

    • The change is really new HTML from the server (inline edit, pagination, lazy load).

    • You'd otherwise be writing JS just to fetch and inject markup.

  • Reach for a Stimulus controller when:

    • Behavior is purely client-side: toggle a class, open a modal, debounce input, copy to clipboard, init a date picker.

    • No server data is needed, so a network request would be wasteful.

  • They complement, not compete: Common pattern: Stimulus enhances UI and triggers actions; Turbo Frames/Streams handle the server-rendered results.

  • Heuristic: "new HTML from the server" implies Turbo; "interactive behavior in the browser" implies Stimulus.

Q62.
What is the role of Stimulus in the Hotwire ecosystem, and how does it help maintain the Rails way of handling JavaScript?

Mid

Stimulus is Hotwire's lightweight JavaScript framework for adding behavior to HTML that already exists on the page. Rather than owning rendering, it connects JS to server-rendered markup through data attributes, keeping JavaScript minimal, declarative, and aligned with the Rails philosophy of HTML-first apps.

  • Its role: behavior, not rendering: Turbo handles navigation and HTML swapping; Stimulus adds the interactive sprinkles (toggles, menus, form helpers).

  • Built around HTML attributes:

    • data-controller attaches a controller; data-action wires events; data-*-target references elements.

    • The HTML is the source of truth, so server-rendered or Turbo-swapped markup just works.

  • Why it fits the Rails way:

    • No client-side templating or duplicated state: logic stays on the server, JS stays thin.

    • Controllers are small, reusable, and survive Turbo navigation via connect()/disconnect().

Q63.
What is the difference between Turbo Drive and Turbo Frames, and when would you use a Frame instead of a full-page Drive navigation?

Mid

Turbo Drive replaces the whole page body on navigation (a fast full-page swap), while a Turbo Frame scopes navigation to a single region. Use a Frame when you want only part of the page to change instead of the entire body.

  • Turbo Drive (whole page):

    • Intercepts links/forms, fetches the response, and swaps the <body> while preserving <head> assets.

    • Updates the URL and history: it behaves like normal navigation, just faster.

  • Turbo Frame (a region):

    • A request inside a <turbo-frame> returns the matching frame, and only that frame is replaced.

    • By default it does not change the URL (unless you set target="_top" or promote it).

  • When to use a Frame over Drive:

    • Inline editing where the rest of the page should stay intact.

    • Independent regions: tabs, paginated lists, lazy-loaded sidebars.

    • You want to avoid re-rendering and re-scrolling the whole page.

Q64.
How do Turbo Streams enable real-time updates without writing custom JavaScript, and how do they interact with Action Cable?

Mid

Turbo Streams deliver fragments of HTML wrapped in <turbo-stream> tags that carry an action (append, prepend, replace, etc.) and a target DOM id; Turbo's client JS applies them automatically, so you broadcast HTML instead of writing JavaScript. Over Action Cable, model broadcasts push those same fragments to subscribers in real time.

  • A Turbo Stream is HTML plus an action and target: Each element names an action (append, prepend, replace, update, remove) and a target DOM id; Turbo mutates the page accordingly.

  • No custom JS needed: Turbo intercepts form submissions and stream responses and applies them; you only render partials server-side.

  • Real-time via Action Cable:

    • A view subscribes with turbo_stream_from @post, which opens a WebSocket channel backed by Action Cable.

    • Models broadcast with broadcast_append_to/broadcast_replace_to, pushing rendered HTML to every subscriber on that stream.

  • Two delivery paths share one format: Direct HTTP responses (format.turbo_stream) update the page for the acting user; Action Cable broadcasts fan out to everyone else.

ruby

# Broadcast on create class Comment < ApplicationRecord belongs_to :post after_create_commit -> { broadcast_append_to post } end # In the view <%= turbo_stream_from @post %> <div id="comments"><%= render @post.comments %></div>

Q65.
What is the purpose of 'Import Maps' and how do they eliminate the need for Node.js/Webpack in Rails?

Mid

Import Maps let you import JavaScript modules by bare name (e.g. import "controllers") directly in the browser, mapping those names to versioned URLs. Because modern browsers support ES modules natively, you ship your JS unbundled and skip the Node-based build step entirely.

  • What an import map is: A JSON <script type="importmap"> block telling the browser where each module name resolves (a CDN URL or an app asset).

  • Managed by the importmap-rails gem: You declare pins in config/importmap.rb with pin, and bin/importmap pin stimulus adds dependencies.

  • Why Node/Webpack become unnecessary:

    • No bundling, transpiling, or node_modules: the browser fetches modules individually, so there is no JS build pipeline to install or run.

    • HTTP/2 multiplexing makes serving many small files practical without concatenation.

  • Trade-off: You cannot transpile JSX/TypeScript or use packages that assume a bundler; you depend on browser-ready ESM builds.

Q66.
What is the difference between Sprockets and the newer Propshaft/Importmaps approach in Rails 7/8?

Mid

Sprockets is the classic asset pipeline that concatenates, transpiles, and bundles assets; Propshaft plus Import Maps is the Rails 7/8 "no-build" approach that only digests and serves files, leaving bundling to the browser. The difference is how much processing the pipeline does.

  • Sprockets does heavy lifting:

    • Concatenates files via //= require directives, compiles CoffeeScript/SCSS, minifies, and fingerprints.

    • Maintains a manifest and a compiled output tree; more configuration and complexity.

  • Propshaft is minimal:

    • It only adds digests (fingerprints) to filenames and serves assets as-is; no concatenation or transpilation.

    • It rewrites asset references (e.g. in CSS) to digested URLs but does nothing else.

  • Import Maps handle JS module resolution: Replaces Sprockets' JS bundling by mapping module names to digested files Propshaft serves.

  • Net effect: Sprockets = build-time bundler; Propshaft + Import Maps = serve-time digesting plus browser-native modules, far simpler but no transpilation.

Q67.
What are the advantages of the 'No-Build' asset pipeline (Importmaps/Propshaft) over traditional bundlers like Webpack or Esbuild?

Mid

The no-build pipeline removes the entire JavaScript toolchain: no Node, no node_modules, no bundler config to maintain. You gain simplicity, faster deploys, and fewer dependencies, at the cost of build-time features like transpilation and tree-shaking.

  • No build step: No Node install, no npm install, no waiting on a bundle to compile during development or deploy.

  • Fewer dependencies and less churn: You avoid the constant upgrade treadmill and security audits of a large node_modules tree.

  • Faster, simpler deploys: Propshaft just digests files; no asset compilation phase to slow CI/CD.

  • Better caching granularity: Unbundled modules are cached individually, so changing one file does not invalidate one giant bundle (works well over HTTP/2).

  • Honest trade-offs: No tree-shaking or minification, no JSX/TypeScript, and packages requiring a bundler won't work.

Q68.
Explain the difference between using Import Maps and a traditional JS bundling tool like esbuild. When would Import Maps be insufficient for a Rails application?

Mid

Import Maps ship JavaScript as native ES modules resolved by the browser with no build step, while esbuild bundles, transpiles, and minifies your JS into optimized output. Import Maps become insufficient once you need transformation (JSX, TypeScript) or heavy front-end frameworks that assume a bundler.

  • Import Maps: no build, browser resolves modules: Pin bare names to URLs; the browser fetches modules directly, ideal for Hotwire/Stimulus and light JS.

  • esbuild: a real build step: Bundles many files into few, transpiles modern/JSX/TypeScript syntax, minifies, and tree-shakes; requires Node and jsbundling-rails.

  • When Import Maps fall short:

    • You need compilation: JSX, TypeScript, or SCSS pipelines.

    • Heavy SPA frameworks (React, Vue) or packages with no browser-ready ESM build.

    • You want tree-shaking/minification to shrink large dependency graphs, or must support browsers lacking ESM/import-map support.

  • Rule of thumb: Modest, browser-ready JS: Import Maps. Significant front-end build needs: reach for esbuild.

Q69.
What are Rails Engines, and when would you choose to build a feature as an Engine rather than a standard part of the main app?

Senior

A Rails Engine is a miniature, self-contained Rails application that plugs into a host app: it can have its own models, controllers, views, routes, and migrations, namespaced so it doesn't collide with the host. You build a feature as an Engine when you want it to be reusable, isolatable, or shippable as a gem.

  • What it is technically:

    • Rails itself is an Engine; a mountable Engine inherits from Rails::Engine and is mounted in routes with mount MyEngine::Engine, at: "/blog".

    • Isolated namespacing via isolate_namespace keeps its classes and routes separate from the host.

  • When to choose an Engine:

    • Reuse across multiple apps: package an admin panel, auth, or CMS as a gem (e.g. Devise, Spree).

    • Modular monolith: split a large app into bounded domains while staying in one process and one deploy.

    • Clear seam: the feature has its own UI, data, and routes that can live behind a mount point.

  • When NOT to:

    • A single feature used once: the namespacing and packaging overhead isn't worth it.

    • You need true process/scaling isolation: that points to a microservice, not an Engine.

Q70.
What is Rack, and how does Rails interact with it? Can you give an example of a common middleware used in the Rails stack?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q71.
Explain the Rails Request/Response lifecycle, tracing a request from the Rack middleware stack through the router to the controller and view.

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q72.
What are the tradeoffs of using a Rails Engine versus a separate microservice?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q73.
Explain the 'Vanilla Rails' philosophy. Why might a senior developer advocate for staying within the framework's defaults rather than adding specialized gems?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q74.
What are the clues that a Rails application is becoming 'monolithic' in a negative way, and how would you begin to decouple it?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q75.
When would you use Polymorphic Associations versus Single Table Inheritance (STI)? What are the tradeoffs of each?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q76.
Explain the Solid trifecta introduced in Rails 8. Why is the framework moving away from Redis as a default dependency?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q77.
When would you implement horizontal sharding in a Rails app using native multi-database support?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q78.
Explain how Rails handles database connection pooling in a multi-threaded environment.

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q79.
What is Kamal, and how does it change the deployment philosophy for Rails applications compared to Heroku or Capistrano?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q80.
What does the phrase 'one database, one process model' mean in the context of Rails 8, and how does it simplify deployment?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q81.
What is the difference between includes, preload, and eager_load? In what specific scenario would eager_load be preferred over preload?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q82.
What are Active Record callbacks, and why are they often considered a code smell in large Rails applications? What are the alternatives?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q83.
Explain the Active Record callback lifecycle. Why are after_commit callbacks often safer than after_save for external service calls?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q84.
How do nested transactions work in Rails, and what happens to the parent transaction if a child transaction block raises an error?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q85.
What is the difference between optimistic and pessimistic locking in Active Record, and when would you use each?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q86.
Explain 'Russian Doll Caching.' How does the touch: true option on associations facilitate efficient cache expiration?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q87.
How does HTTP caching work in Rails using ETags and conditional GET requests with fresh_when and stale?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q88.
What is Solid Queue, and how does it differ from Redis-backed adapters like Sidekiq?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q89.
Why is it important for background jobs to be idempotent, and how do you ensure a job doesn't cause side effects if retried?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q90.
How does the Zeitwerk autoloader work compared to the old 'classic' loader, and why is file naming convention so critical for Zeitwerk?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q91.
Why does the Rails console sometimes behave differently than the Rails server in production (e.g., database connection pooling or readonly modes)?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q92.
What is 'Turbo Morphing' in Turbo 8, and how does it improve the user experience compared to standard Turbo Drive navigations?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q93.
What are the tradeoffs of using Hotwire vs. a SPA framework like React?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.