Chapter 1. Object-Oriented Design

Chapter 2. Designing Classes with a Single Responsibility

class Gear
  attr_reader :chainring, :cog
 
  def initialize(chainring, cog)
    @chainring = chainring
    @cog       = cog
  end
 
  def ratio
    chainring / cog.to_f
  end
end
 
puts Gear.new(52, 11).ratio
puts Gear.new(30, 27).ratio

Enhancement: I have two bicycles; they have the same gearing but different wheel sizes. Add possibility to calculate the effect of the difference in wheels.

class Gear
  attr_reader :chainring, :cog, :rim, :tire
 
  def initialize(chainring, cog, rim, tire)
    @chainring = chainring
    @cog       = cog
    @rim       = rim
    @tire      = tire
  end
 
  def ratio
    chainring / cog.to_f
  end
 
  def gear_inches
    ratio * (rim + (tire * 2))
  end
end
 
puts Gear.new(52, 11, 26, 1.5).gear_inches
puts Gear.new(52, 11, 26, 1.25).gear_inches

This however introduced a bug:

puts Gear.new(52, 11).ratio  # ArgumentError

Gear.initialize was changed to require two additional arguments, and this broke all existing callers of the method.