← Back to all projects

LEARN RAILS WEB FRAMEWORKS

Learn Ruby on Rails: From Surface to Core

Goal: Deeply understand how Ruby on Rails works under the hood—from the Rack interface to ActiveRecord magic to metaprogramming—and how it compares to other major web frameworks.


Why Learn Rails Internals?

Ruby on Rails didn’t just create a framework; it created a philosophy that influenced every major web framework that came after it. Django, Laravel, Phoenix, Next.js—they all borrowed ideas from Rails.

Understanding Rails deeply teaches you:

  • Convention over Configuration - The philosophy that changed web development
  • Ruby metaprogramming - How “magic” is actually implemented
  • ORM design patterns - ActiveRecord and its trade-offs
  • MVC architecture - The dominant web application pattern
  • Middleware pipelines - How requests flow through frameworks
  • Web framework design - Principles applicable to any language

After completing these projects, you will:

  • Understand every layer from HTTP request to database query to HTML response
  • Know how Rails “magic” works (it’s metaprogramming, not magic)
  • Be able to build your own web framework from scratch
  • Appreciate the trade-offs between Rails, Django, Laravel, and Phoenix
  • Debug Rails applications at any level of the stack

Core Concept Analysis

The Rails Philosophy

┌─────────────────────────────────────────────────────────────────────────────┐
│                          THE RAILS DOCTRINE                                  │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  1. CONVENTION OVER CONFIGURATION (CoC)                                     │
│     └── Sensible defaults eliminate boilerplate                             │
│     └── "If you name things consistently, Rails just works"                 │
│                                                                              │
│  2. DON'T REPEAT YOURSELF (DRY)                                             │
│     └── Every piece of knowledge in one place                               │
│     └── Metaprogramming enables this without copy-paste                     │
│                                                                              │
│  3. PROGRAMMER HAPPINESS                                                     │
│     └── Optimize for developer experience                                   │
│     └── Beautiful code over premature optimization                          │
│                                                                              │
│  4. THE MENU IS OMAKASE                                                      │
│     └── Rails makes choices for you (but you can override)                  │
│     └── One way to do things = shared vocabulary                            │
│                                                                              │
│  5. INTEGRATED SYSTEMS                                                       │
│     └── Full-stack: database to HTML, all coherent                          │
│     └── Not just a "micro" framework                                        │
│                                                                              │
│  6. PROVIDE SHARP KNIVES                                                     │
│     └── Power users get powerful tools                                      │
│     └── Trust developers to use them wisely                                 │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

Request Lifecycle: From HTTP to Response

┌─────────────────────────────────────────────────────────────────────────────┐
│                       RAILS REQUEST LIFECYCLE                                │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  HTTP Request                                                                │
│       │                                                                      │
│       ▼                                                                      │
│  ┌─────────────────────────────────────────────────────────────────────┐    │
│  │ WEB SERVER (Puma, Unicorn, Passenger)                               │    │
│  │ • Parses HTTP request                                               │    │
│  │ • Creates Rack env hash                                             │    │
│  │ • Hands off to Rack interface                                       │    │
│  └───────────────────────────────┬─────────────────────────────────────┘    │
│                                  │                                           │
│                                  ▼                                           │
│  ┌─────────────────────────────────────────────────────────────────────┐    │
│  │ MIDDLEWARE STACK (runs top to bottom)                               │    │
│  │ • ActionDispatch::Static        (serve static files)               │    │
│  │ • Rack::Sendfile                (optimize file serving)            │    │
│  │ • ActionDispatch::Executor      (manage autoloading)               │    │
│  │ • ActiveSupport::Cache          (caching layer)                    │    │
│  │ • Rack::Session::Cookie         (session handling)                 │    │
│  │ • ActionDispatch::Flash         (flash messages)                   │    │
│  │ • ActionDispatch::ContentSecurityPolicy                            │    │
│  │ • ActionDispatch::Callbacks                                        │    │
│  │ • ActionDispatch::Cookies       (cookie handling)                  │    │
│  │ • ActionDispatch::Session       (session store)                    │    │
│  │ • ActionDispatch::RemoteIp      (client IP detection)              │    │
│  │ • Rack::MethodOverride          (RESTful form methods)             │    │
│  │ • ActionDispatch::ShowExceptions (error pages)                     │    │
│  │ • ... (20+ more middleware)                                        │    │
│  └───────────────────────────────┬─────────────────────────────────────┘    │
│                                  │                                           │
│                                  ▼                                           │
│  ┌─────────────────────────────────────────────────────────────────────┐    │
│  │ ROUTER (ActionDispatch::Routing::RouteSet)                          │    │
│  │ • Matches URL pattern to route                                      │    │
│  │ • Extracts params from URL (/users/:id → params[:id])              │    │
│  │ • Identifies controller and action                                  │    │
│  └───────────────────────────────┬─────────────────────────────────────┘    │
│                                  │                                           │
│                                  ▼                                           │
│  ┌─────────────────────────────────────────────────────────────────────┐    │
│  │ CONTROLLER (ActionController::Base)                                 │    │
│  │ • before_action callbacks run                                       │    │
│  │ • Action method executes                                            │    │
│  │ • Interacts with Model layer                                        │    │
│  │ • Sets instance variables for view                                  │    │
│  │ • after_action callbacks run                                        │    │
│  └───────────────────────────────┬─────────────────────────────────────┘    │
│                                  │                                           │
│                        ┌─────────┴─────────┐                                │
│                        │                   │                                │
│                        ▼                   ▼                                │
│  ┌──────────────────────────┐  ┌──────────────────────────┐                │
│  │ MODEL (ActiveRecord)     │  │ VIEW (ActionView)        │                │
│  │ • Query database         │  │ • ERB/HAML template      │                │
│  │ • Run validations        │  │ • Render partials        │                │
│  │ • Execute callbacks      │  │ • Apply layouts          │                │
│  │ • Return objects         │  │ • Generate HTML          │                │
│  └──────────────────────────┘  └──────────────────────────┘                │
│                                            │                                │
│                                            ▼                                │
│  ┌─────────────────────────────────────────────────────────────────────┐    │
│  │ RESPONSE                                                            │    │
│  │ • [status, headers, body] (Rack format)                            │    │
│  │ • Flows back through middleware (reverse order)                    │    │
│  │ • Web server sends to client                                       │    │
│  └─────────────────────────────────────────────────────────────────────┘    │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

Rails Component Architecture

