Need feedback on improving Ruby code

B

bcparanj

require 'print_receipt'
require "test/unit"

class TestReceiptBuilder < Test::Unit::TestCase

def test_create_dynamic_method_list
r = ReceiptBuilder.new([["1 book at 12.49"], ["1 music cd at
14.99"], ["1 chocolate bar at 0.85"]])
r.create_dynamic_method_list

assert_equal r.dynamic_method_list.size, 3

assert_equal r.dynamic_method_list[0].to_s, "buy(1,' book ') { at
12.49 }"
assert_equal r.dynamic_method_list[1].to_s, "buy(1,' music cd ')
{ at 14.99 }"
assert_equal r.dynamic_method_list[2].to_s, "buy(1,' chocolate bar
') { at 0.85 }"

end

def test_nearest_five_rounding
assert_equal ReceiptBuilder.round_to_nearest_five_cents(0.01),
0.05
assert_equal ReceiptBuilder.round_to_nearest_five_cents(0.02),
0.05
assert_equal ReceiptBuilder.round_to_nearest_five_cents(0.03),
0.05
assert_equal ReceiptBuilder.round_to_nearest_five_cents(0.04),
0.05
assert_equal ReceiptBuilder.round_to_nearest_five_cents(0.05),
0.05
assert_equal ReceiptBuilder.round_to_nearest_five_cents(0.06),
0.1
assert_equal ReceiptBuilder.round_to_nearest_five_cents(0.07),
0.1
assert_equal ReceiptBuilder.round_to_nearest_five_cents(0.08),
0.1
assert_equal ReceiptBuilder.round_to_nearest_five_cents(0.09),
0.1
assert_equal ReceiptBuilder.round_to_nearest_five_cents(0.1), 0.1

end

def test_exempt_products
r = ReceiptBuilder.new([])

exempt_products = ["book", "chocolate bar", "packet of headache
pills", "imported box of chocolates",
"box of imported chocolates"]

exempt_products.each do |product|
assert r.is_exempt_product?(product)
end

non_exempt_products = ["tin tin", "bugs bunny"]
non_exempt_products.each do |product|
assert !r.is_exempt_product?(product)
end

end

def test_imported_products
r = ReceiptBuilder.new([])

imported_products = ["imported box of chocolates", "imported
bottle of perfume", "box of imported chocolates"]

imported_products.each do |product|
assert r.is_imported_product?(product)
end
end

def test_line_item
r = ReceiptBuilder.new([["1 book at 12.49"], ["1 music cd at
14.99"], ["1 chocolate bar at 0.85"]])
r.create_dynamic_method_list

r.generate_output
r.print_output

line_item = LineItem.new(1, 'book', 15.99)

assert_not_nil line_item.nil?

assert_not_nil line_item.quantity
assert_equal line_item.quantity, 1

assert_not_nil line_item.name
assert_equal line_item.name, 'book'

assert_not_nil line_item.price
assert_equal line_item.price, 15.99
# Check for all combinations of exempt and imported status
assert_equal line_item.sales_tax_for('imported bottle of perfume',
10, 1), 1.5
assert_equal line_item.sales_tax_for('chocolate bar', 10,1), 0
assert_equal line_item.sales_tax_for('bugs bunny', 10,1), 1
assert_equal line_item.sales_tax_for('imported box of chocolates',
10,1), 0.5

end

def test_output_two
r = ReceiptBuilder.new([["1 imported box of chocolates at 10.00"],
["1 imported bottle of perfume at 47.50"]])
r.create_dynamic_method_list
r.generate_output
r.print_output

# line_item = LineItem.new(1, 'imported bottle of perfume', 10)
#
# assert_equal line_item.sales_tax_for('imported box of
chocolates', 47.5,1), 2.375
#
end

def test_output_three
r = ReceiptBuilder.new([["1 imported bottle of perfume at 27.99"],
["1 bottle of perfume at 18.99"], ["1 packet of headache pills at
9.75"],["1 box of imported chocolates at 11.25"]])
r.create_dynamic_method_list

r.generate_output
r.print_output

end
end

The same inputs and outputs are:

# Input 1:
# 1 book at 12.49
# 1 music CD at 14.99
# 1 chocolate bar at 0.85
#
# Input 2:
# 1 imported box of chocolates at 10.00
# 1 imported bottle of perfume at 47.50
#
# Input 3:
# 1 imported bottle of perfume at 27.99
# 1 bottle of perfume at 18.99
# 1 packet of headache pills at 9.75
# 1 box of imported chocolates at 11.25
#
# OUTPUT
#
# Output 1:
# 1 book : 12.49
# 1 music CD: 16.49
# 1 chocolate bar: 0.85
# Sales Taxes: 1.50
# Total: 29.83
#
# Output 2:
# 1 imported box of chocolates: 10.50
# 1 imported bottle of perfume: 54.65
# Sales Taxes: 7.65
# Total: 65.15
#
# Output 3:
# 1 imported bottle of perfume: 32.19
# 1 bottle of perfume: 20.89
# 1 packet of headache pills: 9.75
# 1 imported box of chocolates: 11.85
# Sales Taxes: 6.70
# Total: 74.68

print_receipt.rb
class ReceiptBuilder

module SalesTaxPolicy
BASE_SALES_TAX = 0.1
IMPORT_DUTY = 0.05

def is_exempt_product?(product)
["book", "chocolate bar", "packet of headache pills", "imported
box of chocolates",
"box of imported chocolates"].include?
(product)
end

def is_imported_product?(product)
["imported box of chocolates", "imported bottle of perfume",
"box of imported chocolates"].include?(product)
end
end

include SalesTaxPolicy

attr_accessor :dynamic_method_list, :buffer, :line_items_list
@@header = "Count Item Price\n"

def initialize(purchase_list)
@dynamic_method_list = Array::new
@purchased_items = purchase_list
@buffer = Array::new
@line_items_list = Array::new
end

def generate_output
@dynamic_method_list.each do |element|
eval(element.to_s)
end
end

def create_dynamic_method_list
@purchased_items.each do |s|

input_tokens = s.to_s.split(/(\s+)/)

input_tokens.each_index do |i|
input_tokens = "') { at " if input_tokens ==
"at"
end

input_tokens[0] = input_tokens[0] + ",'"
input_tokens.unshift "buy("
input_tokens << " }"

@dynamic_method_list << input_tokens
end
end

def buy(quantity, item, &block)
_save_line_item_output(quantity, item, block.call)
end

def at(price)
price
end

def self.round_to_nearest_five_cents(price)
((20 * (price + 0.04)).floor)*0.05
end

def print_output
puts "_________________________________________________"
puts @@header
puts @buffer.to_s

total = 0
@line_items_list.each do |item|
total += item.tax_inclusive_price
end

sales_tax_total = 0
@line_items_list.each do |item|
sales_tax_total += item.sales_tax_for(item.name, item.price,
item.quantity)
end

rounded_sales_tax =
ReceiptBuilder.round_to_nearest_five_cents(sales_tax_total)
rounded_total = ReceiptBuilder.round_to_nearest_five_cents(total)
puts "_________________________________________________"
puts "Sales Taxes : #{rounded_sales_tax}"
puts "Total : #{rounded_total}"

end

private
def _save_line_item_output(quantity, item, price)
rounded_amount =
ReceiptBuilder.round_to_nearest_five_cents(price)
line_item = LineItem.new(quantity, item.strip, rounded_amount)

@line_items_list << line_item
@buffer << line_item.to_s + "\n"
end

end

class LineItem
include ReceiptBuilder::SalesTaxPolicy

attr_reader :quantity, :name, :price, :tax_inclusive_price

def initialize(quantity, name, price)
@quantity = quantity
@name = name
@price = price
@tax_inclusive_price =
ReceiptBuilder.round_to_nearest_five_cents(sales_tax_for(name, price,
quantity) + price)
end

def to_s
padding_size = 28 - name.size
extra_space = []
temp = padding_size.times { extra_space << ' '}
"#{quantity} #{name} :" + extra_space.to_s +
"#{tax_inclusive_price}"
end

# Basic sales tax is applicable at a rate of 10% on all goods,
except books,
# food, and medical products that are exempt. Import duty is an
additional
# sales tax applicable on all imported goods at a rate of 5%, with
no
# exemptions.
def sales_tax_for(name, price, quantity)
_importe = is_imported_product?(name)
_exempte = is_exempt_product?(name)

(_basic_tax(_exempte, price) + _import_tax(_importe,
price))*quantity
end


private

def _basic_tax(exempt, price)
if exempt
0
else
BASE_SALES_TAX * price
end
end

def _import_tax(importe, price)
if importe
IMPORT_DUTY * price
else
0
end
end

end

I took a test for a company and they have already decided my
background does not fit their requirements. I want to learn from
advanced Ruby developers on how I can improve the solution. This is
just for improving my Ruby skills. TIA.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top