← Back to all projects

LEARN RUBY THE RIGHT WAY

Learn Ruby: From Scripts to Web Apps

Goal: To learn the Ruby language from its foundations—its elegant syntax, its “everything is an object” philosophy, and its powerful use of blocks—and to apply that knowledge by building real-world command-line tools and web applications.


Why Learn Ruby? The Philosophy of Developer Happiness

Ruby was created by Yukihiro “Matz” Matsumoto in the mid-1990s. His primary goal was to create a language that was fun for programmers to use. It’s optimized for developer productivity and readability, not for raw machine performance.

The Ruby Philosophy in Practice:

  • Everything is an Object: In Ruby, every value is an object, from numbers and strings to nil. This means you can call methods on anything, leading to beautifully expressive code like 5.times { print "Hello!" } or "hello".reverse.
  • Blocks are King: Ruby’s most distinctive feature is its powerful and ubiquitous use of code blocks. They are passed to methods like each, map, and select, allowing you to write concise, declarative code that feels like you’re describing what you want to do, not how to do it.
  • Readability Matters: Ruby code often reads like well-written English. This makes it easier to maintain and for new developers to understand.
  • Metaprogramming and DSLs: Ruby is extremely flexible, allowing you to define and redefine code at runtime. This “metaprogramming” capability is what allows frameworks like Ruby on Rails and testing tools like RSpec to create powerful Domain-Specific Languages (DSLs) that are both concise and expressive.
  • The “Principle of Least Astonishment”: The language is designed to behave in a way that a programmer would expect. While not always perfectly achieved, this guiding principle makes the language feel intuitive.

Ruby vs. Python (A Common Comparison)

Aspect Ruby Python
Philosophy “Developer Happiness.” Designed for beauty, flexibility, and expressiveness. “There should be one– and preferably only one –obvious way to do it.” Emphasizes simplicity and explicitness.
Object Model Pure OOP. Everything is an object. Pragmatic OOP. Has primitive types and functions that are not objects.
Blocks/Lambdas A core, central feature of the language, with a very clean syntax. Lambdas exist but are more limited (single expression). Multi-line anonymous functions are more verbose.
Flexibility Highly flexible. Classes can be modified at runtime (“monkey-patching”). Encourages DSLs. More rigid. Discourages modifying built-in classes.
Web Frameworks Dominated by Ruby on Rails, a powerful, “convention over configuration” framework. Dominated by Django (similar to Rails) and Flask (a minimalist micro-framework).

You learn Ruby when you value rapid development, code elegance, and a language that feels like a sharp tool designed specifically for you, the developer.


Project List

This path will take you from writing simple scripts to building a dynamic, database-backed web application, teaching you the “Ruby way” at each step.


Project 1: The Command-Line Adventure Game

  • File: LEARN_RUBY_THE_RIGHT_WAY.md
  • Main Programming Language: Ruby
  • Alternative Programming Languages: Python, JavaScript (Node.js)
  • Coolness Level: Level 2: Practical but Forgettable
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 1: Beginner
  • Knowledge Area: Ruby Basics / Command-Line I/O
  • Software or Tool: Ruby Interpreter
  • Main Book: “Learn to Program” by Chris Pine

What you’ll build: A simple “choose your own adventure” game that runs in the terminal. The program will present a scenario, ask the user for a choice, and then branch the story based on their input.

Why it teaches the fundamentals: This is the perfect first project. It forces you to use the most basic building blocks of the language: variables, strings, methods, conditional logic (if/else), and user input/output (gets/puts).

Core challenges you’ll face:

  • Printing to the console → maps to using puts and print
  • Getting user input → maps to using gets.chomp to get a string from the user
  • Controlling the story flow → maps to using if/elsif/else statements
  • Organizing code → maps to defining and calling your first methods

Key Concepts:

Difficulty: Beginner Time estimate: Weekend Prerequisites: None. Just have Ruby installed.

Real world outcome: A small, interactive game. You’ll run ruby adventure.rb in your terminal and be able to play through a story you’ve created.

Implementation Hints:

  1. Structure with Methods: Create a method for each “room” or scenario in your story.
    def start_game
      puts "You are in a dark room. There is a door to the north."
      puts "What do you do? (type 'open door')"
      choice = gets.chomp
      if choice == "open door"
        hallway() # Call the next method
      else
        puts "I don't understand that."
        start_game() # Loop back to the beginning of the room
      end
    end
    
    def hallway
      # ... the next part of the story ...
    end
    
    # Start the game
    start_game()
    
  2. Use chomp: gets includes the newline character the user enters. gets.chomp removes it, which is almost always what you want for comparing strings.
  3. Use case statements: For rooms with many choices, a case statement can be cleaner than many elsifs.