┌─────────────────────────────────────────────────────────────────────────────┐
│                        RAILS COMPONENTS (GEMS)                               │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  ┌─────────────────────────────────────────────────────────────────────┐    │
│  │                          RAILTIES                                    │    │
│  │  • Rails::Application                                               │    │
│  │  • Configuration & initialization                                   │    │
│  │  • Generators                                                       │    │
│  │  • Rake tasks                                                       │    │
│  │  • The "glue" that holds everything together                        │    │
│  └─────────────────────────────────────────────────────────────────────┘    │
│                                    │                                         │
│           ┌────────────────────────┼────────────────────────┐               │
│           │                        │                        │               │
│           ▼                        ▼                        ▼               │
│  ┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐         │
│  │ ACTION PACK     │    │ ACTIVE RECORD   │    │ ACTION VIEW     │         │
│  │                 │    │                 │    │                 │         │
│  │ • Controllers   │    │ • ORM           │    │ • Templates     │         │
│  │ • Routing       │    │ • Migrations    │    │ • Helpers       │         │
│  │ • Middleware    │    │ • Validations   │    │ • Partials      │         │
│  │ • Request/Resp  │    │ • Callbacks     │    │ • Layouts       │         │
│  │ • Parameters    │    │ • Associations  │    │ • Form builders │         │
│  └─────────────────┘    │ • Querying      │    └─────────────────┘         │
│                         │ • Transactions  │                                 │
│                         └─────────────────┘                                 │
│                                    │                                         │
│           ┌────────────────────────┼────────────────────────┐               │
│           │                        │                        │               │
│           ▼                        ▼                        ▼               │
│  ┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐         │
│  │ ACTIVE SUPPORT  │    │ ACTION MAILER   │    │ ACTION CABLE    │         │
│  │                 │    │                 │    │                 │         │
│  │ • Extensions    │    │ • Email sending │    │ • WebSockets    │         │
│  │ • Inflections   │    │ • Views/layouts │    │ • Channels      │         │
│  │ • Time zones    │    │ • Attachments   │    │ • Pub/Sub       │         │
│  │ • Caching       │    │ • Previews      │    │ • Real-time     │         │
│  │ • Notifications │    └─────────────────┘    └─────────────────┘         │
│  │ • Dependencies  │                                                        │
│  └─────────────────┘                                                        │
│                                                                              │
│  ┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐         │
│  │ ACTIVE JOB      │    │ ACTIVE STORAGE  │    │ ACTION TEXT     │         │
│  │                 │    │                 │    │                 │         │
│  │ • Background    │    │ • File uploads  │    │ • Rich text     │         │
│  │ • Queues        │    │ • Cloud storage │    │ • Trix editor   │         │
│  │ • Adapters      │    │ • Variants      │    │ • Attachments   │         │
│  └─────────────────┘    └─────────────────┘    └─────────────────┘         │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

Ruby Metaprogramming: The “Magic” Behind Rails

# How Rails turns this:
class User < ApplicationRecord
  belongs_to :company
  has_many :posts
end

# Into this (conceptually):
class User < ApplicationRecord
  def company
    Company.find(company_id)
  end

  def company=(company)
    self.company_id = company.id
  end

  def posts
    Post.where(user_id: id)
  end

  def posts<<(post)
    post.user_id = id
    post.save
  end

  # ... and dozens more methods
end

Key metaprogramming techniques Rails uses:

Technique What it does Rails usage
method_missing Intercepts calls to undefined methods Dynamic finders (find_by_email)
define_method Creates methods at runtime Association methods, attribute accessors
class_eval Evaluates code in class context Adding methods to models
instance_eval Evaluates code in instance context DSL blocks (config.do_something)
const_missing Intercepts undefined constant access Autoloading classes
included/extended Hooks when module is mixed in Concerns, ActiveSupport::Concern
inherited Hook when class is subclassed ApplicationRecord setup

ActiveRecord Internals

┌─────────────────────────────────────────────────────────────────────────────┐
│                        ACTIVERECORD ARCHITECTURE                             │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  User.where(active: true).order(:name).limit(10)                            │
│       │                                                                      │
│       ▼                                                                      │
│  ┌─────────────────────────────────────────────────────────────────────┐    │
│  │ ActiveRecord::Relation (lazy, chainable query builder)              │    │
│  │                                                                     │    │
│  │ • Doesn't execute until needed (lazy evaluation)                   │    │
│  │ • Each method returns a new Relation                               │    │
│  │ • Stores query components: where_clause, order_values, etc.        │    │
│  └───────────────────────────────┬─────────────────────────────────────┘    │
│                                  │ .to_a, .each, .first, etc.               │
│                                  ▼                                           │
│  ┌─────────────────────────────────────────────────────────────────────┐    │
│  │ Arel (Abstract Relational Algebra)                                  │    │
│  │                                                                     │    │
│  │ • Builds an Abstract Syntax Tree (AST) for SQL                     │    │
│  │ • Database-agnostic representation                                  │    │
│  │ • Example: Arel::Nodes::SelectStatement                            │    │
│  └───────────────────────────────┬─────────────────────────────────────┘    │
│                                  │                                           │
│                                  ▼                                           │
│  ┌─────────────────────────────────────────────────────────────────────┐    │
│  │ Connection Adapter (PostgreSQLAdapter, Mysql2Adapter, etc.)         │    │
│  │                                                                     │    │
│  │ • Converts Arel AST to database-specific SQL                       │    │
│  │ • Manages connection pooling                                        │    │
│  │ • Handles prepared statements                                       │    │
│  │ • Type casting (Ruby ↔ Database)                                   │    │
│  └───────────────────────────────┬─────────────────────────────────────┘    │
│                                  │                                           │
│                                  ▼                                           │
│  ┌─────────────────────────────────────────────────────────────────────┐    │
│  │ Database                                                            │    │
│  │ SELECT "users".* FROM "users"                                      │    │
│  │   WHERE "users"."active" = true                                    │    │
│  │   ORDER BY "users"."name" ASC                                      │    │
│  │   LIMIT 10                                                          │    │
│  └───────────────────────────────┬─────────────────────────────────────┘    │
│                                  │                                           │
│                                  ▼                                           │
│  ┌─────────────────────────────────────────────────────────────────────┐    │
│  │ Instantiation                                                       │    │
│  │                                                                     │    │
│  │ • Each row → User instance                                         │    │
│  │ • Type casting (DB types → Ruby types)                             │    │
│  │ • Attribute assignment                                              │    │
│  │ • Returns array of User objects                                    │    │
│  └─────────────────────────────────────────────────────────────────────┘    │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

Framework Comparison Overview

Aspect Rails (Ruby) Django (Python) Laravel (PHP) Phoenix (Elixir)
Philosophy Convention over Config Explicit is better Elegant syntax Functional + OTP
ORM ActiveRecord (Active Record pattern) Django ORM (Active Record-ish) Eloquent (Active Record) Ecto (Repository pattern)
Real-time Action Cable (WebSockets) Channels (Django 3+) Laravel Echo Phoenix Channels (built-in)
Templates ERB, HAML Django Templates Blade EEx, HEEx
Admin Custom/Gems (Administrate) Django Admin (built-in) Nova (paid), Voyager Custom
Job Queue Active Job + Sidekiq Celery Laravel Queues Oban, Broadway
Auth Devise (gem) django.contrib.auth Laravel Breeze/Jetstream Custom/Libraries
Concurrency Multi-process (Puma threads) Multi-process (WSGI/ASGI) Multi-process (PHP-FPM) BEAM VM (millions of processes)
Learning Curve Moderate Moderate Easy Steeper (functional)
Performance Good Good Good Excellent

Project List

Projects are ordered from fundamentals to advanced implementations, building deep understanding of Rails and web frameworks in general.


Project 1: Rack Application from Scratch (The Foundation)

  • File: LEARN_RAILS_WEB_FRAMEWORKS.md
  • Main Programming Language: Ruby
  • Alternative Programming Languages: N/A (Rack is Ruby-specific)
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Web Servers / HTTP Protocol
  • Software or Tool: Rack, Puma/WEBrick
  • Main Book: “The Well-Grounded Rubyist” by David A. Black

What you’ll build: A minimal web application using only Rack—no Rails, no Sinatra—that handles HTTP requests, parses parameters, manages sessions, and returns responses.

Why it teaches web framework fundamentals: Every Ruby web framework (Rails, Sinatra, Hanami) is built on Rack. Understanding Rack means understanding the foundation everything else is built upon.

Core challenges you’ll face:

  • Understanding the Rack interface → maps to the call method and env hash
  • Parsing HTTP requests → maps to query strings, form data, headers
  • Managing state → maps to cookies and sessions
  • Composing middleware → maps to how Rails middleware stack works

Key Concepts:

  • Rack Specification: Rack GitHub
  • HTTP Basics: “HTTP: The Definitive Guide” by Gourley & Totty
  • Ruby Blocks: “The Well-Grounded Rubyist” Chapter 6 - David A. Black

Difficulty: Intermediate Time estimate: 1 week Prerequisites: Ruby basics, understanding of HTTP

Real world outcome:

# Your minimal Rack app running:
$ rackup config.ru
Puma starting...
* Listening on http://127.0.0.1:9292

# In browser or curl:
$ curl "http://localhost:9292/hello?name=World"
Hello, World!

$ curl -X POST -d "username=alice&password=secret" http://localhost:9292/login
Welcome, alice! Your session ID is abc123

$ curl -b "session_id=abc123" http://localhost:9292/dashboard
Dashboard for alice (authenticated)

Implementation Hints:

The Rack interface is simple—one method, three return values:

# A valid Rack app is ANY object that responds to `call`
class MyApp
  def call(env)
    # env is a Hash with request info:
    # - 'REQUEST_METHOD' => 'GET'
    # - 'PATH_INFO' => '/hello'
    # - 'QUERY_STRING' => 'name=World'
    # - 'rack.input' => IO object (POST body)
    # - ... many more

    status = 200
    headers = { 'Content-Type' => 'text/html' }
    body = ['<h1>Hello, World!</h1>']

    [status, headers, body]
  end
end

# config.ru
run MyApp.new

Building middleware:

# Middleware wraps another app
class Logger
  def initialize(app)
    @app = app
  end

  def call(env)
    puts "#{env['REQUEST_METHOD']} #{env['PATH_INFO']}"
    start = Time.now
    status, headers, body = @app.call(env)
    puts "Completed in #{Time.now - start}s"
    [status, headers, body]
  end
end

# Stack middleware:
use Logger
run MyApp.new

Questions to guide your implementation:

  • What’s in the env hash? (Use pp env to explore)
  • How do you parse query parameters and POST bodies?
  • How do you set and read cookies?
  • How do you implement session storage (in-memory first, then cookies)?

Learning milestones:

  1. Basic request/response works → You understand the Rack interface
  2. You parse GET and POST parameters → You understand HTTP message formats
  3. Sessions persist across requests → You understand cookies/state management
  4. You compose multiple middleware → You understand the middleware pattern

Project 2: Build a Minimal MVC Framework (Understanding Rails)

  • File: LEARN_RAILS_WEB_FRAMEWORKS.md
  • Main Programming Language: Ruby
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Web Framework Design / MVC Pattern
  • Software or Tool: Rack, ERB
  • Main Book: “Rebuilding Rails” by Noah Gibbs

What you’ll build: A mini Rails-like framework with routing, controllers, views (ERB), a basic ORM, and the convention-over-configuration philosophy.

Why it teaches Rails internals: “The most effective way to really understand how things work in Rails is to rebuild it from scratch.” This project demystifies Rails magic by implementing it yourself.

Core challenges you’ll face:

  • Routing DSL → maps to parsing route definitions, matching requests
  • Controller dispatch → maps to instantiating controllers, calling actions
  • View rendering → maps to ERB templates, instance variable passing
  • Convention over Configuration → maps to inferring names, locations

Resources for key challenges:

Key Concepts:

  • MVC Pattern: “Patterns of Enterprise Application Architecture” by Martin Fowler
  • DSL Design: “Metaprogramming Ruby 2” by Paolo Perrotta
  • Template Engines: Ruby ERB documentation

Difficulty: Advanced Time estimate: 3-4 weeks Prerequisites: Project 1, Ruby metaprogramming basics

Real world outcome:

# Your framework in action:

# config/routes.rb
MyFramework.routes do
  get '/', to: 'home#index'
  get '/users', to: 'users#index'
  get '/users/:id', to: 'users#show'
  post '/users', to: 'users#create'
end

# app/controllers/users_controller.rb
class UsersController < MyFramework::Controller
  def index
    @users = User.all
    render :index
  end

  def show
    @user = User.find(params[:id])
    render :show
  end
end

# app/views/users/index.html.erb
<h1>Users</h1>
<% @users.each do |user| %>
  <p><%= user.name %></p>
<% end %>

# It works!
$ curl http://localhost:9292/users/42
<h1>User Profile</h1>
<p>Name: Alice</p>

Implementation Hints:

Router design:

class Router
  def initialize
    @routes = []
  end

  def get(path, to:)
    controller, action = to.split('#')
    @routes << {
      method: 'GET',
      path: compile_path(path),  # Convert /users/:id to regex
      controller: controller,
      action: action
    }
  end

  def match(request)
    @routes.find do |route|
      route[:method] == request.method &&
        route[:path].match?(request.path)
    end
  end

  private

  def compile_path(path)
    # /users/:id → /users/(?<id>[^/]+)
    regex_str = path.gsub(/:(\w+)/, '(?<\1>[^/]+)')
    Regexp.new("^#{regex_str}$")
  end
end

Controller base class:

class Controller
  attr_reader :request, :params

  def initialize(request, params)
    @request = request
    @params = params
  end

  def render(template)
    # Find template file based on controller name and template
    controller_name = self.class.name.gsub('Controller', '').downcase
    path = "app/views/#{controller_name}/#{template}.html.erb"

    # Pass instance variables to template
    erb = ERB.new(File.read(path))
    erb.result(binding)  # `binding` passes all instance vars!
  end
end

Questions to guide your implementation:

  • How do you extract :id from /users/42 and put it in params?
  • How does render find the right template file?
  • How do instance variables from controller become available in view?
  • How would you implement before_action callbacks?

Learning milestones:

  1. Routes match and dispatch → You understand routing
  2. Controllers render views → You understand MVC flow
  3. ERB templates work with variables → You understand view binding
  4. Conventions reduce configuration → You understand Rails philosophy

Project 3: Build an ORM (Understanding ActiveRecord)

  • File: LEARN_RAILS_WEB_FRAMEWORKS.md
  • Main Programming Language: Ruby
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 4: Expert
  • Knowledge Area: ORM Design / Database Patterns
  • Software or Tool: SQLite, Ruby
  • Main Book: “Patterns of Enterprise Application Architecture” by Martin Fowler

What you’ll build: A minimal ORM implementing the Active Record pattern—table-to-class mapping, CRUD operations, dynamic finders, associations (belongs_to, has_many), and basic validations.

Why it teaches ActiveRecord: “The cost of understanding ORM is much higher than simply making use of it.” Building one forces you to understand every abstraction.

Core challenges you’ll face:

  • Table-to-class mapping → maps to inferring table names, column types
  • Dynamic method generation → maps to attribute accessors, finders
  • Query building → maps to chainable where/order/limit
  • Associations → maps to belongs_to, has_many implementation

Key Concepts:

  • Active Record Pattern: “Patterns of Enterprise Application Architecture” Chapter 10 - Fowler
  • Metaprogramming: “Metaprogramming Ruby 2” by Paolo Perrotta
  • SQL Basics: “Learning SQL” by Alan Beaulieu

Difficulty: Expert Time estimate: 3-4 weeks Prerequisites: Projects 1-2, SQL knowledge, Ruby metaprogramming

Real world outcome:

# Your ORM in action:

class User < MyORM::Base
  has_many :posts
  belongs_to :company

  validates :email, presence: true, format: /@/
end

class Post < MyORM::Base
  belongs_to :user
end

# CRUD operations
user = User.create(name: 'Alice', email: 'alice@example.com')
user.update(name: 'Alice Smith')

# Dynamic finders
user = User.find_by_email('alice@example.com')
users = User.where(active: true).order(:name).limit(10)

# Associations
user.posts  # → [Post, Post, ...]
post.user   # → User

# Validations
user = User.new(email: 'invalid')
user.valid?  # → false
user.errors  # → { email: ['is invalid'] }

Implementation Hints:

Base class with table inference:

module MyORM
  class Base
    class << self
      def table_name
        # User → users, BlogPost → blog_posts
        name.gsub(/([a-z])([A-Z])/, '\1_\2').downcase + 's'
      end

      def columns
        @columns ||= db.execute("PRAGMA table_info(#{table_name})").map do |row|
          { name: row['name'], type: row['type'] }
        end
      end

      def find(id)
        row = db.execute("SELECT * FROM #{table_name} WHERE id = ?", id).first
        row ? new(row) : nil
      end

      def all
        db.execute("SELECT * FROM #{table_name}").map { |row| new(row) }
      end

      # Dynamic finders via method_missing
      def method_missing(name, *args)
        if name.to_s.start_with?('find_by_')
          column = name.to_s.sub('find_by_', '')
          where(column.to_sym => args.first).first
        else
          super
        end
      end
    end

    def initialize(attributes = {})
      attributes.each { |k, v| send("#{k}=", v) }
    end
  end
end

Generating attribute accessors dynamically:

class Base
  def self.inherited(subclass)
    # When a class inherits from Base, set up its attributes
    subclass.instance_eval do
      columns.each do |col|
        attr_accessor col[:name].to_sym
      end
    end
  end
end

Chainable query builder:

class Relation
  def initialize(klass)
    @klass = klass
    @where_clauses = []
    @order_clause = nil
    @limit_value = nil
  end

  def where(conditions)
    conditions.each { |k, v| @where_clauses << "#{k} = '#{v}'" }
    self  # Return self for chaining
  end

  def order(column)
    @order_clause = column
    self
  end

  def limit(n)
    @limit_value = n
    self
  end

  def to_sql
    sql = "SELECT * FROM #{@klass.table_name}"
    sql += " WHERE #{@where_clauses.join(' AND ')}" if @where_clauses.any?
    sql += " ORDER BY #{@order_clause}" if @order_clause
    sql += " LIMIT #{@limit_value}" if @limit_value
    sql
  end

  def to_a
    @klass.db.execute(to_sql).map { |row| @klass.new(row) }
  end

  # Delegate enumerable methods
  def each(&block)
    to_a.each(&block)
  end
end

Learning milestones:

  1. Basic CRUD works → You understand SQL generation
  2. Dynamic finders work → You understand method_missing
  3. Chainable queries work → You understand lazy evaluation
  4. Associations work → You understand the Active Record pattern fully

Project 4: Ruby Metaprogramming Deep Dive (The “Magic”)

  • File: LEARN_RAILS_WEB_FRAMEWORKS.md
  • Main Programming Language: Ruby
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Ruby Internals / Metaprogramming
  • Software or Tool: Ruby, IRB
  • Main Book: “Metaprogramming Ruby 2” by Paolo Perrotta

What you’ll build: A collection of Ruby metaprogramming exercises that recreate Rails idioms: attr_accessor, concerns, DSLs like has_many, and method hooks.

Why it teaches Rails magic: When you understand that Rails magic is “just” define_method, method_missing, and class_eval, you can debug anything and extend Rails confidently.

Core challenges you’ll face:

  • Understanding self → maps to class context vs instance context
  • Dynamic method definition → maps to define_method, class_eval
  • Method interception → maps to method_missing, prepend
  • DSL creation → maps to instance_eval, block handling

Key Concepts:

  • Ruby Object Model: “Metaprogramming Ruby 2” Chapters 1-3 - Perrotta
  • Closures and Bindings: “The Well-Grounded Rubyist” Chapter 6 - Black
  • Method Lookup: “Metaprogramming Ruby 2” Chapter 2 - Perrotta

Difficulty: Advanced Time estimate: 2 weeks Prerequisites: Ruby fundamentals, comfort with blocks/procs

Real world outcome:

# You'll implement these from scratch:

# 1. Your own attr_accessor
class Person
  my_attr_accessor :name, :age
end
p = Person.new
p.name = "Alice"
p.name  # → "Alice"

# 2. Your own has_many/belongs_to
class User
  my_has_many :posts
end
class Post
  my_belongs_to :user
end
user.posts  # works!
post.user   # works!

# 3. Your own ActiveSupport::Concern
module Taggable
  extend MyConcern

  included do
    has_many :tags
  end

  def tag_names
    tags.map(&:name)
  end
end

# 4. Your own before_action
class MyController
  my_before_action :authenticate!, only: [:create, :update]
end

Implementation Hints:

Implementing attr_accessor:

class Module
  def my_attr_accessor(*names)
    names.each do |name|
      # Define getter
      define_method(name) do
        instance_variable_get("@#{name}")
      end

      # Define setter
      define_method("#{name}=") do |value|
        instance_variable_set("@#{name}", value)
      end
    end
  end
