Menu
Coddy logo textTech

Recap - Payment Methods

Part of the Object Oriented Programming section of Coddy's Ruby journey. Lesson 36 of 57.

challenge icon

Challenge

Hard

Build a checkout with polymorphism, an abstract method and duck typing. PaymentMethod#charge(amount) is a template method: it returns nil when available?(amount) is false, and otherwise returns card paid 50.00, fee 1.00, using label and the abstract fee(amount), which raises NotImplementedError in PaymentMethod. available? is a hook that returns true. Card charges a 2% fee; PayPal 0.30 plus 3%; GiftCard.new(balance) charges no fee, is available only while its balance covers the amount and reduces the balance. Voucher.new(value) is not a PaymentMethod: it only has its own charge(amount), returning voucher covered 20.00 when the value covers the amount and nil otherwise. The helper checkout(amount, methods) in functions.rb tries each method's charge in order and returns the first result, or declined.

The first input line lists the payment methods, such as gift:30,voucher:20,card. Every following line is an order amount; the supplied code prints the result of checkout for each.

Your code goes in payment_method.rb, card.rb, pay_pal.rb, gift_card.rb, voucher.rb and functions.rb. main.rb holds the supplied input/output code and cannot be edited.

Try it yourself

require_relative 'payment_method'
require_relative 'card'
require_relative 'pay_pal'
require_relative 'gift_card'
require_relative 'voucher'
require_relative 'functions'

# Supplied input/output code: keep it as it is
input = []
while (line = gets)
  input << line.chomp
end
methods = input[0].split(",").map do |entry|
  kind, value = entry.split(":")
  case kind
  when "card" then Card.new
  when "paypal" then PayPal.new
  when "gift" then GiftCard.new(value.to_f)
  else Voucher.new(value.to_f)
  end
end
input.drop(1).each { |line| puts checkout(line.to_f, methods) }

All lessons in Object Oriented Programming

Practice on your own: Online Ruby compiler