What is the best method of handling currency/money? What is the best method of handling currency/money? ruby ruby

What is the best method of handling currency/money?


You'll probably want to use a DECIMAL type in your database. In your migration, do something like this:

# precision is the total number of digits# scale is the number of digits to the right of the decimal pointadd_column :items, :price, :decimal, :precision => 8, :scale => 2

In Rails, the :decimal type is returned as BigDecimal, which is great for price calculation.

If you insist on using integers, you will have to manually convert to and from BigDecimals everywhere, which will probably just become a pain.

As pointed out by mcl, to print the price, use:

number_to_currency(price, :unit => "€")#=> €1,234.01


Here's a fine, simple approach that leverages composed_of (part of ActiveRecord, using the ValueObject pattern) and the Money gem

You'll need

  • The Money gem (version 4.1.0)
  • A model, for example Product
  • An integer column in your model (and database), for example :price

Write this in your product.rb file:

class Product > ActiveRecord::Base  composed_of :price,              :class_name => 'Money',              :mapping => %w(price cents),              :converter => Proc.new { |value| Money.new(value) }  # ...

What you'll get:

  • Without any extra changes, all of your forms will show dollars and cents, but the internal representation is still just cents. The forms will accept values like "$12,034.95" and convert it for you. There's no need to add extra handlers or attributes to your model, or helpers in your view.
  • product.price = "$12.00" automatically converts to the Money class
  • product.price.to_s displays a decimal formatted number ("1234.00")
  • product.price.format displays a properly formatted string for the currency
  • If you need to send cents (to a payment gateway that wants pennies), product.price.cents.to_s
  • Currency conversion for free


Common practice for handling currency is to use decimal type.Here is a simple example from "Agile Web Development with Rails"

add_column :products, :price, :decimal, :precision => 8, :scale => 2 

This will allow you to handle prices from -999,999.99 to 999,999.99
You may also want to include a validation in your items like

def validate   errors.add(:price, "should be at least 0.01") if price.nil? || price < 0.01 end 

to sanity-check your values.