end

Implementing has_many:

class ActiveRecordBase
  def self.my_has_many(association_name)
    # has_many :posts → defines posts method
    define_method(association_name) do
      # Infer class: :posts → Post
      klass = association_name.to_s.singularize.capitalize.constantize
      # Infer foreign key: User → user_id
      foreign_key = "#{self.class.name.downcase}_id"
      # Query
      klass.where(foreign_key => id)
    end
  end
end

Understanding self in different contexts:

class Foo
  puts self        # → Foo (class context)

  def bar
    puts self      # → #<Foo:0x...> (instance context)
  end

  class << self
    puts self      # → #<Class:Foo> (singleton class)
  end
end

Method lookup chain:

# Ruby looks for methods in this order:
# 1. Singleton class (eigenclass)
# 2. Prepended modules
# 3. The class itself
# 4. Included modules
# 5. Superclass (repeat 1-4)
# 6. BasicObject
# 7. method_missing

Learning milestones:

  1. You implement attr_accessor → You understand define_method
  2. You implement has_many → You understand class-level DSLs
  3. You implement concerns → You understand module hooks
  4. You can explain self in any context → You understand Ruby’s object model

Project 5: Rails from Scratch (Putting It Together)

  • File: LEARN_RAILS_WEB_FRAMEWORKS.md
  • Main Programming Language: Ruby
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 5: Pure Magic
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 4: Expert
  • Knowledge Area: Full Web Framework Implementation
  • Software or Tool: Ruby, Rack, SQLite
  • Main Book: “Rebuilding Rails” by Noah Gibbs

What you’ll build: Combine Projects 1-4 into a complete mini-framework: Rack foundation, routing, controllers, views, ORM, migrations, generators, and a CLI.

Why this is the ultimate Rails-understanding project: You’ll have built every major component of Rails yourself. Nothing will be “magic” anymore.

Core challenges you’ll face:

  • Integrating all components → maps to making pieces work together
  • Adding migrations → maps to schema versioning
  • Building generators → maps to code generation
  • Creating a CLI → maps to command-line interface design

Key Concepts:

  • Integration: How components communicate
  • CLI Design: Thor gem or custom
  • Code Generation: Template-based generators

Difficulty: Expert Time estimate: 4-6 weeks Prerequisites: Projects 1-4 completed

Real world outcome:

# Your framework works like Rails!

$ ./bin/myframework new blog
Creating new application: blog
      create  blog/
      create  blog/app/controllers/
      create  blog/app/models/
      create  blog/app/views/
      create  blog/config/routes.rb
      create  blog/db/
      create  blog/Gemfile
Done!

$ cd blog
$ ./bin/myframework generate model Post title:string body:text
      create  app/models/post.rb
      create  db/migrate/20240101_create_posts.rb

$ ./bin/myframework db:migrate
Migrating...
  20240101_create_posts.rb
Done!

$ ./bin/myframework server
Starting server on http://localhost:3000

Implementation Hints:

CLI structure:

# bin/myframework
#!/usr/bin/env ruby
require_relative '../lib/my_framework'

command = ARGV[0]

case command
when 'new'
  MyFramework::Generators::AppGenerator.new(ARGV[1]).run
when 'generate', 'g'
  type = ARGV[1]  # 'model', 'controller', etc.
  MyFramework::Generators.run(type, ARGV[2..])
when 'server', 's'
  MyFramework::Server.start
when 'db:migrate'
  MyFramework::Migrator.run
end

Migration system:

class Migrator
  def self.run
    pending_migrations.each do |migration_file|
      require migration_file
      # File: 20240101_create_posts.rb defines CreatePosts
      class_name = File.basename(migration_file, '.rb')
                       .split('_')[1..].map(&:capitalize).join
      klass = Object.const_get(class_name)
      klass.new.up
      record_migration(migration_file)
    end
  end

  def self.pending_migrations
    all_migrations - completed_migrations
  end
end

Autoloading (simplified Zeitwerk):

# When a constant is missing, try to load it
def Object.const_missing(name)
  # User → app/models/user.rb
  path = name.to_s.gsub(/([a-z])([A-Z])/, '\1_\2').downcase
  require "app/models/#{path}"
  const_get(name)
rescue LoadError
  super
end

Learning milestones:

  1. New app generator works → You understand project structure
  2. Migrations create tables → You understand schema management
  3. Server runs your app → You’ve integrated everything
  4. You can build a blog → Your framework is functional!

Project 6: Compare by Building (Django-style Framework)

  • File: LEARN_RAILS_WEB_FRAMEWORKS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Framework Comparison / Python
  • Software or Tool: Python, WSGI
  • Main Book: “Two Scoops of Django” by Greenfeld & Roy

What you’ll build: A minimal Django-like framework in Python—WSGI interface, URL routing, views (functions or classes), templates, and ORM—to understand Django’s design choices.

Why it teaches framework design: Django makes different choices than Rails. Building a Django-style framework reveals why those choices exist and their trade-offs.

Core challenges you’ll face:

  • WSGI vs Rack → maps to similar concepts, different syntax
  • Explicit over implicit → maps to Django’s philosophy vs Rails’ CoC
  • URLconf routing → maps to URL patterns and view dispatch
  • Template language → maps to Django’s sandboxed templates vs ERB

Key Concepts:

  • WSGI: PEP 3333
  • Django Philosophy: “Two Scoops of Django” Introduction
  • Python ORM patterns: Django ORM documentation

Difficulty: Advanced Time estimate: 3 weeks Prerequisites: Projects 1-5, Python basics

Real world outcome:

# Your Django-style framework:

# urls.py
urlpatterns = [
    path('', views.home, name='home'),
    path('users/', views.user_list, name='user-list'),
    path('users/<int:id>/', views.user_detail, name='user-detail'),
]

# views.py
def user_list(request):
    users = User.objects.all()
    return render(request, 'users/list.html', {'users': users})

def user_detail(request, id):
    user = User.objects.get(id=id)
    return render(request, 'users/detail.html', {'user': user})

# models.py
class User(Model):
    name = CharField(max_length=100)
    email = EmailField()

    class Meta:
        db_table = 'users'

Implementation Hints:

WSGI application:

def application(environ, start_response):
    # environ is like Rack's env hash
    path = environ['PATH_INFO']
    method = environ['REQUEST_METHOD']

    # Match URL to view
    view, kwargs = router.match(path)
    request = Request(environ)

    response = view(request, **kwargs)

    start_response(response.status, response.headers)
    return [response.body.encode()]

Key differences to note:

Rails (Ruby)                    Django (Python)
──────────────────────────────  ──────────────────────────────
Convention over Configuration   Explicit is better than implicit
routes.rb (DSL)                 urls.py (Python code)
Controllers are classes         Views are functions (or classes)
ERB (full Ruby access)          Templates (sandboxed, limited)
Implicit rendering              Explicit return render()
Migrations auto-detect          Migrations from makemigrations
belongs_to :user                user = ForeignKey(User, ...)

