Need feedback on improving Ruby code

Discussion in 'Ruby' started by bcparanj@gmail.com, Mar 16, 2007.

  1. Guest

    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.
     
    , Mar 16, 2007
    #1
    1. Advertising

  2. Jan Friedrich, Mar 16, 2007
    #2
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. AndiV

    Need help improving authorization

    AndiV, Jul 21, 2004, in forum: ASP .Net
    Replies:
    3
    Views:
    425
    AndiV
    Jul 23, 2004
  2. feba
    Replies:
    24
    Views:
    956
    Arnaud Delobelle
    Dec 17, 2008
  3. gb345
    Replies:
    1
    Views:
    301
    Terry Reedy
    Aug 13, 2009
  4. AndiV

    Need help improving authorization

    AndiV, Jul 21, 2004, in forum: ASP .Net Security
    Replies:
    2
    Views:
    103
    AndiV
    Jul 23, 2004
  5. Ronald Fischer
    Replies:
    6
    Views:
    342
    Ronald Fischer
    May 21, 2007
Loading...

Share This Page