0
votes

How to convert dollars into cents for money gem

There're many currencies type in my database.

suppose I have these 3 items in my database

  • amount: 100, currency: NTD
  • amount:100, currency: USD
  • amount:100, currency: JPY

Then

Money.new(100, :NTD), the result will be 1 dollar for NTD, but actually it should be 100 dollars.

As as in USD

However,

Money.new(100, :JPY), the result is just 100 dollars for JPY, it's as my expect.

How could I handle this situation in my case. it's not possible to acquire my user to type 100 for 1 dollar with NTD currency.

In the amount field, I want to only save the number for dollar unit.

However the money gem seems only accepts cents as its input.

Is there any good practice to solve my problem.

3
Are you able to multiply the amount the user-provided amount by 100?Daniel M.
so I have to write if else condition, if user choose USD or TWD i should multiply 100, if JPY i don't have to multiply 100. these will add complexity in my app. prone to make new bugs, i'm finding if there is more elegant solution T_TnewBike

3 Answers

0
votes

This is my current solution, however i think it smells bad

I hope there is some solutions can beat my current workaround

CurrencyUtil.money_to_target_currency( price , from_currency, to_currency)

lib/currency_util.rb

module CurrencyUtil

  def self.dollar_to_cents(amount, raw_currency)
    currency = raw_currency.upcase.to_sym
    if [:TWD, :USD].include? currency
      cents = amount*100
    elsif [:JPY]
      cents = amount
    end
    return cents
  end

  def self.money_to_target_currency(amount_in_dollar, from_currency, to_currency)
    cents = dollar_to_cents(amount_in_dollar, from_currency)
    Money.new(cents, from_currency).exchange_to(to_currency)
  end

end
0
votes

If you take a look in money gem, in /config/currency_iso.json

{
  "Jpy": {
    "priority": 6,
    "iso_code": "JPY",
    "name": "Japanese Yen",
    "symbol": "¥",
    "alternate_symbols": ["円", "圓"],
    "subunit": null,
    "subunit_to_unit": 1,
    "symbol_first": true,
    "html_entity": "¥",
    "decimal_mark": ".",
    "thousands_separator": ",",
    "iso_numeric": "392",
    "smallest_denomination": 1
  }
}

You will see that

"subunit_to_unit": 1 

so in this case you should override JPY and NTD currency with

"subunit_to_unit": 100        

Here is my sample code under /config/initializers/money.rb

  Money::Currency.register({
    "priority": 6,
    "iso_code": "JPY",
    "name": "Japanese Yen",
    "symbol": "¥",
    "alternate_symbols": ["円", "圓"],
    "subunit": "Sen",
    "subunit_to_unit": 100,
    "symbol_first": true,
    "html_entity": "¥",
    "decimal_mark": ".",
    "thousands_separator": ",",
    "iso_numeric": "392",
    "smallest_denomination": 1
 })

You can add more currency in here. Hope this help you.

0
votes

Damn, this took me ages to figure out. Awesome gem, but had the same issue. This was my solution:

# multiply amount to convert by the subunit for currency
amount = amount * Money::Currency.new(from_symbol).subunit_to_unit
amount_exchanged = Money.new(amount, from_symbol).exchange_to(to_symbol)