# Need feedback on improving Ruby code

**URL:** <https://www.ruby-forum.com/t/need-feedback-on-improving-ruby-code/225943>\
**Category:** Ruby\
**Created:** [March 16, 2007, 7:51pm UTC](https://www.ruby-forum.com/t/need-feedback-on-improving-ruby-code/225943 "2007-03-16T19:51:12Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [March 16, 2007, 7:51pm UTC](https://www.ruby-forum.com/t/need-feedback-on-improving-ruby-code/225943/1 "2007-03-16T19:51:12Z")

</div>

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[i] = "') { at " if input_tokens[i] ==

```

“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.

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [March 16, 2007, 8:01pm UTC](https://www.ruby-forum.com/t/need-feedback-on-improving-ruby-code/225943/2 "2007-03-16T20:01:13Z")

</div>

removed\_email\_address@domain.invalid schrieb:

> ```
> assert_equal r.dynamic_method_list.size, 3
> 
> ```

Beware the assert\_\* methods expect at first parameter the _expected_  
value and at second parameter the _actual_ vale! Have a look at  
[http://ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit/Assertions.html#M004436](http://ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit/Assertions.html#M004436)

regards  
Jan