Learning milestones:

  1. WSGI app works → You understand Python’s web interface
  2. URL routing works → You see Django’s pattern system
  3. Templates work → You understand sandboxed templates
  4. ORM works → You see explicit field definitions

Project 7: Compare by Building (Laravel-style in PHP)

  • File: LEARN_RAILS_WEB_FRAMEWORKS.md
  • Main Programming Language: PHP
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Framework Comparison / PHP
  • Software or Tool: PHP 8+, Composer
  • Main Book: “Laravel: Up & Running” by Matt Stauffer

What you’ll build: A minimal Laravel-like framework—routing, controllers, Blade-like templates, Eloquent-like ORM—to understand Laravel’s refinements on Rails ideas.

Why it teaches framework evolution: Laravel took Rails ideas and refined them for PHP developers. Understanding Laravel’s choices shows how frameworks evolve.

Core challenges you’ll face:

  • PHP’s unique characteristics → maps to request lifecycle, autoloading
  • Facades → maps to static-like access to services
  • Blade templates → maps to compilation-based templates
  • Eloquent → maps to Active Record with modern PHP

Key Concepts:

  • PHP Autoloading: PSR-4 standard
  • Service Container: Dependency injection
  • Laravel Design: “Laravel: Up & Running” Chapters 1-3

Difficulty: Advanced Time estimate: 3 weeks Prerequisites: Projects 1-5, PHP basics

Real world outcome:

// Your Laravel-style framework:

// routes/web.php
Route::get('/', [HomeController::class, 'index']);
Route::resource('users', UserController::class);

// app/Controllers/UserController.php
class UserController extends Controller
{
    public function index()
    {
        $users = User::all();
        return view('users.index', ['users' => $users]);
    }

    public function show($id)
    {
        $user = User::findOrFail($id);
        return view('users.show', ['user' => $user]);
    }
}

// app/Models/User.php
class User extends Model
{
    protected $fillable = ['name', 'email'];

    public function posts()
    {
        return $this->hasMany(Post::class);
    }
}

Implementation Hints:

Service Container (simplified):

class Container {
    private array $bindings = [];

    public function bind(string $abstract, callable $concrete) {
        $this->bindings[$abstract] = $concrete;
    }

    public function make(string $abstract) {
        if (isset($this->bindings[$abstract])) {
            return $this->bindings[$abstract]($this);
        }
        // Auto-resolve via reflection
        return $this->resolve($abstract);
    }

    private function resolve(string $class) {
        $reflection = new ReflectionClass($class);
        $constructor = $reflection->getConstructor();
        // Recursively resolve dependencies...
    }
}

Facades (static access to container):

class Facade {
    protected static Container $container;

    public static function __callStatic($method, $args) {
        $instance = static::$container->make(static::getFacadeAccessor());
        return $instance->$method(...$args);
    }
}

class DB extends Facade {
    protected static function getFacadeAccessor() {
        return 'database';
    }
}

// Usage: DB::table('users')->get()
// Actually: $container->make('database')->table('users')->get()

Learning milestones:

  1. Router works → You understand PHP’s request handling
  2. Service container works → You understand DI containers
  3. Eloquent ORM works → You see modern PHP ORM design
  4. You compare with Rails → You understand trade-offs

Project 8: Compare by Building (Phoenix-style in Elixir)

  • File: LEARN_RAILS_WEB_FRAMEWORKS.md
  • Main Programming Language: Elixir
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 5: Pure Magic
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 4: Expert
  • Knowledge Area: Functional Web Frameworks / Concurrency
  • Software or Tool: Elixir, Phoenix, Ecto
  • Main Book: “Programming Phoenix” by Chris McCord

What you’ll build: A minimal Phoenix-like framework understanding—Plug (like Rack), Router, Controllers, Templates (EEx), and Ecto (repository pattern ORM).

Why it teaches modern framework design: Phoenix represents a different paradigm—functional programming, immutability, and the BEAM’s concurrency model. It shows how to rethink Rails ideas for a functional language.

Core challenges you’ll face:

  • Functional programming → maps to immutability, pipelines
  • Plug middleware → maps to Elixir’s Rack equivalent
  • Ecto’s Repository pattern → maps to different ORM approach than Active Record
  • Concurrency model → maps to actors, processes, fault tolerance

Key Concepts:

  • Elixir Basics: “Programming Elixir” by Dave Thomas
  • Phoenix Architecture: “Programming Phoenix” by McCord et al.
  • Ecto: “Programming Ecto” by Darin Wilson

Difficulty: Expert Time estimate: 4 weeks Prerequisites: Projects 1-7, functional programming concepts

Real world outcome:

# Your understanding of Phoenix patterns:

# Router
scope "/", MyApp do
  pipe_through :browser

  get "/", PageController, :index
  resources "/users", UserController
end

# Controller
defmodule MyApp.UserController do
  use MyApp, :controller

  def index(conn, _params) do
    users = Accounts.list_users()
    render(conn, :index, users: users)
  end

  def show(conn, %{"id" => id}) do
    user = Accounts.get_user!(id)
    render(conn, :show, user: user)
  end
end

# Context (not controller!)
defmodule MyApp.Accounts do
  def list_users do
    Repo.all(User)
  end

  def get_user!(id) do
    Repo.get!(User, id)
  end

  def create_user(attrs) do
    %User{}
    |> User.changeset(attrs)
    |> Repo.insert()
  end
end

Key differences from Rails:

Rails (Ruby, OOP)                Phoenix (Elixir, FP)
──────────────────────────────   ──────────────────────────────
ActiveRecord (Active Record)     Ecto (Repository pattern)
user.save                        Repo.insert(changeset)
Mutable objects                  Immutable data
@user in controller/view         Explicit assigns
Classes with state               Modules with functions
Threads (limited)                Millions of processes
Rails.cache                      ETS tables
ActionCable (bolted on)          Channels (built-in, first-class)

Implementation Hints:

Plug (Elixir’s Rack):

defmodule MyPlug do
  def init(opts), do: opts

  def call(conn, _opts) do
    conn
    |> put_resp_content_type("text/html")
    |> send_resp(200, "<h1>Hello!</h1>")
  end
end

Ecto changeset (validation):

defmodule User do
  use Ecto.Schema

  schema "users" do
    field :name, :string
    field :email, :string
    timestamps()
  end

  def changeset(user, attrs) do
    user
    |> cast(attrs, [:name, :email])
    |> validate_required([:name, :email])
    |> validate_format(:email, ~r/@/)
    |> unique_constraint(:email)
  end
end

# Usage: Repo.insert(User.changeset(%User{}, params))

Learning milestones:

  1. Plug pipeline works → You understand functional middleware
  2. Ecto queries work → You understand Repository pattern
  3. Channels work → You understand real-time in functional style
  4. You appreciate the differences → You can choose the right tool

