Dealing with Money in Rails Apps

Dealing with money involves making decision about how to store it in the database, you can store it as a decimal with a given precision, usually two decimal places. Stripe payment takes the payment amount as cents, so we convert the decimal into cents for making the API call. If you are selling products in different currencies and want to avoid the headache of converting the stored value to human readable value, use money-rails gem. Add:

gem 'money-rails'

to Gemfile and run bundle. Run the money configuration initializer:

rails g money_rails:initializer

You can define default currency in the generated config/initializers/money.rb file.

config.default_currency = :usd

The price column in the products table can be defined as integer that stores the price in cents.

  create_table "products", force: :cascade do |t|
    t.string   "name"
    t.integer  "price_in_cents"
    t.string   "description"
    t.string   "currency"
    t.datetime "created_at",     null: false
    t.datetime "updated_at",     null: false
  end

Now the product model can use the Money object:

class Product < ApplicationRecord
  monetize :price_in_cents
end

Refer the money-rails docs if you have to migrate your existing products table.

The gem assumes you are using price_cents as the column name. To customize the column name, use the as option:

  monetize :price_in_cents, as: "price"

This automatically gives the price method that is a Money object. You can use it in the view like this:

<%= humanized_money_with_symbol @product.price %>

Since the default currency is set as USD. This will display the amount as $50. If you want space between the $ and the amount:

Amount: <%= currency_symbol %> <%= humanized_money @product.price %>

The currency_symbol money-rails gem helper will generate the span tag:

<span>
     Amount: <span class="currency_symbol">$</span> 50
</span>

This will display:

Amount: $ 50

in the view.

This will work only for the default currency. Because money-gem implements the helper like this:

def currency_symbol
  content_tag(:span, Money.default_currency.symbol, class: "currency_symbol")
end

You can see how to make the money gem display the symbol for Chinese currency:

 c = Money.new('5000', 'CNY')
 => #<Money fractional:5000 currency:CNY> 
 > c.symbol
 => "¥" 

Let's make a helper that can handle any type of currency:

 def currency_symbol(symbol)
   content_tag(:span, symbol, class: "currency_symbol")
 end

This must be added to the application_helper.rb. We can now use this in our view:

   Amount: <%= currency_symbol(product.currency) %> <%= humanized_money product.price %>              

This looks like this:

Displaying Currency Symbols


Related Articles


Ace the Technical Interview

  • Easily find the gaps in your knowledge
  • Get customized lessons based on where you are
  • Take consistent action everyday
  • Builtin accountability to keep you on track
  • You will solve bigger problems over time
  • Get the job of your dreams

Take the 30 Day Coding Skills Challenge

Gain confidence to attend the interview

No spam ever. Unsubscribe anytime.