Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I convert a decimal to string value for dollars and cents in ruby?

I am storing a cost in my application. The cost is not formatted in the database. For example: 00.00 saves as 0, 1.00 saves as 1, and 40.50 saves as 40.5

I need to read these values from the database and convert them to strings for dollars and cents. For example: 0 --> cost_dollars = "00" & cost_cents = "00", 1 --> cost_dollars = "01" & cost_cents = "00", 40.5 --> cost_dollars = "40" & cost_cents = "50".

Is there an easy way to do this in ruby on rails? Or does someone have code that does this?

Thanks!

like image 681
Tony Avatar asked Apr 13 '09 20:04

Tony


5 Answers

You can accomplish that with this little bit of Ruby code:

fmt = "%05.2f" % cost
cost_dollars, cost_cents = fmt.split '.'
like image 135
mipadi Avatar answered Nov 20 '22 10:11

mipadi


If you're trying to format dollar values in a view, you should look at number_to_currency in ActionView::Helpers::NumberHelper.

>> bd = BigDecimal.new "5.75"   
>> include ActionView::Helpers
>> number_to_currency(bd)
=> "$5.75"

As for breaking up the value into separate dollars and cents, my first question would be, "Why?" If you have a good reason, and you're dealing with decimals in your database, then you could do the following.

>> bd = BigDecimal.new "5.75"
>> "dollars:#{bd.truncate} cents:#{bd.modulo(1) * BigDecimal.new('100')}"
=> "dollars:5.0 cents:75.0"
like image 20
jdl Avatar answered Nov 20 '22 12:11

jdl


number_to_currency is nice, but it can get expensive; you might want to roll your own if you need to call it a lot.

You should be aware that using a float to store currency can be problematic (and see) if you do a lot of calculations based on these values. One solution is to use integers for currency and count cents. This appears to be the approach used by the money plugin. Another solution is to use a decimal type in your migration, which should work out-of-the-box for modern versions of Rails (> 1.2):

add_column :items, :price, :decimal, :precision => 10, :scale => 2

(:scale is the number of places past the decimal, :precision is the total number of digits.) This will get you BigDecimal objects in Rails, which are a little harder to work with, but not too bad.

Both the integer and decimal approaches are a little slower than floating point. I'm using floats for currency in some places, because I know I won't need to do calculations on the values within Rails, only store and display them. But if you need accurate currency calculations, don't use floats.

like image 36
Chinasaur Avatar answered Nov 20 '22 12:11

Chinasaur


Instead of storing as a decimal, store as an integral number of cents. So 1 dollar is stored as 100 in the database.

Alternatively, if you don't mind a bit of performance overhead, check for '.' in the database's value. If it exists, split on '.', and parse the pieces as integers.

like image 5
John Millikin Avatar answered Nov 20 '22 10:11

John Millikin


sprintf is your friend here:

cost_dollars = sprintf('%02.f', cost)
cost_cents = sprintf('%.2f', cost)
like image 3
Pras Avatar answered Nov 20 '22 11:11

Pras