Tony
Tony

Reputation: 19151

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!

Upvotes: 6

Views: 19421

Answers (5)

Chinasaur
Chinasaur

Reputation: 2138

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.

Upvotes: 7

jdl
jdl

Reputation: 17790

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"

Upvotes: 9

Pras
Pras

Reputation: 1435

sprintf is your friend here:

cost_dollars = sprintf('%02.f', cost)
cost_cents = sprintf('%.2f', cost)

Upvotes: 3

mipadi
mipadi

Reputation: 410662

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

fmt = "%05.2f" % cost
cost_dollars, cost_cents = fmt.split '.'

Upvotes: 18

John Millikin
John Millikin

Reputation: 200806

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.

Upvotes: 5

Related Questions