Skip to content

Latest commit

 

History

History
2472 lines (2009 loc) · 107 KB

File metadata and controls

2472 lines (2009 loc) · 107 KB

Ruby on Rails Technical Interview Questions:

Basic

1. What is MVC?

MVC stands for Model-View-Controller. It is a design pattern used in Rails to separate concerns in an application:

  • Model: Represents the data and business logic of the application. It interacts with the database to retrieve and store information.
  • View: The presentation layer that displays the data to the user. It is typically HTML or JSON for web apps.
  • Controller: Acts as an intermediary between the Model and View. It processes user input, calls the necessary model methods, and renders the appropriate view.

Example:

# Model
class Post < ApplicationRecord
  validates :title, presence: true
end

# Controller
class PostsController < ApplicationController
  def show
    @post = Post.find(params[:id])
  end
end

# View (show.html.erb)
<h1><%= @post.title %></h1>
<p><%= @post.body %></p>

2. What is ActiveRecord?

ActiveRecord is the Object-Relational Mapping (ORM) layer in Rails that facilitates communication between the application and the database. It maps database tables to Ruby classes, allowing you to interact with the database using Ruby objects.

ActiveRecord automatically handles CRUD operations. It allows you to query, insert, update, and delete database records without needing to write raw SQL. Example:

# Finding a record
user = User.find(1)

# Creating a new record
user = User.create(name: "John", email: "john@example.com")

# Updating a record
user.update(name: "John Doe")

# Deleting a record
user.destroy

3. What are callbacks in Rails?

Callbacks in Rails are methods that get called at certain points of an object's lifecycle. They allow you to hook into and modify the behavior of ActiveRecord objects before or after certain events, such as saving, updating, or destroying records.

Common Callbacks: before_save, after_save before_create, after_create before_update, after_update before_destroy, after_destroy Example:


class Post < ApplicationRecord
  before_save :set_default_title

  private

  def set_default_title
    self.title = "Untitled" if title.blank?
  end
end

4. What is mass assignment?

Mass assignment occurs when you assign values to multiple attributes of an object at once, typically using the update or create methods. This is a feature in Rails that lets you assign values to several attributes in a single step.

Mass assignment vulnerability occurs when an attacker can update attributes that they shouldn't be allowed to, such as sensitive fields.

Example of mass assignment:

# Allowed attributes: name, email
user = User.new(name: "John", email: "john@example.com", admin: true)  # admin should not be assignable!
Follow-up: How do you protect your app against it?
You can prevent mass assignment vulnerabilities by using strong parameters in Rails, which explicitly define which attributes are allowed to be mass-assigned.



class UsersController < ApplicationController
  def user_params
    params.require(:user).permit(:name, :email)  # Only allow name and email
  end
end

5. What is CSRF?

Cross-Site Request Forgery (CSRF) is an attack where a malicious website can send unauthorized requests to a web application where the user is already authenticated. It tricks the user into performing an unintended action.

Follow-up: How is it handled in Rails? Rails protects against CSRF by using a CSRF token. This token is generated on each form and ensures that the request came from your site and not from an external source.

Rails includes the token in every form by default, and it’s checked on form submissions.

Example:

<%= form_with(url: posts_path, method: :post) do %>
  <%= text_field_tag :title %>
  <%= submit_tag "Create Post" %>
<% end %>

Rails automatically includes a hidden CSRF token in forms generated by form_with.

6. How do you handle database migrations in Rails?

Database migrations in Rails are used to manage changes to the database schema over time. They allow you to version-control your database structure, making it easy to roll back or apply changes.

Migrations are stored in files in the db/migrate directory. They can be run using rails db:migrate. Example:

# Migration to add a title column to the posts table
class AddTitleToPosts < ActiveRecord::Migration[6.0]
  def change
    add_column :posts, :title, :string
  end
end
Run the migration:

rails db:migrate

7. What is a scope?

A scope in Rails is a way to define commonly-used queries that can be reused throughout the application. It’s defined within the model and is typically used to simplify querying the database.

Example:

class Post < ApplicationRecord
  scope :published, -> { where(published: true) }
  scope :recent, -> { order(created_at: :desc).limit(5) }
end

# Usage
Post.published.recent

8. What is the difference between has_one and belongs_to?

has_one: This association indicates that one object can have one related object. It is typically used on the "one" side of a relationship. belongs_to: This association indicates that an object belongs to another object. It is used on the "many" side of the relationship. Example:

class Author < ApplicationRecord
  has_one :profile  # Author has one profile
end

class Profile < ApplicationRecord
  belongs_to :author  # Profile belongs to an author
end

In this case, an Author has one Profile, and a Profile belongs to an Author.

9. What is Rails Console, and how do you use it?

The Rails Console (rails console or rails c) is an interactive REPL (Read-Eval-Print Loop) that allows developers to run Ruby and Rails commands inside an application’s environment.

Usage:

rails console  # Start console in default (development) mode
rails console --sandbox  # Run console with changes rolled back after exit
rails console production  # Start console in production environment
Example:

# Create a new user
user = User.create(name: "Alice", email: "alice@example.com")

# Find a user
user = User.find_by(email: "alice@example.com")

# Update a user
user.update(name: "Alice Doe")

# Delete a user
user.destroy

etc

10. What are before_action, after_action, and skip_before_action?

These controller filters in Rails run specific code before or after an action.

before_action
Runs before the controller action.

class ArticlesController < ApplicationController
  before_action :authenticate_user

  def index
    @articles = Article.all
  end

  private

  def authenticate_user
    redirect_to login_path unless current_user
  end
end
after_action
Runs after the action is executed.


class ArticlesController < ApplicationController
  after_action :log_activity

  def show
    @article = Article.find(params[:id])
  end

  private

  def log_activity
    Rails.logger.info("Article viewed at #{Time.now}")
  end
end
skip_before_action
Skips the execution of a before_action for certain actions.

class ArticlesController < ApplicationController
  before_action :authenticate_user
  skip_before_action :authenticate_user, only: [:index, :show]

  def index
    @articles = Article.all
  end
end

11. What are Strong Parameters? Why are they needed?

Strong parameters prevent mass assignment vulnerabilities by requiring attributes to be explicitly permitted.

Unsafe (Vulnerable to Mass Assignment Attack)

user = User.new(params[:user]) # An attacker can set `admin: true`
Safe Approach (Strong Parameters)

class UsersController < ApplicationController
  def create
    @user = User.new(user_params)
    @user.save
  end

  private

  def user_params
    params.require(:user).permit(:name, :email)
  end
end

12. How do you define routes in Rails?

Routes define URL patterns and corresponding controller actions.

Basic Routes (config/routes.rb):
Rails.application.routes.draw do
  get "/articles", to: "articles#index"
  post "/articles", to: "articles#create"
  get "/articles/:id", to: "articles#show", as: "article"
end
Follow-up: What is the difference between resources and resource?
Method	    Routes   Generated        	Example
resources :users	Creates 7 RESTful routes (index, show, new, create, , update, destroy)	GET /users/:id/
resource :profile	Creates only one route per action (no index route)	GET /profile/

13. How do you generate a model, controller, and migration in Rails?

Model:

rails generate model User name:string email:string
Creates:

app/models/user.rb
db/migrate/xxxx_create_users.rb
Controller:

rails generate controller Users index show
Creates:

app/controllers/users_controller.rb
app/views/users/index.html.erb
app/views/users/show.html.erb
Migration:


rails generate migration AddAgeToUsers age:integer
rails db:migrate

14. What is the config/routes.rb file used for?

