WagnerMatosUK WagnerMatosUK - 1 month ago 7
Ruby Question

How to resolve this error erb is throwing when passing a currency formatted string

I'm using a module within my Rails App to perform some actions and render a html file and save it to S3. So far so good, apart from the fact that I need to pass a currency variable to to be rendered and erb is throwing this error:

undefined method `/' for "3,395,000":String


Here's my code:

options = {
...
price: Money.new(@case.cash_price / 100.to_i, "DKK").format.to_s.html_safe,
...
}


And here's my module:

def generate_html(options)
require 'erb'

erb_file = "templates/banners/widesky.html.erb"

erb_str = File.read(erb_file)

...
@price = options[:price]
...

renderer = ERB.new(erb_str)
result = renderer.result(binding)

FileUtils.mkdir_p('temp') unless File.directory?('temp')

File.open('temp/index.html', 'w') do |f|
f.write(result)
end

'temp/index.html'

end


And I tried formatting the currency in different ways, but I always get the same error. Any ideas why?

EDIT

@case.cash_price
originally is an Integer. I want to convert it to a string with commas (hence using Money to format it). The problem seems to be that
erb
doesn't like the formatted result and throw the above error.

Answer

If for some reason you cannot use any gem/helper, let's reinvent the wheel!

def to_currency(price_in_cents, currency=nil, decimal_separator = '.', thousand_separator = ',')
  price_in_cents.to_s.rjust(3,'0').reverse.insert(2,decimal_separator).gsub(/(\d{3})(?=\d)/, '\1'+thousand_separator).reverse+(currency ? " #{currency}" : '')
end

puts to_currency(123456789, 'DKK')
puts to_currency(123456, '€', ',', ' ')
puts to_currency(1)

It outputs :

1,234,567.89 DKK
1 234,56 €
0.01

Note that price_in_cents should be either a String that looks like an Integer ("123456789") or an Integer (123456789), but not a preformatted String ("123,456.78") or a Float (1.23). Finally, the resulting String is as unsafe as price_in_cents :

to_currency("unsafe_codejs")
=> "unsafe_code.js"

You don't have to specify html_safe on the result anyway, because nothing would be escaped in "1,234,567.89 DKK".

Original answer :

If cash_price is a String with commas, you need to remove the commas first, then convert it to a float, then divide by 100, and then convert the result to an Integer. cash_price.to_s is to avoid getting errors if cash_price does come as a Numeric.

price: Money.new((@case.cash_price.to_s.delete(',').to_f/100).to_i, "DKK").format.to_s.html_safe