why's (poignant) guide to ruby

Them What Make the Rules and Them What Live the Dream

by _why the lucky stiff  ·  CC BY-SA 2.5
Original DomainRuby ProgrammingClassic 2003–2009
Chapter 5 illustration — Dr. ChamDr. Cham — the main character of Chapter 5 in Why's Poignant Guide

Frankly, I’m sick and tired of hearing that Dr. Cham was a madman. Yes, he tried to bury himself alive. Yes, he electrocuted his niece. Yes, in fact, he did dynamite a retirement home. But this was all with good cause and, in each case, I believe he took the correct course of action.

This chapter is about classes. Classes are the blueprints Ruby uses to build objects. Once you understand classes, you understand most of what there is to know about object-oriented Ruby.

Defining a Class

class Fox
  def initialize(name, age)
    @name = name   # @ means instance variable
    @age  = age
  end

  def speak
    puts "#{@name} says: *rustle rustle*"
  end

  def description
    "#{@name} is #{@age} years old"
  end
end

trady = Fox.new("Trady Blix", 9)
trady.speak         # => "Trady Blix says: *rustle rustle*"
trady.description   # => "Trady Blix is 9 years old"
Elderly characters — Chapter 5 illustration

attr_accessor

class Fox
  attr_accessor :name, :age, :color

  def initialize(name, age, color = :red)
    @name  = name
    @age   = age
    @color = color
  end
end

f = Fox.new("Spot", 3)
f.name        # => "Spot"
f.color       # => :red
f.color = :silver
f.color       # => :silver

attr_accessor generates both getter and setter methods for you. attr_reader generates only the getter. attr_writer only the setter. Use attr_accessor most of the time.

Inheritance

class Animal
  def breathe
    puts "inhale... exhale..."
  end

  def eat(food)
    puts "nom nom nom #{food}"
  end
end

class Fox < Animal
  def speak
    puts "*rustle*"
  end
end

class Cat < Animal
  def speak
    puts "meow"
  end
end

f = Fox.new
f.breathe   # inherited from Animal: "inhale... exhale..."
f.speak     # own method: "*rustle*"
f.eat("chunky bacon")  # inherited: "nom nom nom chunky bacon"
Dr. Cham demonstrating Ruby inheritance

Modules

module Greetable
  def greet
    "Hello! I am #{name}"
  end
end

module Trackable
  def log_action(action)
    puts "[#{self.class}] #{action} at #{Time.now}"
  end
end

class Person
  include Greetable
  include Trackable
  attr_reader :name

  def initialize(name)
    @name = name
  end
end

p = Person.new("Trady Blix")
p.greet        # => "Hello! I am Trady Blix"
p.log_action("spoke")  # => "[Person] spoke at 2026-..."

Modules allow you to share behavior across classes that don’t share a parent class. They are Ruby’s answer to multiple inheritance. A class can include as many modules as needed.

Class Methods vs Instance Methods

class TextSample
  @@count = 0  # class variable

  def initialize(text)
    @text = text
    @@count += 1
  end

  def word_count
    @text.split.length
  end

  def self.total_created
    @@count
  end
end

t1 = TextSample.new("chunky bacon is chunky")
t2 = TextSample.new("why the lucky stiff")

t1.word_count           # => 4  (instance method)
TextSample.total_created  # => 2  (class method)

Why's (Poignant) Guide to Ruby is released under the Creative Commons Attribution-ShareAlike 2.5 license. Written by _why the lucky stiff, originally published 2003–2009. Preserved at its original domain. Images © _why the lucky stiff, CC BY-SA 2.5.

→ AI Detector Benchmark & Research Hub