Learning milestones:

  1. You can get user input and print a response → You understand basic I/O.
  2. Your game has at least two different branching paths → You’ve mastered if/else.
  3. Your code is organized into at least three methods → You understand how to define and call methods.
  4. The game runs from start to finish without errors → You’ve written your first complete Ruby program.

Project 2: Re-implementing Enumerable Methods

  • File: LEARN_RUBY_THE_RIGHT_WAY.md
  • Main Programming Language: Ruby
  • Alternative Programming Languages: JavaScript (re-implementing Array.prototype methods)
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Ruby / Blocks / Functional Programming
  • Software or Tool: Ruby Interpreter
  • Main Book: “Eloquent Ruby” by Russ Olsen

What you’ll build: You will add several methods to Ruby’s Array class: my_each, my_map, and my_select. These methods will replicate the behavior of the built-in methods, but you will implement them from scratch using basic loops to understand how they work under the hood with blocks.

Why it teaches blocks: This project goes to the very heart of what makes Ruby special. It demystifies the magic of methods like each and map. By building them yourself, you will gain a deep, lasting understanding of yield and how blocks are passed to and executed by methods.

Core challenges you’ll face:

  • Re-opening a core class → maps to understanding Ruby’s open classes
  • Writing a method that accepts a block → maps to the core concept of this project
  • Using yield to execute a block → maps to passing control from your method to the provided block
  • Passing arguments to yield → maps to how each provides each element to its block

Key Concepts:

  • Blocks, Procs, and Lambdas: Ruby-Doc - Blocks and Iterators
  • The yield keyword: The mechanism for calling a block from within a method.
  • Open Classes: In Ruby, you can add methods to existing classes, including built-in ones like Array.

Difficulty: Intermediate Time estimate: Weekend Prerequisites: Project 1.

Real world outcome: You will be able to write code like this and have it work with your custom-built methods:

[1, 2, 3].my_each { |num| puts "Number: #{num}" }

doubled = [1, 2, 3].my_map { |num| num * 2 }
# doubled is now [2, 4, 6]

evens = [1, 2, 3, 4].my_select { |num| num.even? }
# evens is now [2, 4]

Implementation Hints:

  1. Open the Array Class:
    class Array
      # Your methods will go here
    end
    
  2. Implement my_each: This is the foundation. All other enumerable methods can be built using each.
    def my_each
      for i in 0...self.length
        # 'self' is the array instance the method is called on
        element = self[i]
        yield(element) # Pass the element to the block
      end
      self # The original 'each' returns the original array
    end
    
  3. Implement my_map using my_each:
    def my_map
      result = []
      self.my_each do |element|
        # Execute the block and add its return value to our result array
        result << yield(element)
      end
      result
    end
    

Learning milestones:

  1. Your my_each method correctly iterates over an array and yields each element → You understand yield.
  2. Your my_map method returns a new array with the transformed elements → You understand how to capture the return value of yield.
  3. Your my_select method correctly returns a new array with only the filtered elements → You can use yield’s return value for conditional logic.
  4. You feel a deep sense of enlightenment about how Ruby’s iterators work → You’ve unlocked the magic.

Project 3: A Command-Line Blog with File Persistence

  • File: LEARN_RUBY_THE_RIGHT_WAY.md
  • Main Programming Language: Ruby
  • Alternative Programming Languages: Python
  • Coolness Level: Level 2: Practical but Forgettable
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Ruby / OOP / File I/O
  • Software or Tool: Ruby, JSON or YAML standard library
  • Main Book: “Practical Object-Oriented Design in Ruby” by Sandi Metz

What you’ll build: A command-line tool for managing blog posts. You will define Post and Blog classes. The tool will allow you to add new posts, list all existing posts, and, most importantly, save the posts to and load them from a file on your disk using a format like JSON.

Why it teaches OOP and I/O: This project forces you to think in terms of objects and their responsibilities. A Post is responsible for holding title and content. A Blog is responsible for managing a collection of posts. It also introduces the practical and essential skill of data serialization—turning your objects into a storable format and back again.

Core challenges you’ll face:

  • Designing classes and their interfaces → maps to what methods should a Post have? What about a Blog?
  • Managing a collection of objects → maps to using an array within the Blog class to hold Post objects
  • Serializing object data to JSON → maps to using the json standard library to convert your array of posts into a JSON string
  • Deserializing from JSON back into objects → maps to reading the JSON file and recreating your Post objects

Key Concepts:

  • Classes and Objects: The core of OOP in Ruby.
  • File I/O: File.read and File.write.
  • JSON library: require 'json', JSON.parse, JSON.generate.

