views:

94

answers:

5

i've got a price field/column and i wonder should the rails datatype be string, decimal or float?

eg. 15.50 USD.

thanks

+1  A: 

It depends.

If you are performing calculations for purchase prices use a decimal.
If you are performing engineering mathematics use a float.
If you are just storing the data use a string.

Woot4Moo
+2  A: 
add_column :table, :price, :decimal, :precision => 8, :scale => 2

The code above would be your best bet.

Tom
how do i do it in the command line? i typed "rails generate scaffold Product price:decimal" and it created a column with :scale 1.
never_had_a_name
Depending on your needs, you might want to add -> add_column :table, :currency, :string, :default => 'USD'
Tom
Is this Rails 3? rails g migration AddPriceToYourModel price:decimal then go to the generated migration and add in the details.
Tom
@Tom. where do you find all the options like precision and scale? im on ror3 but cant find the options in the migrations page.
never_had_a_name
If you run rails g migration AddPriceToYourModel price:decimal and go to [some timestamp]_add_price_to_yourmodel you should see add_column :table, :price, :decimal. Just append ', :precision => 8, :scale => 2' to that line.
Tom
A: 

I recommend using integers for prices if possible. Many popular gems (such as ActiveMerchant, Money) assume the use of integers, and it is often better to store units of measurement in a base unit (such as cents).

Kevin Sylvestre
but integers has no 13.25?
never_had_a_name
That is why you base it on cents. So the $13.25 gets stored as 1325 in the database. You format the dollar sign and the decimal in the view.
sosborn
+1  A: 

Floats are not accurate:

0.3 - 0.2 - 0.1
=> -2.77555756156289e-17

Don't use them unless you only store values.

If you need to make calculations store the price in cents as an integer. You can easily display them as USD with a helper.

vise
+1  A: 

This argument always has two sides - decimals and integers. Supporters of integers argue that decimals might not be accurate (when doing conversions) and that the BigDecimal implementation includes bugs, sometimes even segfaulting.

For my own project, i picked up integers also, wrapped them in a custom container, converting cents to "real" amounts and back. At first it seemed nice, after a while it became really cumbersome to use - tracking when you are dealing with cents, when with formatted strings etc.

Then i reverted to decimals - same format all the time, i can easily convert the amount to cents if needed, i get the different rounding algorithms out of the box. Im much much more satisfied with decimals.

And to address the issues about decimals not being accurate - when googling you might notice that most of the bugs are related to converting decimals into floats :) As vise already mentioned before, floats are not accurate and you should never ever convert your decimal to a float. That's the single most important thing you have to remember when dealing with decimals - you don't want to lose accuracy by conversions. Oh and i have never actually encountered any bugs with ruby 1.8.7, 1.8.7 and 1.9.1 while using BigDecimal extensively.

Tanel Suurhans