All books

The Well-Grounded Rubyist

Bookshelf

The Well-Grounded Rubyist

When I was first learning Ruby, The Well-Grounded Rubyist was hands-down one of the most valuable books I came across. A lot of programming books just walk you through syntax and features, but this book goes deeper—it explains the why behind Ruby’s design and philosophy. It helped me not just write Ruby, but think in Ruby, which made a huge difference in how I approached the language.

Core Ruby Philosophy

  • Everything is an object - Even primitives like integers and booleans
  • Open classes - Classes can be modified at runtime
  • Duck typing - “If it quacks like a duck, it’s a duck” - focus on what objects can do, not what they are
  • Blocks and closures - First-class functions and powerful iteration tools
  • Metaprogramming - Code that writes code

Ruby Object Model

Objects and Methods

  • Every object has a class
  • Objects respond to messages (method calls)
  • obj.methods shows all methods available to an object
  • obj.respond_to?(:method_name) checks if an object can respond to a message
  • obj.send(:method_name, arguments) dynamically calls methods

Classes and Instances

  • Classes are objects too (instances of the Class class)
  • Instance variables (@variable) belong to specific objects
  • Class variables (@@variable) belong to classes and are shared among all instances
  • Instance methods vs. Class methods (def self.method_name)

Inheritance and Modules

  • Single inheritance only - A class can only inherit from one superclass
  • super calls the parent class’s version of the current method
  • Modules provide mixins (multiple inheritance-like behavior)
  • include adds module methods as instance methods
  • extend adds module methods as class methods
  • Method lookup path: instance → included modules → class → superclass → Object → Kernel → BasicObject

Control Flow and Code Blocks

Blocks, Procs, and Lambdas

  • Blocks are not objects, but can be converted to Proc objects
  • yield executes the associated block from within a method
  • &block parameter captures a block as a Proc
  • Lambdas are Procs with stricter argument checking and different return behavior
  • proc {|x| puts x} vs lambda {|x| puts x} (or -> (x) { puts x })

Iteration and Collection

  • each - Basic iterator, returns original collection
  • map/collect - Transform each element, returns new collection
  • select/find_all - Filter collection based on condition
  • reject - Opposite of select
  • reduce/inject - Accumulate values through iteration

Variables and Scope

Variable Types

  • Local variables: my_var
  • Instance variables: @my_var (belong to object instances)
  • Class variables: @@my_var (shared across a class and all instances)
  • Global variables: $my_var (accessible everywhere, rarely used)
  • Constants: MY_CONST or MyClass (uppercase, can be redefined with warning)

Scope

  • Methods create their own scope
  • Blocks create a new scope but can access outer variables
  • Classes and modules create their own scope
  • Variables defined outside blocks are accessible inside blocks
  • Variables defined inside blocks may not be accessible outside

Methods and Arguments

Method Arguments

  • Required arguments: def method(required)
  • Optional arguments with defaults: def method(optional = "default")
  • Variable-length arguments (splat): def method(*args)
  • Keyword arguments: def method(key: "value")
  • Required keyword arguments: def method(required:)
  • Double splat for variable keyword arguments: def method(**options)

Method Return Values

  • Last evaluated expression is implicitly returned
  • Explicit return with return keyword
  • Multiple return values: return a, b, c (returns an array)

Modules and Namespaces

Namespacing

  • Use modules to organize code: module MyNamespace; class MyClass; end; end
  • Access namespaced classes with ::: MyNamespace::MyClass
  • Prevent name collisions between similar classes/methods

Mix-ins

  • Include modules to add functionality to classes
  • Common mixins: Enumerable, Comparable
  • Custom mixins for shared functionality
  • include vs prepend vs extend

Metaprogramming

Dynamic Method Handling

  • method_missing captures calls to undefined methods
  • define_method creates methods dynamically
  • instance_eval and class_eval execute code in the context of objects/classes

Class Macros

  • Methods that set up other methods or attributes
  • attr_accessor, attr_reader, attr_writer
  • Custom macros for domain-specific languages (DSLs)

Reflection

  • instance_variables - List of instance variable names
  • instance_variable_get - Access instance variable values
  • instance_variable_set - Set instance variable values
  • constants - List constants in a class/module

Ruby Idioms

Truthiness

  • Everything is truthy except false and nil
  • &&, ||, and ! for logical operations
  • and, or, and not for control flow (lower precedence)

Conditional Assignment

  • ||= assigns only if variable is nil or false
  • a ||= b is equivalent to a = a || b

Safe Navigation

  • object&.method - Calls method only if object is not nil
  • Avoids nil errors in method chains

Conversion Methods

  • to_s - Convert to string
  • to_i - Convert to integer
  • to_a - Convert to array
  • to_h - Convert to hash

Standard Library Highlights

String Manipulation

  • String interpolation: "Hello, #{name}"
  • Multi-line strings with heredocs: <<~TEXT ... TEXT
  • Regular expressions: /pattern/ and String#match, String#scan

Collections

  • Arrays: Ordered, indexed collections
  • Hashes: Key-value pairs
  • Sets: Unique values
  • Ranges: Sequences with start and end points

File and I/O

  • File.open, File.read, File.write
  • IO streams
  • Dir for directory operations

Date and Time

  • Time class for timestamps
  • Date and DateTime for calendar dates
  • Conversion between time representations

Testing and Debugging

IRB/Pry

  • Interactive Ruby for quick testing
  • Inspect objects, test methods
  • Debug and explore code

RSpec/MiniTest

  • BDD/TDD testing frameworks
  • Test methods and behavior
  • Expectations and assertions

Debugging

  • puts debugging
  • byebug/pry for interactive debugging
  • pp (pretty print) for complex objects

Gems and Ecosystem

Bundler

  • Manage dependencies with Gemfile
  • bundle install, bundle update
  • Gemfile.lock ensures consistent environments

RubyGems

  • Find and install packages
  • gem install name