Project 9: Real-Time Features (Action Cable Deep Dive)

  • File: LEARN_RAILS_WEB_FRAMEWORKS.md
  • Main Programming Language: Ruby (Rails)
  • Alternative Programming Languages: JavaScript (client)
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 3: Advanced
  • Knowledge Area: WebSockets / Real-Time Web
  • Software or Tool: Rails, Redis, JavaScript
  • Main Book: “The Rails 5 Way” by Obie Fernandez

What you’ll build: A real-time chat application diving deep into Action Cable internals—understanding WebSocket connections, channels, pub/sub, and broadcasting.

Why it teaches real-time web: WebSockets are essential for modern apps. Understanding Action Cable teaches you how Rails integrates real-time features.

Core challenges you’ll face:

  • WebSocket lifecycle → maps to connection, subscription, messages
  • Pub/Sub pattern → maps to Redis, broadcasting
  • JavaScript client → maps to consumer, subscriptions
  • Authentication → maps to identifying connections

Key Concepts:

  • WebSocket Protocol: RFC 6455
  • Action Cable: Rails Guides
  • Redis Pub/Sub: Redis documentation

Difficulty: Advanced Time estimate: 2 weeks Prerequisites: Rails basics, JavaScript

Real world outcome:

# Chat room with Action Cable:

# app/channels/chat_channel.rb
class ChatChannel < ApplicationCable::Channel
  def subscribed
    stream_from "chat_#{params[:room]}"
  end

  def receive(data)
    message = Message.create!(
      user: current_user,
      room: params[:room],
      content: data['message']
    )

    ActionCable.server.broadcast(
      "chat_#{params[:room]}",
      message: render_message(message)
    )
  end

  private

  def render_message(message)
    ApplicationController.render(
      partial: 'messages/message',
      locals: { message: message }
    )
  end
end

# In browser console:
subscription = App.cable.subscriptions.create(
  { channel: "ChatChannel", room: "general" },
  {
    received(data) {
      document.getElementById('messages').innerHTML += data.message
    }
  }
)
subscription.send({ message: "Hello, world!" })

Implementation Hints:

Action Cable architecture:

┌─────────────────────────────────────────────────────────────────┐
│                     ACTION CABLE ARCHITECTURE                    │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Browser                        Rails Server                     │
│  ┌────────────────────┐        ┌────────────────────┐           │
│  │ JavaScript Consumer│◄──────▶│ Connection (per ws)│           │
│  │                    │  WS    │ • identified_by    │           │
│  │ • subscriptions    │        │ • current_user     │           │
│  │ • received(data)   │        └─────────┬──────────┘           │
│  │ • send(data)       │                  │                      │
│  └────────────────────┘                  │                      │
│                                          │                      │
│                               ┌──────────▼──────────┐           │
│                               │ Channel (per sub)   │           │
│                               │ • subscribed        │           │
│                               │ • unsubscribed      │           │
│                               │ • stream_from       │           │
│                               │ • receive           │           │
│                               └──────────┬──────────┘           │
│                                          │                      │
│                               ┌──────────▼──────────┐           │
│                               │ Redis Pub/Sub       │           │
│                               │ • Broadcast messages│           │
│                               │ • Multi-server sync │           │
│                               └─────────────────────┘           │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Connection authentication:

module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user = find_verified_user
    end

    private

    def find_verified_user
      if (user = User.find_by(id: cookies.signed[:user_id]))
        user
      else
        reject_unauthorized_connection
      end
    end
  end
end

Learning milestones:

  1. Basic chat works → You understand channels
  2. Multi-room works → You understand streaming
  3. Works with multiple servers → You understand Redis pub/sub
  4. Authentication works → You understand connection identification

Project 10: Rails Performance & Internals

  • File: LEARN_RAILS_WEB_FRAMEWORKS.md
  • Main Programming Language: Ruby (Rails)
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 4: Expert
  • Knowledge Area: Performance / Profiling / Internals
  • Software or Tool: Rails, rack-mini-profiler, bullet
  • Main Book: “The Complete Guide to Rails Performance” by Nate Berkopec

What you’ll build: A performance analysis toolkit—understanding Rails internals through profiling, identifying N+1 queries, memory bloat, and cache strategies.

Why it teaches Rails deeply: Performance problems force you to understand what Rails actually does. You’ll trace through Rails source code and understand every allocation.

Core challenges you’ll face:

  • N+1 query detection → maps to understanding eager loading
  • Memory profiling → maps to object allocation, GC
  • Request profiling → maps to what takes time
  • Caching strategies → maps to fragment, Russian doll, low-level

Key Concepts:

  • Rails Performance: “The Complete Guide to Rails Performance” - Berkopec
  • Ruby GC: “Ruby Performance Optimization” by Alexander Dymo
  • Database Optimization: “High Performance MySQL” (concepts apply)

Difficulty: Expert Time estimate: 3 weeks Prerequisites: All previous projects, production Rails experience

Real world outcome:

# Your profiling output:

$ rails performance:analyze

Request: GET /users
Total time: 245ms
  Database: 180ms (12 queries - N+1 DETECTED!)
  View rendering: 45ms
  Ruby: 20ms

N+1 Queries detected:
  User.all → then user.posts for each user
  Fix: User.includes(:posts).all

Memory allocations: 15,234 objects
  String: 8,432
  Array: 3,211
  Hash: 2,101
  User: 500

Top 5 slow methods:
  1. ActiveRecord::Result#each (45ms)
  2. ERB::Compiler#compile (23ms)
  3. ActionView::Template#render (18ms)
  4. JSON.parse (12ms)
  5. User#full_name (8ms)

Recommendations:
  1. Add .includes(:posts) to fix N+1
  2. Cache rendered partials
  3. Use find_each for large collections

Implementation Hints:

Understanding Rails internals with TracePoint:

# Trace all method calls in a request
trace = TracePoint.new(:call) do |tp|
  if tp.defined_class.to_s.start_with?('ActiveRecord')
    puts "#{tp.defined_class}##{tp.method_id}"
  end
end

trace.enable do
  User.find(1)
end
# Output shows every AR method called!

Query analysis:

# See what SQL is generated
ActiveRecord::Base.logger = Logger.new(STDOUT)

# Or analyze queries programmatically
queries = []
callback = ->(name, start, finish, id, payload) {
  queries << payload[:sql] if payload[:sql]
}

ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do
  User.includes(:posts).where(active: true).to_a
end

puts "Queries executed: #{queries.count}"
queries.each { |q| puts q }

Memory profiling:

require 'memory_profiler'

report = MemoryProfiler.report do
  1000.times { User.create(name: "Test") }
end

report.pretty_print
# Shows allocated objects by gem, location, class

Learning milestones:

  1. You can find N+1 queries → You understand eager loading
  2. You can profile memory → You understand Ruby allocations
  3. You can trace Rails internals → You understand the source code
  4. You can optimize real apps → You’re a Rails performance expert

Project Comparison Table