Difficulty: Intermediate Time estimate: Weekend Prerequisites: Project 2.

Real world outcome: A persistent command-line application. You can add posts, close the program, re-open it, and your posts will still be there.

Implementation Hints:

  1. The Post Class: Keep it simple. It just needs an initialize method and some attr_readers.
    class Post
      attr_reader :title, :content, :timestamp
      def initialize(title, content)
        @title = title
        @content = content
        @timestamp = Time.now
      end
    end
    
  2. The Blog Class: This class will manage the posts.
    require 'json'
    
    class Blog
      def initialize
        @posts = []
      end
      def add_post(post)
        @posts << post
      end
      def list_posts
        @posts.each { |p| puts "#{p.timestamp}: #{p.title}" }
      end
      def save(file_path)
        # You need to convert posts to a simple Hash for JSON
        posts_as_hashes = @posts.map { |p| {title: p.title, content: p.content} }
        File.write(file_path, JSON.generate(posts_as_hashes))
      end
      def load(file_path)
        # ... logic to read the file, parse JSON, and create new Post objects ...
      end
    end
    

Learning milestones:

  1. You can create Post objects and add them to a Blog instance → You understand class instantiation and composition.
  2. You can successfully save your posts to a posts.json file → You’ve mastered serialization.
  3. You can load the program and have it repopulate your blog from the JSON file → You’ve mastered deserialization.
  4. You start thinking about how to separate responsibilities between classes → You’re developing an object-oriented mindset.

Project 4: Your First Web App with Sinatra

  • File: LEARN_RUBY_THE_RIGHT_WAY.md
  • Main Programming Language: Ruby
  • Alternative Programming Languages: Python with Flask, Node.js with Express
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Web Development / HTTP
  • Software or Tool: Sinatra Gem, Bundler
  • Main Book: “Sinatra: Up and Running” by Alan Harris and Konstantin Haase

What you’ll build: A simple, one-page web application version of your blog. It will have a web page that shows a list of current posts and a form that allows you to submit a new post.

Why it teaches web fundamentals: Sinatra is a “micro-framework.” It’s a thin layer over the web’s core protocols, making it perfect for understanding the basics. You’ll learn about HTTP verbs (GET, POST), routes, and how a server responds to a browser request without the heavy magic of a larger framework like Rails.

Core challenges you’ll face:

  • Managing dependencies with Bundler → maps to creating a Gemfile and running bundle install
  • Defining routes for GET and POST requests → maps to get '/' do ... end and post '/new_post' do ... end
  • Rendering HTML with ERB → maps to embedding Ruby code in your HTML templates using <% ... %>
  • Passing data from your Ruby code to your view → maps to using instance variables (@posts) in your route handler

Key Concepts:

  • Bundler: The standard for managing gem dependencies in Ruby.
  • Routing: Matching an incoming URL to a block of code.
  • HTTP Verbs: The difference between GET (requesting data) and POST (submitting data).
  • ERB (Embedded Ruby): The templating system built into Ruby’s standard library.

Difficulty: Advanced Time estimate: Weekend Prerequisites: Project 3. Basic HTML knowledge is helpful.

Real world outcome: A running web server on your local machine. You can open http://localhost:4567 in your browser and interact with a live web application that you built.

Implementation Hints:

  1. Setup:
    • Create a Gemfile with source 'https://rubygems.org' and gem 'sinatra'.
    • Run bundle install.
  2. The App File (app.rb):
    require 'sinatra'
    
    # In-memory "database" for simplicity
    $posts = []
    
    get '/' do
      @posts = $posts
      erb :index # This will render views/index.erb
    end
    
    post '/create_post' do
      title = params['title']
      content = params['content']
      $posts << { title: title, content: content }
      redirect '/' # Send the user back to the homepage
    end
    
  3. The View (views/index.erb):
    <h1>My Blog</h1>
    <% @posts.each do |post| %>
      <div>
        <h2><%= post[:title] %></h2>
        <p><%= post[:content] %></p>
      </div>
    <% end %>
    
    <hr>
    <form action="/create_post" method="POST">
      <input type="text" name="title">
      <textarea name="content"></textarea>
      <button type="submit">Add Post</button>
    </form>
    
  4. Run it: bundle exec ruby app.rb

Learning milestones:

  1. You can run the Sinatra server and see a webpage → You understand the basic web server loop.
  2. Your webpage correctly displays the list of posts → You can pass data from Ruby to an ERB view.
  3. You can submit the form and see the new post appear → You understand the difference between GET and POST requests.
  4. You start to see how a web application is just a program that responds to specific text-based requests → You have demystified the web.