This file defines all application routes that map URLs to controllers and actions.

Example:

Rails.application.routes.draw do
  root "home#index"
  resources :articles
end
root "home#index" → Homepage
resources :articles → Generates RESTful routes

What is the difference between render, redirect_to, and respond_to in controllers?

Method	      Purpose	                                        Example
render	      Renders a template	                            render "show"
redirect_to	  Redirects to another URL	                      redirect_to articles_path
respond_to	  Responds with different formats (HTML, JSON)	`respond_to {

15. What is flash in Rails? How is it different from session?

Flash Stores temporary messages that last one request. Commonly used for notifications.

flash[:notice] = "Article saved!"
redirect_to articles_path
Session
Stores data across multiple requests.
Used for user authentication.
session[:user_id] = @user.id

16. How does Rails handle sessions and cookies?

Session stores data server-side (e.g., in cookies or Redis). Cookies store small amounts of client-side data.

Example (Using Sessions):
session[:user_id] = @user.id
Example (Using Cookies):

cookies[:user_id] = { value: @user.id, expires: 1.week.from_now }

17. What is link_to in Rails views?

Used to generate HTML tags dynamically.

<%= link_to "Home", root_path %>
Follow-up: How can you make link_to submit a form?
<%= link_to "Delete", article_path(@article), method: :delete, data: { confirm: "Are you sure?" } %>

18. What is form_with, and how does it work?

Used to generate forms dynamically in Rails.

<%= form_with model: @article, local: true do |f| %>
  <%= f.text_field :title %>
  <%= f.submit "Save" %>
<% end %>

19. What is partial in Rails views?

A partial is a reusable view component.

Usage:

<%= render "shared/header" %>
Follow-up: How do you pass local variables to a partial?

<%= render "article", article: @article %>
Partial _article.html.erb:


<h2><%= article.title %></h2>

20. What is link_to in Rails views?

link_to is a Rails helper method that generates HTML anchor () tags dynamically.

Basic Usage:

<%= link_to "Home", root_path %>
Generates:

<a href="/">Home</a>
Follow-up: How can you make link_to submit a form?
link_to can be used to send DELETE/POST/PUT requests by specifying the method and adding data: { confirm: "Message" }.

<%= link_to "Delete", article_path(@article), method: :delete, data: { confirm: "Are you sure?" } %>
Generates:
<a href="/articles/1" data-method="delete" data-confirm="Are you sure?">Delete</a>
Rails uses JavaScript (UJS) to convert this into a DELETE request.

21. What is form_with, and how does it work?

form_with is a Rails helper used to generate forms dynamically.

Basic Example:

<%= form_with model: @article, local: true do |f| %>
  <%= f.text_field :title %>
  <%= f.submit "Save" %>
<% end %>
This generates:
<form action="/articles" method="post">
  <input type="text" name="article[title]">
  <input type="submit" value="Save">
</form>
local: true prevents AJAX submissions.

22. What is a partial in Rails views?

A partial is a reusable view component that helps avoid duplication.

Example: Create _article.html.erb:

<div class="article">
  <h2><%= article.title %></h2>
  <p><%= article.content %></p>
</div>
Use it in another view:
<%= render "article", article: @article %>
Follow-up: How do you pass local variables to a partial?
<%= render "article", article: @article %>
Inside _article.html.erb:
<h2><%= article.title %></h2>

23. What is layout in Rails, and how do you use it?

Layouts define a common structure for multiple views.

Example app/views/layouts/application.html.erb:

<!DOCTYPE html>
<html>
<head>
  <title>My App</title>
</head>
<body>
  <%= yield %>
</body>
</html>
Each view injects its content into <%= yield %>.

24. What is yield, and how does it work in Rails layouts?

yield acts as a placeholder for page-specific content inside a layout.

Example app/views/layouts/application.html.erb:

<html>
<head><title>My App</title></head>
<body>
  <%= yield %> <!-- Page-specific content goes here -->
</body>
</html>
Usage in app/views/articles/index.html.erb:

<h1>All Articles</h1>
Final Rendered Output:

<html>
<head><title>My App</title></head>
<body>
  <h1>All Articles</h1>
</body>
</html>

25. What are helpers in Rails?

Helpers are Ruby methods used in views to keep logic out of templates.

Example Helper (app/helpers/articles_helper.rb):

module ArticlesHelper
  def formatted_date(date)
    date.strftime("%B %d, %Y")
  end
end
Usage in a view:

<p>Published on <%= formatted_date(@article.created_at) %></p>

Follow-up: When should you use a helper vs. a partial?

Use Case Helper Partial Formatting data ✅ Yes ❌ No Repeating view elements ❌ No ✅ Yes

26. What is params in Rails, and how does it work?

params stores request data (e.g., form inputs, URL parameters).

Example Controller:

class ArticlesController < ApplicationController
  def show
    @article = Article.find(params[:id]) # Fetch from URL
  end

  def create
    @article = Article.new(params.require(:article).permit(:title, :content)) # Form Data
  end
end

27. What is the difference between GET, POST, PUT, and DELETE requests in Rails?

HTTP Method Purpose Example Usage GET Read data GET /articles/1 POST Create data POST /articles PUT Update entire record PUT /articles/1 DELETE Delete a record DELETE /articles/1

28. What is rails routes, and how do you use it?

Lists all available routes in a Rails app.

rails routes
Example Output:

articles GET  /articles(.:format)  articles#index

29. What is has_many :through, and when do you use it?

It sets up a many-to-many relationship via a join table.

class User < ApplicationRecord
  has_many :user_projects
  has_many :projects, through: :user_projects
end

class UserProject < ApplicationRecord
  belongs_to :user
  belongs_to :project
end

class Project < ApplicationRecord
  has_many :user_projects
  has_many :users, through: :user_projects
end

30. What is validates in Rails models?

validates ensures data integrity before saving records.

class User < ApplicationRecord
  validates :name, presence: true, length: { minimum: 3 }
  validates :email, uniqueness: true
end
Follow-up: What are some common validation options?
Validation	Example
presence: true	Ensures value is present
uniqueness: true	Ensures unique values
length: { minimum: x }	Min character length
format: { with: /regex/ }	Custom regex validation

31. What is rescue_from, and how does it work?

rescue_from handles exceptions globally in controllers.

class ApplicationController < ActionController::Base
  rescue_from ActiveRecord::RecordNotFound, with: :not_found

  private

  def not_found
    render plain: "404 Not Found", status: :not_found
  end
end

32. What is rake, and how does it work in Rails?

Rake (Ruby Make) automates tasks like migrations and seeding.

rake db:migrate
rake db:seed
Follow-up: What is the difference between rake and rails commands?
Command	Purpose
rake	Runs tasks (e.g., migrations)
rails	Runs commands (e.g., server, console)

🛠 1. Handling N+1 Queries (Optimization)

To handle N+1 queries in Rails, We typically use eager loading with includes, preload, or eager_load. This ensures that associated records are fetched in a single query rather than one per record. ❌ Problem:

# N+1 Issue
Post.all.each do |post|
  puts post.comments.count
end
users = User.all
users.each do |user|
  puts user.posts.count
end

This results in one query per user, leading to an N+1 query issue.

✅ Solution: Use includes for Eager Loading

users = User.includes(:posts)  # Fetch users & posts in 1 query
users.each do |user|
  puts user.posts.count  # Does not make extra queries
end

# Optimized with eager loading
Post.includes(:comments).each do |post|
  puts post.comments.count
end

👉 includes loads the associated records efficiently. preload:

Use when: You want to load the associations in a separate query (good for simple display, not for SQL conditions on joined tables).

# This will run two queries:
# 1. SELECT * FROM posts
# 2. SELECT * FROM comments WHERE post_id IN (...)

posts = Post.preload(:comments)
posts.each do |post|
  post.comments.each do |comment|
    puts comment.body
  end
end

eager_load: Use when: You want to avoid N+1 and also filter or sort based on associated table columns using a single SQL query with a JOIN.

# This performs a LEFT OUTER JOIN in one SQL query
posts = Post.eager_load(:comments).where("comments.created_at > ?", 1.week.ago)

posts.each do |post|
  post.comments.each do |comment|
    puts comment.body
  end
end

This is helpful when the query involves conditions on the joined table (comments), and Rails handles the LEFT OUTER JOIN automatically.

Summary:
Method	      Type of Query	              Use Case
includes	  Smartly chooses join/preload	Safe default for most use cases
preload	    Separate queries	            Display data without filtering/sorting on join
eager_load	Single joined query	          Needed when filtering/sorting using joined table

🛠 2. Implementing Caching in Rails

🔹 Fragment Caching

Use case: You want to cache a specific section of the view, like a post card or sidebar, to avoid rendering it again and again.

How it works:

Rails generates a cache key for the object (like views/posts/123-20250422113000) based on its class, ID, and updated_at timestamp. If the key exists in the cache store, it reuses the HTML output instead of rerendering.

Cache key tip:

Rails automatically uses cache_key_with_version (e.g., posts/123-20250422120000) so you don’t need to manually manage invalidation unless you have custom logic.

- cache @post do
  .post
    %h2= @post.title
    %p= @post.body

Best practices:
Use meaningful keys if you're caching non-record-based content:


- cache ['sidebar', current_user.role] do
  = render 'shared/sidebar'

🔹 Russian Doll Caching:

Use case:

Your view has multiple nested partials (e.g., posts with comments), and you want to cache each layer separately to avoid cache invalidation of the entire block.

Why it's powerful:

If a comment changes, only the comment block cache is invalidated, not the entire post. Rails handles this efficiently using cache keys with timestamps.

- cache @post do
  .post
    %h2= @post.title
    %p= @post.body

    - cache @post.comments do
      .comments
        = render @post.comments

In the above example:

If @post.updated_at changes → outer cache invalidated.

If a comment changes → only @post.comments cache is invalidated.


👉 Caches the HTML output of the article block.

🔹 Low-Level Caching

Use case: When you want to cache arbitrary data — like a set of records, a computed value, or external API results — at the controller or model level.

How it works:

You manually define a cache key and use Rails.cache.fetch to store and retrieve data. If the key is not present in the cache, the block is executed and the result is cached.

Example – Top Posts:

# In controller or service object
def top_posts
  Rails.cache.fetch("top_posts", expires_in: 12.hours) do
    Post.order(views: :desc).limit(10).to_a
  end
end
- This avoids hitting the DB every time users visit the homepage or dashboard.

You can add user-specific or context-specific info to the key:

Rails.cache.fetch(["top_posts", current_user.role], expires_in: 6.hours) do
  Post.visible_to(current_user).order(created_at: :desc).limit(10)
end

Rails.cache.fetch("recent_articles", expires_in: 10.minutes) do
  Article.order(created_at: :desc).limit(5)
end
👉 Caches query results for 10 minutes.

🔹 HTTP Caching

Use case: When you want to reduce bandwidth and avoid unnecessary re-rendering by allowing browsers or CDNs to use cached versions of your content.

Rails provides built-in helpers like fresh_when and stale? to implement this based on the record’s updated_at timestamp and cache_key.

Example using fresh_when:

def show
  @article = Article.find(params[:id])
  fresh_when(@article)  # Sets ETag and Last-Modified headers
end
If the content hasn’t changed since the last request, Rails will respond with 304 Not Modified, skipping the view rendering.

Example using stale?:

def show
  @article = Article.find(params[:id])
  if stale?(@article)
    render :show
  end
end
stale? checks if the content is outdated and only renders if necessary.

Production Cache Store In production, I typically configure a high-performance cache backend:

Redis: Great for both caching and session storage. It supports advanced features like key expiry, namespaces, etc.

Memcached: Lightweight and super-fast, good for ephemeral cache use cases.

Example in config/environments/production.rb:

config.cache_store = :redis_cache_store, { url: ENV['REDIS_URL'] }

Pro Tips: Enable config.action_controller.perform_caching = true in development to test this.

Use tools like rack-mini-profiler or fragment-cacher to inspect which fragments are being hit or missed.

Keep cache blocks small and specific—avoid putting entire pages inside one cache block unless absolutely necessary.

🚀 𝗟𝗲𝘃𝗲𝗹 𝗨𝗽 𝗬𝗼𝘂𝗿 𝗥𝗮𝗶𝗹𝘀 𝗞𝗻𝗼𝘄𝗹𝗲𝗱𝗴𝗲 𝘄𝗶𝘁𝗵 𝗧𝗵𝗲𝘀𝗲 𝗜𝗻𝘁𝗲𝗿𝘃𝗶𝗲𝘄 𝗤𝘂𝗲𝘀𝘁𝗶𝗼𝗻𝘀 🚀

5. When to Use Proc vs. Lambda

Feature Proc Lambda Arity Check Allows missing arguments (defaults to nil). Strictly enforces the number of arguments. Return Behavior Exits the method immediately. Returns control to the method. Use Case Flexible argument handling, quick inline logic. Function-like behavior with strict argument handling.

6. Real-World Use Cases

Using Proc in Dynamic Method Execution

def perform_action(action)
  actions = {
    greet: Proc.new { puts "Hello!" },
    farewell: Proc.new { puts "Goodbye!" }
  }
  actions[action].call if actions[action]
end

perform_action(:greet)    # Output: "Hello!"
perform_action(:farewell) # Output: "Goodbye!"

Using Lambda for Strict Validations

validate_input = ->(name, age) {
  raise "Invalid name" if name.nil? || name.empty?
  raise "Invalid age" if age < 18
  "Welcome, #{name}!"
}

puts validate_input.call("Alice", 20)  # ✅ Output: "Welcome, Alice!"
puts validate_input.call("", 25)       # ❌ Raises error "Invalid name"

Summary

Feature	                      Proc (Proc.new)	                                        Lambda (-> {})
Arity (Arguments Handling)	  Doesn't enforce argument count (missing args = nil).	  Strict argument checking (errors if missing).
Return Behavior	              Exits the calling method immediately.	                  Returns control to the calling method.
Use Case	                    When flexibility is needed.	                            When strict function-like behavior is required.

💡 TL;DR Use Procs when you want loose argument handling and early exit behavior.

Use Lambdas when you want strict function-like execution.

Explain Sharding ?

Sharding is a database partitioning technique that distributes data across multiple databases or servers to improve performance, scalability, and availability. Instead of storing all records in a single database, data is split (sharded) into multiple databases based on a specific key (e.g., user ID, region, tenant).

Why Use Sharding?

✅ Benefits of Sharding

Scalability – Distributes load across multiple database instances.

Performance – Reduces query time by limiting the data each query scans.

Fault Tolerance – Failure in one shard doesn’t affect others.

Multi-tenancy Support – Different customers (tenants) can be stored in separate databases.

How Does Sharding Work in Rails?

Rails 6+ provides built-in support for database sharding using the multiple databases feature (config/database.yml).

Example: User Data Sharded Across Multiple Databases

# config/database.yml
production:
  primary:
    adapter: postgresql
    database: main_db
    host: db1.example.com
  shard_1:
    adapter: postgresql
    database: shard1_db
    host: db2.example.com
  shard_2:
    adapter: postgresql
    database: shard2_db
    host: db3.example.com
Each database (shard_1, shard_2) contains a subset of the total records.

🔹 Implementing Sharding in Rails

Step 1: Define Database Connections Modify database.yml to add shard configurations.

Step 2: Switch Between Shards in Models Use connects_to in the model:

class User < ApplicationRecord
  connects_to database: { writing: :shard_1, reading: :shard_1 }
end

Step 3: Manually Switch Shards in Queries

ActiveRecord::Base.connected_to(role: :writing, shard: :shard_1) do
  User.create(name: "Alice")
end

Step 4: Auto-Route Requests Based on Shard Key Example: Shard based on user region.

def set_shard
  user_region = params[:region]  # Example: "asia"
  shard = "shard_#{user_region}"
  ActiveRecord::Base.connected_to(role: :writing, shard: shard) do
    yield
  end
end

This method automatically connects to the appropriate shard.

When to Use Sharding?

Use Case Should You Use Sharding? Millions of rows per table ✅ Yes Multi-tenancy (separate databases per customer) ✅ Yes Geo-distributed applications ✅ Yes Simple CRUD apps with low traffic ❌ No Short-term performance issues (use indexing instead) ❌ No

Alternatives to Sharding Read Replicas – Separate read and write databases (primary, replica).

Partitioning – Store different data segments in the same database (PostgreSQL table partitioning).

TL;DR Sharding splits data across multiple databases to improve performance and scalability.

Rails 6+ supports multi-database configurations (connects_to, connected_to).

Use sharding when dealing with high-volume, multi-tenant, or geographically distributed applications.

🛠 Core Rails Questions

How does Rails handle database connection pooling?

What is Database Connection Pooling?

Database connection pooling is a technique where a fixed number of database connections are maintained and reused across requests. Instead of opening and closing a connection for each request (which is expensive), Rails maintains a "pool" of open connections to improve performance and reduce overhead.

Rails uses ActiveRecord’s built-in connection pool, which is managed by ActiveRecord::ConnectionAdapters::ConnectionPool. Here's how it works under the hood:

Pool Initialization:

When the app boots, Rails reads the config/database.yml file and initializes a connection pool per environment (and per role/shard if you're using multi-DB).

Per-thread: Checkout Each thread (e.g., Puma worker thread) checks out a connection from the pool when needed. The same thread reuses that connection throughout the request.

Connection Checkout and Check-in:

When a request begins → Rails checks out a connection.

When the request ends → Rails checks it back into the pool.

If all connections are in use, new threads will wait (up to a timeout) for a connection to free up.

Connection Pool Settings (from database.yml)

production:
  adapter: postgresql
  database: myapp_production
  pool: 15       # number of connections
  timeout: 5000  # wait time (ms) before raising a timeout error

Common Issues

  1. Too Small Pool Size

If your app handles many concurrent requests, and your pool size is too low, you’ll see:

ActiveRecord::ConnectionTimeoutError: could not obtain a database connection within 5 seconds
  1. Too Large Pool Size

Oversizing the pool can exhaust the database's max connections, especially if you scale horizontally.

Summary:

Rails maintains a per-thread connection pool using ActiveRecord.

Connections are checked out at request start and checked in at the end.

You configure the pool size and timeout in database.yml.

Tuning the pool size is critical for performance and stability in production environments.

What are ActiveRecord callbacks? When should you avoid them?

ActiveRecord callbacks are lifecycle hooks in Rails that allow you to run code before or after certain events on a model — such as create, update, save, or destroy.

They’re used to encapsulate logic that is tightly coupled to a model's data lifecycle.

Common Callbacks:

class Post < ApplicationRecord
  before_save :generate_slug
  after_create :send_notification
  before_destroy :log_deletion
end

eg:

before_validation, after_save, after_create, before_update, before_destroy etc

When to Use Them:

Auto-generating fields (e.g., slugs, tokens)

Logging/auditing changes

Sending notifications or triggering side effects after save

Enforcing business rules closely tied to the model’s lifecycle

When to Avoid Callbacks (Best Practices):

Complex Business Logic:

➤ Move logic into service objects or jobs.

Callbacks can make models "do too much" and harder to test/debug.

What are ActiveSupport Concerns? How do they differ from modules?

What are ActiveSupport::Concerns? ActiveSupport::Concern is a Rails helper module that provides a clean and structured way to write reusable code (usually shared logic) and include it into models, controllers, or other classes.

It builds on Ruby’s native Module but adds a few Rails-specific conveniences for:

Organizing code more cleanly

Hooking into lifecycle methods (included, class_methods)

Avoiding tricky included do blocks and meta-programming

Basic Structure of a Concern

module Archivable
  extend ActiveSupport::Concern

  included do
    scope :archived, -> { where(archived: true) }
  end

  def archive!
    update(archived: true)
  end

  module ClassMethods
    def recently_archived
      where("archived_at >= ?", 1.week.ago)
    end
  end
end
How It Differs From a Plain Ruby Module:
Feature                               	Module	          ActiveSupport::Concern
Basic inclusion	                         ✅ Yes	          ✅ Yes
Clean included do syntax	               ❌ No	            ✅ Yes
Handles ClassMethods automatically	     ❌ No	            ✅ Yes
Designed for Rails (scopes, callbacks)	 ❌ No	            ✅ Yes
Explicit load order safety	             ❌ Risk of bugs	  ✅ Prevents common issues

Example Use Case: Archivable Records

Imagine you have multiple models (like Post, Comment, Document) that need to support archiving — a common behavior with archived: true/false.

We’ll extract this logic into a reusable concern called Archivable.
Step 1: Create the Concern


# app/models/concerns/archivable.rb
module Archivable
  extend ActiveSupport::Concern

  included do
    scope :archived, -> { where(archived: true) }
    scope :unarchived, -> { where(archived: false) }
  end

  def archive!
    update(archived: true)
  end

  def unarchive!
    update(archived: false)
  end

  def archived?
    archived
  end
end

Step 2: Include it in your model

# app/models/post.rb
class Post < ApplicationRecord
  include Archivable

  # other associations, validations, etc.
end

# app/models/comment.rb
class Comment < ApplicationRecord
  include Archivable

  # other logic
end

Step 3: Use it in Your Application

# Archive a post
post = Post.find(params[:id])
post.archive!

# List only archived posts
Post.archived

# Check if a comment is archived
comment.archived?

# Get all unarchived comments
Comment.unarchived

What is the purpose of Rails engines? When would you use one?

How does Rails handle has_many :through vs. has_and_belongs_to_many?

Both are used to set up many-to-many relationships in Rails, but they differ in flexibility and use case.

has_and_belongs_to_many (HABTM):

Direct many-to-many association with no intermediate model.

Uses a join table (e.g., students_courses) without a corresponding model.

# app/models/student.rb
class Student < ApplicationRecord
  has_and_belongs_to_many :courses
end

# app/models/course.rb
class Course < ApplicationRecord
  has_and_belongs_to_many :students
end

Requires a join table migration:

create_join_table :students, :courses

Limitations:

Cannot store additional data (e.g., enrollment date, grade) on the relationship.

Less flexible for validations and callbacks.

has_many :through Uses an intermediate model to manage the relationship.

Ideal when you need to store extra data or add logic to the join.

# app/models/student.rb
class Student < ApplicationRecord
  has_many :enrollments
  has_many :courses, through: :enrollments
end

# app/models/enrollment.rb
class Enrollment < ApplicationRecord
  belongs_to :student
  belongs_to :course

  # extra fields: enrolled_at, grade, etc.
end

# app/models/course.rb
class Course < ApplicationRecord
  has_many :enrollments
  has_many :students, through: :enrollments
end

Advantages:

More powerful and flexible

Allows custom validations, callbacks, and extra attributes on the join model

Summary:

Feature	                    has_and_belongs_to_many	  has_many :through
Join Table	                         Yes (no model)	   Yes (with model)
Extra Attributes	                  ❌ Not possible	  ✅ Yes
Validations/Callbacks             	❌ No	            ✅ Yes
Preferred for	                      Simple joins	     Complex logic, extra fields

What’s the difference between belongs_to and has_one?

These are both one-to-one associations but from opposite directions:

belongs_to

Declares ownership from the child side.

The table has the foreign key column.

Used when the current model "belongs to" another.

class Order < ApplicationRecord
  belongs_to :user  # foreign key: user_id
end

has_one:

Declares ownership from the parent side.

Points to a related record that exists only once.

Often used when you want to access a related model from the owning model.

class User < ApplicationRecord
  has_one :profile
end
✅ Summary:

Feature	                  belongs_to	                  has_one
Owns the FK	                  ✅ Yes	                    ❌ No
Declares on	              Child model	                  Parent model
Association direction	    Inward	                      Outward
Example	                  Order → belongs_to :user  	  User → has_one :profile

What are different ways to manage configurations in Rails (secrets.yml, credentials.yml.enc, ENV variables)?

Rails provides several ways to manage sensitive data and environment-specific settings like API keys, database credentials, and secret tokens.

  1. secrets.yml (Rails < 5.2) Located in config/secrets.yml

Used for storing application secrets per environment.

Loaded via Rails.application.secrets[:your_key]

Example:

production:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
  stripe_secret: <%= ENV["STRIPE_SECRET"] %>

Deprecated in favor of credentials.yml.enc in Rails 5.2+

  1. credentials.yml.enc (Rails 5.2+) Encrypted file managed by Rails for storing secrets.

Decrypted using the master key (config/master.key) or ENV["RAILS_MASTER_KEY"].

Location:

config/credentials.yml.enc

Decrypted with: rails credentials:edit

Example:

aws:
  access_key_id: 123
  secret_access_key: 456

stripe:
  secret_key: sk_test_123

Access:

Rails.application.credentials.aws[:access_key_id]
Rails.application.credentials[:stripe][:secret_key]

Recommended for most applications unless using multi-environment credentials (see below).

Use Case                                        	Recommended Approach
Small to medium app with default secrets	        credentials.yml.enc
Separate dev, staging, and prod credentials	      Multi-env credentials
Secrets managed externally (Heroku, AWS, Docker)	ENV variables
Legacy apps (Rails < 5.2)	                        secrets.yml (legacy only)

What is the difference between dependent: :destroy, dependent: :delete_all, and dependent: :nullify?

How do you implement state machines in Rails (e.g., AASM, workflow gem)?

What’s the difference between rake and rails commands?

What are concerns, and when should they be used?

Explain the difference between joins, includes, preload, and eager_load.

How does Rails’ autoloading work? What changed in Zeitwerk?

What are Rails observers, and why are they deprecated?

How does the Rails asset pipeline work?

⚡ Performance & Scalability

What techniques do you use to prevent N+1 queries?

What is database sharding? How does Rails support it?

How do you analyze slow database queries in Rails?

What is caching in Rails? How does fragment caching work?

How do you handle background jobs at scale in Rails?

What are the advantages and disadvantages of Sidekiq vs. Delayed Job vs. Resque?

What is a Rails middleware? How do you add a custom middleware?

How do you scale a Rails application to handle high traffic?

What are different types of caching available in Rails?

What is Puma? How does it improve Rails performance?

How does Rails handle HTTP/2 and WebSockets?

What are the best practices for optimizing ActiveRecord queries?

What’s the difference between connection_pool and database.yml settings?

How do you handle large file uploads in Rails?

What’s the difference between synchronous and asynchronous processing in Rails?

🛡️ Security & Best Practices

What is CSRF, and how does Rails prevent it?

What is SQL injection? How does Rails prevent it?

How does Rails handle Cross-Site Scripting (XSS) vulnerabilities?

What is mass assignment, and how can it be prevented?

What is the difference between strong_parameters and attr_accessible?

What is session fixation, and how does Rails mitigate it?

What is secure_compare and why is it important?

How do you prevent brute-force attacks in Rails authentication?

How does Devise handle authentication and security?

What are Rails' default security mechanisms (e.g., Secure Headers, HTTP-only cookies)?

How do you enforce password policies in Rails apps?

What is parameter tampering, and how does Rails prevent it?

How do you secure Rails APIs (rate limiting, JWT, OAuth)?

What is the difference between session_store and cookie_store?

What is CORS, and how does Rails handle it?

What is permanent_signed vs. signed cookies in Rails?

How do you handle authorization (Pundit vs. CanCanCan)?

How do you prevent replay attacks in Rails?

What is rails-ujs, and how does it help with security?

How do you enforce HTTPS in a Rails application?

🛠 System Design & Architecture

What is REST, and how does Rails enforce RESTful design?

How do you implement API versioning in Rails?

What are the key differences between REST and GraphQL?

How would you design a multi-tenant Rails application?

How does Rails handle WebSockets and real-time features?

How do you design a microservices-based architecture with Rails?

What are the trade-offs of monolithic vs. microservices architecture in Rails?

What are design considerations for building a large-scale Rails API?

How do you handle background jobs in a multi-server environment?

How do you handle file storage in Rails (ActiveStorage, Shrine, Paperclip)?

What is CQRS, and how can it be applied in Rails applications?

How do you handle rate-limiting in Rails APIs?

What are the challenges of running Rails in a containerized environment (Docker, Kubernetes)?

How would you handle real-time notifications in Rails?

How do you implement event-driven architecture in Rails?

What are the key performance bottlenecks in a Rails application?

What are the key differences between Rails and other frameworks like Django or Laravel?

How do you handle service-to-service authentication in a Rails microservices setup?

How do you optimize database indexes for large-scale Rails applications?

How would you design a rate-limiting system in Rails?🛠 System Design & Architecture

What is REST, and how does Rails enforce RESTful design?

How do you implement API versioning in Rails?

What are the key differences between REST and GraphQL?

How would you design a multi-tenant Rails application?

How does Rails handle WebSockets and real-time features?

How do you design a microservices-based architecture with Rails?

What are the trade-offs of monolithic vs. microservices architecture in Rails?

What are design considerations for building a large-scale Rails API?

How do you handle background jobs in a multi-server environment?

How do you handle file storage in Rails (ActiveStorage, Shrine, Paperclip)?

What is CQRS, and how can it be applied in Rails applications?

How do you handle rate-limiting in Rails APIs?

What are the challenges of running Rails in a containerized environment (Docker, Kubernetes)?

How would you handle real-time notifications in Rails?

How do you implement event-driven architecture in Rails?

What are the key performance bottlenecks in a Rails application?

What are the key differences between Rails and other frameworks like Django or Laravel?

How do you handle service-to-service authentication in a Rails microservices setup?

How do you optimize database indexes for large-scale Rails applications?

How would you design a rate-limiting system in Rails?

💎 Advanced Ruby Questions

What is the difference between Proc and Lambda?

What is the difference between include, extend, and prepend?

How does Ruby garbage collection (GC) work?

How It Works (Conceptually)

Ruby’s GC follows a "mark-and-sweep" algorithm, with enhancements in newer versions:

Mark Phase

Ruby walks through all "reachable" objects — starting from root references (like global variables, method stacks, etc.).

Marks them as "in use."

Sweep Phase

All objects that weren’t marked are considered unused and are freed from memory.

What is the difference between Thread and Fiber?

What are Ruby metaprogramming techniques?

What are method_missing and respond_to_missing?

These are part of Ruby’s dynamic method handling. They allow objects to respond to method calls even if those methods are not explicitly defined — a key part of Ruby's metaprogramming capabilities.

method_missing:

A special method you can override to intercept calls to undefined methods.

Commonly used in dynamic proxies, DSLs, or delegators.

respond_to_missing?

Used in combination with method_missing to make respond_to? return true for dynamically handled methods.

Helps tools like irb, introspection, and method lookup work correctly.

What are singleton classes and eigenclasses in Ruby?

What is duck typing in Ruby?

In Ruby, an object’s type doesn’t matter — what matters is whether it responds to the methods you need.

def make_sound(animal)
  animal.sound
end

class Dog
  def sound
    "Bark"
  end
end

class Cat
  def sound
    "Meow"
  end
end

make_sound(Dog.new)  # => "Bark"
make_sound(Cat.new)  # => "Meow"

make_sound doesn’t care whether the object is a Dog or Cat, as long as it responds to #sound.

Benefits of Duck Typing:

Flexible: No strict interfaces required

Clean code: Less boilerplate

Powerful metaprogramming

How does Ruby handle method lookup and method resolution order (MRO)?

How does module_function work in Ruby?

What is the difference between public, private, and protected methods?

public (default):

Methods are accessible from anywhere — inside or outside the class.

All instance methods are public by default unless specified otherwise.

private:

Can only be called within the context of self, and without an explicit receiver.

Typically used for internal logic that shouldn’t be accessed externally.

protected: Can be called within the same class or its subclasses, even with an explicit receiver — but only if the receiver is an instance of the same class.

Summary:

Modifier	                      Access From	      Explicit Receiver Allowed?	      Use Case
public	                        Anywhere	           ✅ Yes	                       Normal API methods
private	                         Within class	         ❌ No	                        Internal helpers
protected	                      Same class/subclass   	✅ Yes (if same class)	    Comparisons, shared logic

What is the difference between class_variable, instance_variable, and global_variable?

Summary:
Variable          Type	       Prefix	Scope	                Shared? 	Usage
Instance Variable	@	            Per object	                ❌ No	  Object state
Class Variable	  @@	        Shared in class & subclasses	✅ Yes	Global class-level count, config
Global Variable	  $	            Everywhere in program	       ✅ Yes (global)	Avoid unless absolutely necessary

What is monkey patching, and when should you avoid it?

What are refinements in Ruby?

How do you implement multiple inheritance in Ruby?

What is the difference between super and self?

How does define_method work in Ruby?

What is method_missing, and how can it be useful?

What is a Ruby block, and how is it different from a Proc?

What is the difference between tap, yield_self, and then in Ruby?

Core Ruby Questions

How is memory management handled in Ruby?

What’s the difference between dup and clone in Ruby?

Explain the concept of object immutability in Ruby.

What is the difference between super and super()?

super:

Passes all arguments that were passed to the current method to the superclass method automatically.

If the superclass method accepts those arguments, it works as expected.

class Parent
  def greet(name)
    "Hello, #{name}"
  end
end

class Child < Parent
  def greet(name)
    super   # passes `name` automatically
  end
end

Child.new.greet("Alice")  # => "Hello, Alice"

super():

Passes no arguments at all to the superclass method.

Use this when the superclass method does not expect arguments, or when you want to override without forwarding arguments.

class Parent
  def greet
    "Hello!"
  end
end

class Child < Parent
  def greet(name)
    super() + " I'm #{name}."
  end
end

Child.new.greet("Alice")  # => "Hello! I'm Alice."

How does Ruby’s case statement work internally? Does it use == or ===?

🧩 OOP and Design Questions

What are the SOLID principles? Can you demonstrate one using Ruby?

What’s the difference between a class variable and a class instance variable?

When would you use method_missing vs define_method?

How do modules affect the method lookup chain in Ruby?

What is a mixin and when would you use it over inheritance?

🧪 Testing and Tooling

How would you test private methods in Ruby? Should you?

Explain how RSpec matchers work and how to write custom matchers.

What’s the difference between mocking and stubbing in tests?

How do you test a class that uses metaprogramming or dynamic behavior?

🔀 Enumerable and Functional Patterns

What’s the difference between map, collect, each_with_object, and reduce?

How would you reverse a linked list using only Ruby's Enumerable methods?

Explain lazy evaluation in Ruby with an example.

How would you implement your own version of zip or group_by?

🧬 Metaprogramming & DSLs

What are the risks of using eval in Ruby?

Can you write a DSL for a pizza builder? (e.g., Pizza.new.size(:large).toppings(:olives, :cheese))

How does method_missing affect performance and debuggability?

When would you use class_eval vs define_singleton_method?

Can you override send or respond_to?? When might you do that?

🕹 Concurrency and System Design

How would you handle thread safety in Ruby for shared data structures?

What are Fibers and how are they different from Threads?

Have you used Ractor in Ruby 3.x? How does it enable true parallelism?

Design an in-memory rate limiter in Ruby (e.g., max 10 requests per minute per user).

💡 Debugging and Performance

How do you profile memory or CPU usage in a Ruby script?

Explain the concept of memoization. How would you implement it manually?

How do you reduce object allocation in a large loop?

When and why would you freeze an object in Ruby?

🔐 Trick Questions / Gotchas

What will this return and why?

def weird
  begin
    raise "Oops"
  rescue
    return "rescued"
  ensure
    return "ensured"
  end
end

puts weird  # => ???

Answer: "ensured" — ensure always runs last and overrides the return.

What’s the difference between ||= and or=?

Why might using Hash.new([]) cause unexpected behavior?

✅ Basic Ruby Questions

What are symbols in Ruby? How are they different from strings?

What are the different types of variables in Ruby (local, instance, class, global)?

What is the difference between ==, eql?, and equal??

Explain the difference between puts, print, and p.

What is a block, and how is it different from a Proc or a lambda?

What is the use of the self keyword in Ruby?

What is the difference between include and extend in modules?

How does garbage collection work in Ruby?

What’s the difference between nil, false, and undefined variable in Ruby?

🔁 Intermediate Ruby Questions

Explain how Ruby handles method overloading or default arguments.

What is duck typing in Ruby? Give an example.

How does Ruby handle inheritance and method resolution?

What are singleton methods? When would you use them?

What’s the difference between Proc.new, lambda, and the -> syntax?

What are refinements in Ruby? Why would you use them instead of monkey-patching?

What are the scopes of constants in Ruby (e.g., ::, nesting)?

Explain what mixins are. How are they implemented in Ruby?

How do you define and use custom enumerators in Ruby?

🔬 Advanced Ruby Questions

How would you implement your own version of each, map, or select without using Ruby's built-in methods?

What are some metaprogramming techniques in Ruby? Show an example using define_method or method_missing.

What is the difference between class variables (@@) and class instance variables (@ on the class)?

How does Ruby’s method_missing work, and what are the risks?

What’s the difference between eager and lazy enumerators in Ruby?

How do fibers work in Ruby? What are they useful for?

How would you optimize memory usage in a Ruby app that processes millions of records?

What is the Global Interpreter Lock (GIL) in Ruby MRI? How does it affect threading?

How would you implement a Domain-Specific Language (DSL) in Ruby?

📌 Live Coding Challenge Questions

Implement a caching mechanism in Rails without using built-in Rails caching.

Optimize a slow SQL query in a Rails application.

Write a background job that sends scheduled emails using Sidekiq.

Write a Rails service object that processes and validates a CSV file upload.

Refactor a Rails controller that has too many instance variables.

Write a Rails middleware that logs request details before passing it to the controller.

Write a method that finds all duplicate users based on their email in ActiveRecord.

Design a system to throttle API requests in Rails without using third-party gems.

Implement an authentication system without Devise in Rails.

Write a custom ActiveRecord scope that returns all users who haven’t logged in for 30 days.

𝗜𝗻𝘁𝗲𝗿𝗺𝗲𝗱𝗶𝗮𝘁𝗲 𝗤𝘂𝗲𝘀𝘁𝗶𝗼𝗻𝘀 -:

1. How do you handle exceptions and errors in Rails? What strategies do you use for logging and notification?

2. How do you approach database modeling in Rails? What considerations do you take for efficient data retrieval and storage?

3. How do you use Rails migrations to manage database schema changes? What are some best practices for writing migrations?

4. What caching mechanisms does Rails offer (fragment, action, and page caching), and when would you use each?

5. How do you design RESTful APIs in Rails? What considerations do you take for API versioning and security?

6. How do you use service objects to encapsulate business logic in Rails? What benefits do they offer?

7. How do you define nested routes in Rails? What are some advanced routing techniques such as shallow routes?

8. Explain polymorphic associations in Rails. When would you choose them over standard associations?

𝗔𝗱𝘃𝗮𝗻𝗰𝗲𝗱 𝗤𝘂𝗲𝘀𝘁𝗶𝗼𝗻𝘀 -:

9. How do you tackle the N+1 query problem in Rails? What tools or techniques do you use to optimize queries?

10. How do you handle database transactions in Rails? What steps do you take to optimize database performance through indexing and query tuning?

11. How would you manage caching in a high-traffic, distributed Rails environment? Discuss the use of fragment, action, and page caching.

12. Discuss Rails’ built-in security features. How do you mitigate risks like CSRF, XSS, and SQL injection?

13. How do you design, secure, and version API endpoints in Rails? What are your thoughts on REST vs. GraphQL?

14. What architectural patterns have you implemented to ensure a Rails application scales? Discuss multi-tenancy or micro-services if applicable.

15. How do you address concurrency in Rails? Have you encountered and solved challenges with multi-threading?

16. What is sharding, and how can it be implemented in Rails to optimise data access for large datasets?

17. What testing frameworks and strategies (unit, integration, performance) do you rely on in Rails? How do you ensure comprehensive test coverage?

18. Describe your experience implementing real-time features using Action Cable. What challenges did you encounter?

19. How do you approach refactoring a large, legacy Rails codebase without causing disruptions? What tools or methodologies do you use?

20. Have you worked with Rails 6/7 features such as ActionMailbox, ActionText, or Hotwire? How have they influenced your development process?

21. How do you use service objects or decorators to encapsulate business logic? Share your experiences with Ruby’s meta-programming capabilities.

22. What role does Rack play in Rails? Have you ever built custom middleware? If so, how?

23. How do you analyze and optimize database queries in Rails? What tools do you use to identify performance bottlenecks?

How does Rails handle database connection pooling?

Explain the difference between joins, includes, preload, and eager_load.

How does Rails’ autoloading work? What changed in Zeitwerk?

What are ActiveRecord callbacks? When should you avoid them?

What are ActiveSupport Concerns? How do they differ from modules?

What is the purpose of Rails engines? When would you use one?

How does Rails handle has_many :through vs. has_and_belongs_to_many?

What’s the difference between belongs_to and has_one?

What are Rails observers, and why are they deprecated?

How does the Rails asset pipeline work?

What are different ways to manage configurations in Rails (secrets.yml, credentials.yml.enc, ENV variables)?

What is the difference between dependent: :destroy, dependent: :delete_all, and dependent: :nullify?

How do you implement state machines in Rails (e.g., AASM, workflow gem)?

What’s the difference between rake and rails commands?

What are concerns, and when should they be used?

🧠 Problem 1: Dynamic Method Generation (Metaprogramming)

Challenge: Write a class CurrencyConverter that dynamically defines methods like to_usd, to_eur, to_gbp, and converts from a base amount in cents (as integer) to those currencies using given exchange rates.

🧠 Problem 2: Lazy Prime Generator (Enumerators)

Challenge: Write a method lazy_primes(n) that lazily generates the first n prime numbers using Ruby's enumerators.

🧠 Problem 3: Safe Concurrency with Threads

Challenge: Create a counter that increments safely from multiple threads (simulate 100 threads incrementing a shared counter 1000 times each). Use a mutex to avoid race conditions.

🚀 Intermediate Rails Questions

1. Handling Exceptions & Logging

Use rescue_from in controllers to handle specific exceptions:

class ApplicationController < ActionController::Base
  rescue_from ActiveRecord::RecordNotFound, with: :not_found
  rescue_from StandardError, with: :handle_error

  private

  def not_found
    render json: { error: "Record not found" }, status: :not_found
  end

  def handle_error(exception)
    Rails.logger.error(exception.message)
    render json: { error: "Something went wrong" }, status: :internal_server_error
  end
end

Use Rollbar, Sentry, or Bugsnag for error notifications.

2. Database Modeling Considerations

Normalize data when needed (e.g., extract a tags table if storing repeated text). Use indexes for faster lookups (add_index :users, :email, unique: true). Optimize eager loading to avoid N+1 queries.

3. Managing Migrations

Keep migrations idempotent (avoid destructive changes in production).

Use change method over up and down unless a complex rollback is needed. Example:

class AddIndexToUsers < ActiveRecord::Migration[7.0]
  def change
    add_index :users, :email, unique: true
  end
end

4. Caching Mechanisms

Page Caching: Stores full HTML response (caches_page :index).

Action Caching: Caches entire actions but checks authentication.

Fragment Caching: Caches parts of a view:

<% cache @user do %>
  <%= render @user.profile %>
<% end %>

SQL Query Caching: Enabled by default in Rails.

5. RESTful API Design

Versioning: /api/v1/users Security Considerations: Use JWT or OAuth2 for authentication.

Add rate limiting with rack-attack.

6. Service Objects for Business Logic

Service objects keep controllers clean:

class UserCreator
  def initialize(user_params)
    @user_params = user_params
  end

  def call
    User.create(@user_params)
  end
end

Benefits: Reusable, testable, and scalable.

7. Nested Routes & Advanced Routing

resources :authors do
  resources :books, only: [:index, :show]
end

Use shallow routes to avoid deep nesting:

resources :books, shallow: true do
  resources :reviews
end
  1. Polymorphic Associations Use when a model can belong to multiple models:
class Comment < ApplicationRecord
  belongs_to :commentable, polymorphic: true
end
Example:

class Post < ApplicationRecord
  has_many :comments, as: :commentable
end

class Video < ApplicationRecord
  has_many :comments, as: :commentable
end

9. N+1 Query Problem & Optimization

Use includes or preload:

Post.includes(:comments).each do |post|
  puts post.comments.count
end

Use bullet gem to detect N+1.

  1. Database Transactions & Performance Wrap operations in transactions:
User.transaction do
  user.update!(balance: user.balance - 100)
  Payment.create!(user: user, amount: 100)
end
Indexing:
add_index :orders, :user_id

11. Caching in a Distributed Rails App

Use Redis as a caching layer.

Use low-level caching with Rails.cache.fetch.

12. Rails Security

CSRF Protection: protect_from_forgery with: :exception

XSS Protection: Use sanitize for user input.

SQL Injection Prevention: Always use ActiveRecord’s query methods:

User.where("email = ?", params[:email]) 13. REST vs. GraphQL REST: Good for simple CRUD APIs.

GraphQL: Good for complex frontends needing flexible data fetching.

14. Scaling Rails

Use read replicas and database sharding.

Move long tasks to background jobs.

15. Handling Concurrency

Use Redis locks to prevent race conditions.

16. Sharding in Rails

Use octopus gem or Rails 6 multiple databases feature.

17. Rails Testing

Unit tests: RSpec or Minitest

Integration tests: Capybara

Performance testing: Benchmark

18. Real-Time Features (ActionCable)

class ChatChannel < ApplicationCable::Channel
  def subscribed
    stream_from "chat_#{params[:room]}"
  end
end

Challenges: Scaling with Redis, handling connections.

19. Refactoring Legacy Rails Code

Use rubocop for code consistency.

Gradually introduce service objects.

20. Rails 6/7 Features

Hotwire (Turbo & Stimulus)

ActionText (Rich Text ing)

ActionMailbox (Incoming Emails Handling)

Ruby-Specific Questions

1. Rack & Middleware

Rack is a lightweight interface between web servers and Ruby frameworks.

Custom Middleware:

class LoggerMiddleware
  def initialize(app)
    @app = app
  end

  def call(env)
    Rails.logger.info "Request received: #{env['PATH_INFO']}"
    @app.call(env)
  end
end

2. N+1 Query

Solved using includes, preload, or eager_load.

3. Concerns in Rails

Use concerns for shared logic:

module Taggable
  extend ActiveSupport::Concern

  included do
    has_many :tags
  end
end

4. HABTM vs HMT

HABTM: Direct many-to-many without extra fields.

HMT: Uses a join model for additional attributes.

5. Class vs. Instance Variables

class User
  @@class_var = "class var"
  @instance_var = "instance var"
end

6. Mutable vs. Immutable in Ruby

Strings are mutable, Numbers & Booleans are immutable.

7. Ruby GC (Garbage Collection)

Ruby uses Mark-and-Sweep Garbage Collection.

8. include vs extend

include adds instance methods.

extend adds class methods.

9. Threads vs. Fibers

Threads: Pre-emptive (run in parallel).

Fibers: Cooperative (manual yielding).

10. Proc vs. Lambda

Lambdas check arity (number of arguments), Procs don’t.

Final Questions

Mass Assignment & Protection:

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

protect_from_forgery with: :exception ActiveRecord Callbacks: before_save, after_commit, etc.

Convention Over Configuration: Rails’ opinionated design.

Difference Between save and save!: save! raises an exception on failure.

Want Mock Interview Practice? 🔥 I can generate Rails coding challenges or mock system design questions! 🚀

Please share the type of associations in rails and how they are formed?

📌 Associations in Rails and How They Are Formed Associations in Rails define relationships between models, allowing efficient data retrieval and manipulation.

  1. belongs_to Association
One-to-One or Many-to-One relationship

The child model holds the foreign key.

Example: A Book belongs to an Author

class Book < ApplicationRecord
  belongs_to :author
end
class Author < ApplicationRecord
  has_many :books
end

The books table must have an author_id column.

Foreign key: author_id in books.

class AddAuthorToBooks < ActiveRecord::Migration[7.0]
  def change
    add_reference :books, :author, foreign_key: true
  end
end

2. has_one Association

One-to-One relationship

The parent model has one associated record.

Example: A User has one Profile


class User < ApplicationRecord
  has_one :profile
end

class Profile < ApplicationRecord
  belongs_to :user
end
Foreign key: user_id in profiles.


class AddUserToProfiles < ActiveRecord::Migration[7.0]
  def change
    add_reference :profiles, :user, foreign_key: true
  end
end

3. has_many Association

One-to-Many relationship

A record has many related records.

Example: An Author has many Books

class Author < ApplicationRecord
  has_many :books
end

class Book < ApplicationRecord
  belongs_to :author
end
Foreign key: author_id in books.

4. has_many :through Association

Many-to-Many relationship with a join table containing additional attributes.

Example: Doctor has many Patients through Appointments

class Doctor < ApplicationRecord
  has_many :appointments
  has_many :patients, through: :appointments
end

class Patient < ApplicationRecord
  has_many :appointments
  has_many :doctors, through: :appointments
end

class Appointment < ApplicationRecord
  belongs_to :doctor
  belongs_to :patient
end
Join table: appointments (with doctor_id and patient_id).

class CreateAppointments < ActiveRecord::Migration[7.0]
  def change
    create_table :appointments do |t|
      t.references :doctor, foreign_key: true
      t.references :patient, foreign_key: true
      t.datetime :appointment_date
      t.timestamps
    end
  end
end

5. has_and_belongs_to_many (HABTM)

Direct Many-to-Many relationship without additional attributes.

Example: Students and Courses

class Student < ApplicationRecord
  has_and_belongs_to_many :courses
end

class Course < ApplicationRecord
  has_and_belongs_to_many :students
end
Requires a join table (courses_students) with no extra columns.

class CreateCoursesStudentsJoinTable < ActiveRecord::Migration[7.0]
  def change
    create_join_table :courses, :students do |t|
      t.index :course_id
      t.index :student_id
    end
  end
end

📝 HABTM vs. has_many :through

Use has_many :through if the join table needs extra columns (e.g., appointments.date).

Use HABTM if the join table is purely relational.

6. polymorphic Association

A model can belong to multiple other models using a single association.

Example: A Comment can belong to both Post and Video

class Comment < ApplicationRecord
  belongs_to :commentable, polymorphic: true
end

class Post < ApplicationRecord
  has_many :comments, as: :commentable
end

class Video < ApplicationRecord
  has_many :comments, as: :commentable
end

The comments table has:

commentable_type (stores "Post" or "Video")

commentable_id (stores the related record’s ID)

class CreateComments < ActiveRecord::Migration[7.0]
  def change
    create_table :comments do |t|
      t.text :body
      t.references :commentable, polymorphic: true, index: true
      t.timestamps
    end
  end
end

7. self-join (Recursive Association)

A model associates with itself.

Example: Employees reporting to a Manager

class Employee < ApplicationRecord
  belongs_to :manager, class_name: "Employee", optional: true
  has_many :subordinates, class_name: "Employee", foreign_key: "manager_id"
end

Foreign key: manager_id in employees.

class AddManagerToEmployees < ActiveRecord::Migration[7.0]
  def change
    add_reference :employees, :manager, foreign_key: { to_table: :employees }
  end
end

Summary Table

Association Type	      Description	                                Example
belongs_to	            Child model holds foreign key	              Book belongs_to Author
has_one	One-to-one	                                                User has_one Profile
has_many	One-to-many	                                              Author has_many Books
has_many :through	Many-to-many with join model	                    Doctor has_many Patients through Appointments
has_and_belongs_to_many (HABTM)	Many-to-many without extra fields	  Students and Courses
polymorphic	Model belongs to multiple types	Comment belongs_to      Post or Video
self-join	Model relates to itself	                                  Employee belongs_to Manager