Ruby and money, in a rails app, how to store money values in the db?
I want to make sur开发者_StackOverflowe I don't have rounding issues when it comes to storing prices for products in a rails app.
What mysql datatype should I use, and what does it map to in rails?
I want decimal with 10 places for precision.
I prefer to store currency in the database as an integer of the lowest denomination (pence, cents etc), and do calculations against this.
add_column :product, :price, :integer
Of course, you will want any form input and display to be in the form people expect, so we add some helper methods to the model to help with this.
class Product < ActiveRecord::Base
def price_dollars
self.price / 100
end
def price_dollars=(val)
self.price = val * 100
end
end
In the console we then get:
> prod = Product.new
=> [snip]
> prod.price_dollars = 12.93
=> 12.93
> prod.price
=> 1293
> prod.price_dollars
=> 12.93
> prod.price = 1691
=> 1691
> prod.price_dollars
=> 16.91
I'm sure there is probably a plugin that handles this nicely somewhere.
Sounds you want the :decimal
column type. You can control the total number of digits and the number of decimal places with the :precision
and :scale
options:
add_column :mytable, :mycolumn, :decimal, :precision => 30, :scale => 10
A little more on data types in this documentation (no idea what the column
function is, though - probably internal!).
Hope this helps!
Adding to Douglas's excellent answer above:
In order for it to work, at least in Ruby 2.1.4, you will need to convert the :price field to a float or decimal when dividing by 100.
Dividing an integer by another integer
1293 / 100
will not return what you might expect. Instead of getting 12.93 Ruby returns 12 the integer.
2.1.4 :002 > 1293 / 100
=> 12
2.1.4 :003 > 1293.to_f / 100
=> 12.93
Product Model Code Example
class Product < ActiveRecord::Base
def price_dollars
self.price.to_f / 100
end
def price_dollars=(val)
self.price = val * 100
end
end
I think it's always easiest to store your lowest common denominator as an integer in the database (here's a question where we used cents: Handling international currency input in Ruby on Rails, but you could store prices in 1/10,000 cents if you like), and do the correct math when you take the number out of the DB.
Use "float"
add_column :customer, :amount, :float
精彩评论