Project Difficulty Time Depth of Understanding Fun Factor
1. Rack Application ⭐⭐ 1 week ⚡⚡⚡ 🎮🎮🎮
2. Minimal MVC Framework ⭐⭐⭐ 3-4 weeks ⚡⚡⚡⚡⚡ 🎮🎮🎮🎮
3. Build an ORM ⭐⭐⭐⭐ 3-4 weeks ⚡⚡⚡⚡⚡ 🎮🎮🎮🎮
4. Metaprogramming Deep Dive ⭐⭐⭐ 2 weeks ⚡⚡⚡⚡⚡ 🎮🎮🎮🎮🎮
5. Rails from Scratch ⭐⭐⭐⭐ 4-6 weeks ⚡⚡⚡⚡⚡ 🎮🎮🎮🎮🎮
6. Django-style (Python) ⭐⭐⭐ 3 weeks ⚡⚡⚡⚡ 🎮🎮🎮
7. Laravel-style (PHP) ⭐⭐⭐ 3 weeks ⚡⚡⚡⚡ 🎮🎮🎮
8. Phoenix-style (Elixir) ⭐⭐⭐⭐ 4 weeks ⚡⚡⚡⚡⚡ 🎮🎮🎮🎮🎮
9. Action Cable Deep Dive ⭐⭐⭐ 2 weeks ⚡⚡⚡⚡ 🎮🎮🎮🎮
10. Rails Performance ⭐⭐⭐⭐ 3 weeks ⚡⚡⚡⚡⚡ 🎮🎮🎮🎮

Your Starting Point

If you’re a Rails user wanting to understand the magic: Projects 1 → 2 → 3 → 4 → 5 (Build from scratch)

If you’re comparing frameworks for a project: Projects 1 → 6 → 7 → 8 (Build similar things in each)

If you’re performance-focused: Projects 1 → 2 → 3 → 10 (Understand then optimize)

Phase 1: Foundation (1-2 weeks)
└── Project 1: Rack Application → Understand the HTTP interface

Phase 2: Rails Core (6-10 weeks)
├── Project 2: MVC Framework → Routing, controllers, views
├── Project 3: ORM → ActiveRecord's secrets
└── Project 4: Metaprogramming → How the magic works

Phase 3: Integration (4-6 weeks)
└── Project 5: Rails from Scratch → Put it all together

Phase 4: Comparison (9-11 weeks)
├── Project 6: Django-style → Python's approach
├── Project 7: Laravel-style → PHP's refinements
└── Project 8: Phoenix-style → Functional paradigm

Phase 5: Mastery (5 weeks)
├── Project 9: Action Cable → Real-time Rails
└── Project 10: Performance → Production optimization

Final Project: Production-Grade Web Application

  • File: LEARN_RAILS_WEB_FRAMEWORKS.md
  • Main Programming Language: Ruby (Rails)
  • Alternative Programming Languages: JavaScript (frontend)
  • Coolness Level: Level 5: Pure Magic
  • Business Potential: 4. The “Open Core” Infrastructure
  • Difficulty: Level 5: Master
  • Knowledge Area: Full-Stack Web Development
  • Software or Tool: Rails, PostgreSQL, Redis, Sidekiq
  • Main Book: “Sustainable Web Development with Ruby on Rails” by David Copeland

What you’ll build: A complete, production-ready SaaS application demonstrating mastery of Rails—authentication, authorization, background jobs, caching, API, real-time features, and deployment.

Why this is the ultimate project: This combines everything: deep Rails knowledge, performance optimization, real-world architecture decisions, and production deployment.

Core features:

  • Multi-tenant SaaS with organizations
  • Authentication (Devise or custom)
  • Authorization (Pundit or custom policies)
  • Background jobs (Sidekiq)
  • Real-time updates (Action Cable)
  • API (RESTful + optionally GraphQL)
  • Admin dashboard
  • Caching (fragment, Russian doll)
  • Full test suite (RSpec)
  • CI/CD pipeline
  • Production deployment

Difficulty: Master Time estimate: 2-3 months Prerequisites: All 10 projects completed

Real world outcome:

Your SaaS application:

┌─────────────────────────────────────────────────────────────────┐
│                    PROJECT MANAGEMENT SAAS                       │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Features:                                                       │
│  ✓ Multi-tenant (organization-based)                            │
│  ✓ User authentication with 2FA                                 │
│  ✓ Role-based permissions                                       │
│  ✓ Real-time project updates                                    │
│  ✓ Background job processing                                    │
│  ✓ RESTful API with documentation                               │
│  ✓ Comprehensive test coverage (>95%)                           │
│  ✓ Performance-optimized (<100ms p95)                           │
│  ✓ Deployed to production (Heroku/AWS)                          │
│                                                                  │
│  Architecture decisions documented:                              │
│  • Why Rails over Django/Laravel                                │
│  • Service objects vs fat models                                │
│  • Caching strategy                                             │
│  • Real-time architecture                                       │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Essential Resources

Books (Primary)

Book Author Best For
Rebuilding Rails Noah Gibbs Start here for understanding Rails
Metaprogramming Ruby 2 Paolo Perrotta Ruby’s magic techniques
The Rails 7 Way Obie Fernandez Comprehensive Rails reference
The Complete Guide to Rails Performance Nate Berkopec Performance optimization
Programming Phoenix Chris McCord Phoenix for comparison
Two Scoops of Django Greenfeld & Roy Django for comparison

Online Resources

Resource URL Description
Rails Guides guides.rubyonrails.org Official documentation
Rails Source github.com/rails/rails Read the actual code
RubyMonk rubymonk.com Metaprogramming tutorials
The Odin Project theodinproject.com Full Rails curriculum
GoRails gorails.com Video tutorials

Comparison Articles

Resource URL
Matt Schultz Framework Comparison matt.fyi
Rails vs Django vs Laravel StackShare

Summary

# Project Main Language Knowledge Area
1 Rack Application Ruby Web Servers / HTTP Protocol
2 Minimal MVC Framework Ruby Web Framework Design / MVC
3 Build an ORM Ruby ORM Design / Database Patterns
4 Metaprogramming Deep Dive Ruby Ruby Internals / Metaprogramming
5 Rails from Scratch Ruby Full Web Framework Implementation
6 Django-style Framework Python Framework Comparison / Python
7 Laravel-style Framework PHP Framework Comparison / PHP
8 Phoenix-style (Elixir) Elixir Functional Web Frameworks
9 Action Cable Deep Dive Ruby WebSockets / Real-Time Web
10 Rails Performance Ruby Performance / Profiling
Final Production SaaS Ruby Full-Stack Web Development

Getting Started Checklist

Before starting Project 1:

  • Ruby installed (3.0+): ruby -v
  • Bundler installed: gem install bundler
  • Read Ruby basics if needed (blocks, procs, classes)
  • Understand HTTP basics (methods, headers, status codes)
  • Install a database (SQLite for learning, PostgreSQL for production)
  • Read “Rack basics” section of Rack documentation

Welcome to the world of web framework internals! 🚀


Generated for deep understanding of Ruby on Rails and web framework design