Skip to content

Instantly share code, notes, and snippets.

@agustibr
Last active April 29, 2025 09:23
Show Gist options
  • Save agustibr/2b9b4a1f84a317cb771ce7fd24e75480 to your computer and use it in GitHub Desktop.
Save agustibr/2b9b4a1f84a317cb771ce7fd24e75480 to your computer and use it in GitHub Desktop.
Refactoring Ruby
# The customer class represents the customer of the store.
class Customer
attr_reader :name
def initialize(name)
@name = name
@rentals = []
end
def add_rental(arg)
@rentals << arg
end
def html_statement
result = "<h1>Rentals for <em>#{@name}</em></h1><p>\n"
@rentals.each do |element|
# show figures for this rental
result += "\t" + element.movie.title + ": " + element.charge.to_s + "<br>\n"
end
# add footer lines
result += "<p>You owe <em>#{total_charge}</em><p>\n"
result += "On this rental you earned " +
"<em>#{total_frequent_renter_points}</em> " +
"frequent renter points<p>"
result
end
private
def total_charge
@rentals.inject(0) { |sum, rental| sum + rental.charge }
end
def total_frequent_renter_points
@rentals.inject(0) { |sum, rental| sum + rental.frequent_renter_points }
end
end
# Movie is just a simple data class.
class Movie
REGULAR = 0
NEW_RELEASE = 1
CHILDRENS = 2
attr_reader :title, :price_code
attr_writer :price
def price_code=(value)
@price_code = value
@price = case price_code
when REGULAR: RegularPrice.new
when NEW_RELEASE: NewReleasePrice.new
when CHILDRENS: ChildrensPrice.new
end
end
def initialize(title, price_code)
@title, @price_code = title, price_code
end
def charge(days_rented)
@price.charge(days_rented)
end
def frequent_renter_points(days_rented)
(price_code == NEW_RELEASE && days_rented > 1) ? 2 : 1
end
end
class RegularPrice
def charge(days_rented)
result = 2
result += (days_rented - 2) * 1.5 if days_rented > 2
result
end
end
class NewReleasePrice
def charge(days_rented)
days_rented * 3
end
end
class ChildrensPrice
def charge(days_rented)
result = 1.5
result += (days_rented - 3) * 1.5 if days_rented > 3
result
end
end
# The rental class represents a customer renting a movie.
class Rental
attr_reader :movie, :days_rented
def initialize(movie, days_rented)
@movie, @days_rented = movie, days_rented
end
def charge
movie.charge(days_rented)
end
def frequent_renter_points
movie.frequent_renter_points(days_rented)
end
end
@agustibr
Copy link
Author

# calling code
movie = Movie.new("The Watchmen", NewReleasePrice.new)
# and later...
movie.price = RegularPrice.new

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment