why's (poignant) guide to ruby

A Quick (and Hopefully Painless) Ride Through Ruby (with Cartoon Foxes)

by _why the lucky stiff  ·  CC BY-SA 2.5
Original DomainRuby ProgrammingClassic 2003–2009
Chapter 3 illustration — the foxes arrive
This chapter was reprinted in The Best Software Writing I, selected and introduced by Joel Spolsky (Apress, 2005). It is the most-read and most-cited chapter in the guide.
The cartoon foxes — protagonists of Why's Poignant Guide

I’m told that this chapter is best accompanied by a rag. Something you can mop your face with as the sweat pours off. We’ll be covering a lot of Ruby in a short time. Names and types and variables and objects. Methods and classes and modules. It’s not hard. It’s actually quite lovely. But there is a lot of it.

“My conscience won’t let me call Ruby a computer language. That would imply that the language works primarily on the computer’s terms. That the language is designed to accommodate the computer, first and foremost. That therefore, we, the coders, are foreigners, seeking citizenship in the computer’s locale.”

Numbers

5       # integer
3.14    # float
2_000_000  # underscores for readability — still just a number
0xFF    # hexadecimal: 255
0b1111  # binary: 15
Foxes learning about Ruby variables

Strings

"chunky bacon"          # double-quoted
'also a string'         # single-quoted (no interpolation)
"chunky #{4 - 2}"      # => "chunky 2"
"line one
line two"    # 
 is a newline
%Q(this works too)      # another way to make a string

Symbols

:chunky
:bacon
:a_longer_symbol

A symbol is like a string that doesn’t change. It always refers to the same object in memory. Symbols are used as keys in hashes, as method names, as identifiers. They start with a colon.

Foxes discovering symbols and hashes

Arrays

animals = ['fox', 'dog', 'cat']
animals[0]    # => 'fox'
animals[-1]   # => 'cat' (negative: count from end)
animals[1..2] # => ['dog', 'cat']  (a range)
animals.first # => 'fox'
animals.last  # => 'cat'
animals.length  # => 3
animals.include?('fox')  # => true

animals.push('wolf')     # add to end
animals.unshift('bear')  # add to beginning
animals.map { |a| a.upcase }  # => ['BEAR', 'FOX', 'DOG', 'CAT', 'WOLF']
animals.select { |a| a.length > 3 }  # => ['wolf']

Hashes

blix = { name: 'Trady Blix', age: 9, color: :black }
blix[:name]   # => 'Trady Blix'
blix[:age]    # => 9
blix.keys     # => [:name, :age, :color]
blix.values   # => ['Trady Blix', 9, :black]
blix[:weight] # => nil (missing keys return nil, not an error)

Hashes are the workhorses of Ruby. You will use them constantly. Any time you want to store key-value pairs — configuration, attributes, options — use a hash.

True, False, Nil

!!nil    # => false  (nil is falsy)
!!false  # => false  (false is falsy)
!!0      # => true   (0 is truthy in Ruby — unlike some languages!)
!!""     # => true   (empty string is truthy!)
!!"any string"  # => true

In Ruby, only nil and false are falsy. Everything else — including 0 and empty string — is truthy. This surprises people coming from Python or JavaScript.

The foxes contemplating truth and falsehood in Ruby

Methods

def double(x)
  x * 2
end

double(5)  # => 10
double 5   # also fine — parentheses optional in many cases

In Ruby, the last expression evaluated in a method is automatically the return value. You don’t need an explicit return, though you can use one if you want to return early.

Blocks

3.times { puts "hello" }

[1, 2, 3].each do |n|
  puts n * 10
end
# => 10
# => 20
# => 30

Blocks are the soul of Ruby. They are chunks of code you can pass to methods. The curly braces or do...end wrap the block. The |n| is the block parameter — the thing the method passes in to the block each time it calls it.

Foxes demonstrating Ruby blocks and iterators

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