Skip to main content

Ruby / RoR - Interview Questions

1. What is the difference between includes, joins, and preload in Rails ActiveRecord?

  • includes: Eager loads associated records to avoid N+1 queries (uses LEFT OUTER JOIN or separate queries).
  • joins: Performs SQL INNER JOIN but does not load associated data—useful for filtering.
  • preload: Like includes, but always uses separate queries instead of joins.

Use includes when you want eager loading and potential filtering; use preload when you're sure filtering won't occur.

2. How does Rails manage database transactions, and how can you use them effectively?

Rails provides ActiveRecord::Base.transaction to wrap operations in a DB transaction. If an exception occurs, changes are rolled back.

ActiveRecord::Base.transaction do
user.save!
order.save!
end

Use this to ensure atomicity—either all operations succeed, or none do.

3. Explain how Rails handles background jobs. What tools have you used?

Rails 5+ includes ActiveJob, an abstraction over background job frameworks. Common adapters: Sidekiq, Resque, DelayedJob.

Example with Sidekiq:

class HardWorker
include Sidekiq::Worker
def perform(user_id)
UserMailer.welcome_email(User.find(user_id)).deliver_now
end
end

Use background jobs for asynchronous, non-blocking tasks—emailing, API calls, data processing.

4. What is a concern in Rails, and when should you use it?

A concern is a module used to share reusable code across models/controllers without inheritance.

# app/models/concerns/trackable.rb
module Trackable
extend ActiveSupport::Concern

included do
has_many :activities
end
end

Use concerns to extract logic that cuts across models—avoid fat models/controllers.

5. How do you optimize performance in large Rails applications?

  • Eager load associations to avoid N+1
  • Use pagination (kaminari, pagy)
  • Memoization (@memoized ||= value)
  • Caching: fragment, Russian-doll, low-level
  • Avoid unnecessary callbacks and validations
  • Use indexes on DB columns
  • Avoid heavy queries in views

6. What are service objects in Rails, and why would you use them?

Service objects encapsulate business logic outside controllers/models.

class InvoiceGenerator
def initialize(user)
@user = user
end

def call
Invoice.create(user: @user, total: calculate_total)
end
end

Use them for complex operations, fat controller/model avoidance, and testing isolation.

7. What’s the difference between before_save and before_create callbacks?

  • before_save: Runs on both create and update
  • before_create: Runs only on create

Use before_create when logic should not run during update, e.g., setting UUIDs or default roles.

8. What is strong parameters and why is it important?

Strong parameters (params.require(...).permit(...)) protect against mass assignment vulnerabilities.

params.require(:user).permit(:email, :name)

Without it, malicious users could update protected attributes like admin: true.

9. How do you handle multi-environment secrets securely in Rails?

Use Rails credentials (config/credentials.yml.enc) or ENV variables with gems like dotenv.

For multiple environments:

EDITOR="vim" bin/rails credentials:edit --environment production

Avoid committing secrets to git. Use environment-based credential stores for CI/CD.

10. Explain the asset pipeline and how it works in Rails

The asset pipeline:

  • Combines and minifies assets
  • Uses fingerprinting for cache-busting
  • Allows use of preprocessors (Sass, CoffeeScript)
  • Manifest file controls what gets compiled

Path: app/assets, lib/assets, vendor/assets

In Rails 7, asset management shifted toward import maps, ESBuild, or Webpacker.