开发者

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