Project 5: The Rails Blog - Convention over Configuration

  • File: LEARN_RUBY_THE_RIGHT_WAY.md
  • Main Programming Language: Ruby
  • Alternative Programming Languages: Python with Django, PHP with Laravel
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 4. The “Open Core” Infrastructure
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Full-Stack Web Development
  • Software or Tool: Ruby on Rails, SQLite3, RSpec
  • Main Book: The Official Ruby on Rails Guides

What you’ll build: A complete, database-backed blog application using Ruby on Rails. It will have multiple pages, allow creating, viewing, editing, and deleting posts, and include data validations (e.g., a title cannot be blank).

Why it teaches the Ruby ecosystem’s power: This project shows you why Ruby became so popular. Rails is a “convention over configuration” framework that makes incredible assumptions to boost your productivity. By building the same blog app for the third time, you’ll be stunned at how much Rails gives you for free.

Core challenges you’ll face:

  • The Rails command-line interface → maps to rails new, rails server, rails generate
  • Understanding the MVC pattern → maps to the roles of Models (database), Views (HTML), and Controllers (logic)
  • Using Active Record for database interaction → maps to writing Post.all or Post.find(params[:id]) instead of SQL
  • Writing your first test with RSpec → maps to adopting the testing culture of the Ruby community

Key Concepts:

  • Convention over Configuration: Rails’ core philosophy.
  • MVC (Model-View-Controller): The architectural pattern Rails is built on.
  • Active Record: The Object-Relational Mapper (ORM) that connects your Ruby classes to database tables.
  • RESTful routing: The conventional way Rails maps HTTP requests to controller actions.

Difficulty: Advanced Time estimate: 1-2 weeks Prerequisites: Project 4.

Real world outcome: A fully functional, professional-grade web application. It will have a real database, follow modern web architecture, and be a solid foundation for any web project you want to build in the future.

Implementation Hints:

  1. Create the app: rails new rails_blog --database=sqlite3.
  2. Generate the Post resource: rails generate scaffold Post title:string content:text. This one command will create the database migration, the Post model, the controller with all actions (index, show, new, create, edit, update, destroy), and all the corresponding view templates. It’s magic.
  3. Run the database migration: rails db:migrate.
  4. Start the server: rails server.
  5. Explore: Open http://localhost:3000/posts in your browser. You have a working application.
  6. Add a Validation and a Test:
    • In app/models/post.rb, add validates :title, presence: true.
    • Set up RSpec (gem 'rspec-rails').
    • In spec/models/post_spec.rb, write a test:
      it "is not valid without a title" do
        post = Post.new(title: nil)
        expect(post).to_not be_valid
      end
      

Learning milestones:

  1. You generate a scaffold and see a working CRUD application appear → You have witnessed the productivity of Rails.
  2. You can explain the role of the Model, View, and Controller in your app → You understand the MVC pattern.
  3. You add a validation to your model and see the application correctly show an error → You understand how Active Record works.
  4. You write a failing test for your validation, make it pass, and feel like a professional developer → You have embraced the Ruby testing culture.

Project Comparison Table

Project Difficulty Time Core Focus Why it’s Important
Command-Line Adventure Level 1: Beginner Weekend Basic Syntax Teaches the absolute fundamentals.
Enumerable Methods Lab Level 2: Intermediate Weekend Blocks & yield Unlocks the “magic” of Ruby’s expressiveness.
CLI Blog Level 2: Intermediate Weekend OOP & File I/O Teaches object design and data persistence.
Sinatra Web App Level 3: Advanced Weekend Web Basics & HTTP Demystifies how web applications work.
Rails Blog Level 3: Advanced 1-2 weeks Full-Stack Framework Shows the power of “convention over configuration.”

Recommendation

This path is designed to be followed sequentially.

  1. Start with the Command-Line Adventure. It’s a fun and easy way to get your feet wet.
  2. Do not skip the Enumerable Methods Lab. It is the single most important project for understanding what makes Ruby “Ruby.”
  3. Progress through the CLI Blog and the Sinatra App. Each one adds a new layer of complexity.
  4. Finally, when you build the Rails Blog, you will have a series of “aha!” moments as you see how Rails automates all the concepts you learned manually in the previous projects.

This journey will give you a deep and practical understanding of the Ruby language and its powerful ecosystem.

Summary

Project Main Programming Language
The Command-Line Adventure Game Ruby
Re-implementing Enumerable Methods Ruby
A Command-Line Blog with File Persistence Ruby
Your First Web App with Sinatra Ruby
The Rails Blog - Convention over Configuration Ruby