why's (poignant) guide to ruby

Downtown Walrus & Upsetting a Salmon

by _why the lucky stiff  ·  CC BY-SA 2.5
Original DomainRuby ProgrammingClassic 2003–2009
Chapter 6 illustration — Wixl the WalrusWixl — the walrus character in Chapter 6 of Why's Poignant Guide

This chapter covers file I/O, string manipulation, and regular expressions. These are the workhorses of scripting — the tools you reach for when Ruby is solving a real problem rather than illustrating a concept.

Files

text = File.read("my_file.txt")  # read entire file as string

File.open("my_file.txt") do |f|  # block form — auto-closes
  f.each_line { |line| puts line }
end

lines = File.readlines("my_file.txt")  # array of lines
lines.each { |line| puts line.chomp }

File.write("output.txt", "hello world
")  # write a file
Wixl demonstrating file operations

String Methods (The Good Parts)

s = "Why the Lucky Stiff"
s.upcase              # => "WHY THE LUCKY STIFF"
s.downcase            # => "why the lucky stiff"
s.swapcase            # => "wHY THE lUCKY sTIFF"
s.capitalize          # => "Why the lucky stiff"
s.reverse             # => "ffitS ykcuL ehT yhW"
s.length              # => 19
s.chars.first(3)      # => ["W", "h", "y"]
s.include?("Lucky")   # => true
s.start_with?("Why")  # => true
s.sub("Lucky", "Unlucky")   # replaces first
s.gsub("l", "L")            # replaces all
s.split(" ")          # => ["Why", "the", "Lucky", "Stiff"]
s.strip               # removes leading/trailing whitespace
s[4..6]               # => "the"  (substring by range)

Regular Expressions

text = "perplexity: 45.3, burstiness: 0.22"

text.match(/perplexity: ([d.]+)/)
# => MatchData — or nil if no match
$1  # => "45.3" (first capture group from last match)

text.scan(/[d.]+/)   # => ["45.3", "0.22"]
text.gsub(/d/, '*')  # => "perplexity: **.*,..."

text =~ /perplexity/   # => 0 (position) or nil
text[/[d.]+/]         # => "45.3" (first match)
Wixl using Ruby regular expressions

Exception Handling

begin
  result = 10 / 0
rescue ZeroDivisionError => e
  puts "Caught: #{e.message}"
ensure
  puts "This always runs"
end

# Custom exceptions
class DetectionError < StandardError; end

def detect_ai(text)
  raise DetectionError, "text too short" if text.length < 50
  # ... detection logic
end

begin
  detect_ai("hi")
rescue DetectionError => e
  puts "Detection failed: #{e.message}"
end

Iterators and Lazy Enumerators

require 'enumerator'

# lazy evaluation — only processes what you need
(1..Float::INFINITY).lazy
  .select { |n| n % 3 == 0 }
  .map    { |n| n * n }
  .first(5)
# => [9, 36, 81, 144, 225]

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