Skip to content

Complete Ruby Programming Study Guide

flowchart TD
    A[Hub] --> B[Key Concepts]
    A --> C[Core Principles]
    A --> D[Practical Applications]
    B --> E[Fundamental definitions]
    C --> F[Design patterns]
    D --> G[Real-world usage]

Ruby is a dynamic, object-oriented language designed for developer happiness. Its elegant syntax, powerful metaprogramming, and the Rails framework made it one of the most influential languages in web development. Ruby prioritizes readability and expressiveness, enabling developers to write code that reads like natural language.

This hub page maps every resource on this site. The learning path takes you from Ruby’s core language features through Rails, testing, and metaprogramming, building a thorough understanding of how Ruby works and how to write idiomatic, maintainable code.


Ruby’s fundamentals are designed for simplicity and expressiveness. Everything is an object, including numbers, strings, and booleans. Understanding Ruby’s syntax, data types, and control flow is the foundation for all Ruby programming.

Everything is an object — In Ruby, integers have methods, strings have methods, and even nil has methods. This makes the language consistent — you can call methods on anything. 5.times { puts "hello" } is valid Ruby.

Symbols are immutable, interned strings. They are frequently used as hash keys and method names because they are memory-efficient and fast to compare. Symbols are written with a colon prefix: :name, :status.

Iterators replace traditional for loops. Ruby’s each, map, select, and reject methods are more expressive and less error-prone than index-based loops. Ruby encourages functional-style iteration over imperative loops.


Ruby is a pure object-oriented language. Every value is an object, and every operation is a method call. Understanding classes, modules, mixins, and inheritance is essential for writing idiomatic Ruby.

Modules serve two purposes: namespaces and mixins. As namespaces, modules group related classes and methods. As mixins, modules add behavior to classes without inheritance. include adds instance methods; extend adds class methods.

Duck typing — In Ruby, you do not care about an object’s type, only whether it responds to the methods you need. If an object quacks like a duck, it is treated as a duck. This enables flexible, loosely-coupled designs.

Attr accessorsattr_reader, attr_writer, and attr_accessor generate getter and setter methods automatically. They eliminate the boilerplate of manual method definitions for simple property access.


Blocks, Procs, and Lambdas are Ruby’s tools for passing code as arguments. They enable functional programming patterns, iterators, and callback mechanisms. Understanding the differences between them is essential for writing idiomatic Ruby.

Blocks are chunks of code passed to methods. They are written with do/end or {}. The yield keyword calls the block from within the method. Blocks are not objects — they are syntactic sugar for passing code to a method.

Procs are objects that wrap blocks. Proc.new { puts "hello" } creates a Proc object that can be stored, passed, and called with .call. Procs do not check argument counts and have lenient arity.

Lambdas are strict Procs. They check argument counts and return from the lambda, not the enclosing method. lambda { |x| x * 2 } creates a lambda. Use lambdas when you need strict argument checking and predictable return behavior.


Ruby has a strong testing culture. RSpec is the most popular testing framework, providing a DSL for expressive, readable tests. Testing is integral to Ruby development and Rails.

RSpec uses a describe/it structure for organizing tests. expect(value).to eq(expected) asserts the expected result. RSpec matchers provide readable assertions: be_nil, include, have_attributes.

Test doubles replace real objects in tests. Stubs return predefined values. Mocks verify that methods were called. They isolate the code under test from external dependencies — databases, APIs, and file systems.

FactoryBot creates test objects with predefined attributes. Factories replace fixture files and make test data creation flexible. Traits, sequences, and associations handle complex object graphs.


Ruby on Rails is a full-stack web framework that emphasizes convention over configuration. Rails provides everything needed for web development: routing, controllers, views, database access, and deployment. Rails has shaped modern web frameworks across all languages.

Convention over configuration — Rails makes assumptions about file names, database table names, and routing. A model named Post maps to the posts table. This eliminates configuration boilerplate and keeps code organized.

Active Record is Rails’ ORM (Object-Relational Mapper). Each model class maps to a database table. Associations (has_many, belongs_to, has_and_belongs_to_many) define relationships. Validations ensure data integrity at the model level.

Migrations are version-controlled database schema changes. rails generate migration AddEmailToUsers email:string creates a migration that adds an email column to the users table. Migrations are reversible and can be applied or rolled back.


Ruby’s metaprogramming capabilities allow you to write code that writes code. Methods can be defined dynamically, classes can be modified at runtime, and the language itself can be extended. Metaprogramming is powerful but should be used judiciously.

  • Dynamic Methods — define_method, method_missing, and respond_to_missing?
  • Open Classes — monkey patching and the risks
  • DSLs — building domain-specific languages with Ruby
  • Reflection — class, methods, instance_variables, and send

define_method creates methods dynamically. define_method(:greet) { |name| "Hello, #{name}" } adds a greet method to the class. This enables DRY code when you need similar methods with slight variations.

method_missing intercepts calls to undefined methods. Override it to handle dynamic method names. Always implement respond_to_missing? alongside method_missing to ensure proper behavior with respond_to?.

Open classes let you modify existing classes at any time. You can add methods, override behavior, and extend core classes. This is powerful but dangerous — monkey patching can cause subtle bugs. Modify classes only when you have a compelling reason.


Ruby is designed for developer happiness. Its learning curve is gentle compared to most languages.

  • Learn variables, types, control flow, and strings
  • Understand arrays, hashes, and iterators
  • Write small programs using classes and objects
  • Master blocks, Procs, and lambdas
  • Learn modules, mixins, and duck typing
  • Study the standard library methods
  • Learn RSpec and FactoryBot
  • Study Rails MVC architecture and Active Record
  • Build a complete web application

Stage 4: Metaprogramming and Advanced (Weeks 12–14)

Section titled “Stage 4: Metaprogramming and Advanced (Weeks 12–14)”
  • Learn define_method and method_missing
  • Study open classes and DSLs
  • Understand when to use and when to avoid metaprogramming

Wyatt’s Notes is a network of interconnected programming and study sites:


Both are excellent first languages. Ruby’s syntax is more consistent (everything is an object) and its web framework (Rails) is more opinionated. Python has a larger ecosystem for data science and general-purpose programming. Choose based on your goals: Rails for web development, Python for data science.

Yes. Ruby and Rails remain popular for web development, especially for startups and rapid prototyping. Ruby’s ecosystem is mature, and Rails continues to evolve with new features. Ruby is also the language behind tools like Jekyll (static site generation) and Homebrew (package management).

What is the difference between a Proc and a Lambda?

Section titled “What is the difference between a Proc and a Lambda?”

Procs are lenient about argument counts — they silently ignore extra arguments or pad with nil. Lambdas check argument counts and raise errors on mismatch. Procs return from the enclosing method when return is called; lambdas return from the lambda itself. Use lambdas for strict behavior and Procs for flexible code blocks.

No. Ruby is a general-purpose language useful for scripting, automation, command-line tools, and data processing. However, Rails is Ruby’s most prominent use case, and learning Rails is valuable for web development careers.

Use rbenv or rvm for Ruby version management. Use Bundler for gem dependency management. The Gemfile declares dependencies, and bundle install installs them. Bundler creates a Gemfile.lock that locks exact versions for reproducible builds.

What is the difference between include and extend in Ruby?

Section titled “What is the difference between include and extend in Ruby?”

include adds module methods as instance methods of the class. extend adds module methods as class methods of the class. Use include for shared instance behavior and extend for shared class behavior.


Last updated: 24 July 2026

Written by Wyatt. For questions or feedback, visit wyattau.com.