views:

2692

answers:

5

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!

+3  A: 

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.

John Millikin
+5  A: 

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

fmt = "%05.2f" % cost
cost_dollars, cost_cents = fmt.split '.'
mipadi
very useful, I was aware of sprintf but not of this plain use for "%".
Maximiliano Guzman
A: 

sprintf is your friend here:

cost_dollars = sprintf('%02.f', cost)
cost_cents = sprintf('%.2f', cost)
Pras
+4  A: 

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"
jdl
+4  A: 

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.

Chinasaur
i am using decimal, thanks
Tony