Module: BigMoney::Parser

Included in:
BigMoney
Defined in:
lib/big_money/parser.rb

Overview

Fuzzy string parsing.

Supports scientific notation for amounts and ISO-4217 currency symbols.

Synopsis

require 'big_money'
require 'big_money/parser' # This module/mixin.

BigMoney.parse('JPY ¥2500')   #=> BigMoney.new('2500', :jpy)
BigMoney.parse('JPY2500')     #=> BigMoney.new('2500', :jpy)
BigMoney.parse('2500JPY')     #=> BigMoney.new('2500', :jpy)
BigMoney.parse('¥2500JPY')    #=> BigMoney.new('2500', :jpy)
BigMoney.parse('¥2500')       #=> BigMoney.new('2500', :xxx)

Currency

Due to the nature of string parsing it’s possible t

Constant Summary collapse

REGEXP =
%r{
  (?:^|\b)
  ((?:[a-zA-Z]{3})?)\s*             # ISO4217 Currency code.
  [^\d+-]?                          # Currency symbol.
  ([-+]?)                           # +-
  [^\d+-]?                          # Currency symbol.
  \s*(
    (?:(?:\d(?:\d+|[., ]?)*\d)|\d)  # Digits and ., or spaces.
    (?:[eE][-+]?\d+)?               # Exponents.
  )\s*
  ((?:[a-zA-Z]{3})?)                # ISO4217 Currency code.
  (?:$|\b)
}x

Instance Method Summary collapse

Instance Method Details

#parse(money) ⇒ Object

Fuzzy parsing.

Parameters

money<.to_s>

The object to parse as money.

Currency

ISO-4217 BigMoney::Currency::XXX aka ‘No currency’ will be used if a currency cannot be parsed along with the amount. If you know the currency and just need the amount XXX is always exchanged 1:1 with any currency:

money = BigMoney.parse(‘¥2500’) #=> BigMoney.new(‘2500’, :xxx) money.exchange(:jpy) #=> BigMoney.new(‘2500’, :jpy)

Returns

BigMoney or nil

Raises:

  • (TypeError)


52
53
54
55
56
57
58
59
60
61
62
# File 'lib/big_money/parser.rb', line 52

def parse(money)
  raise TypeError.new("Can't convert +money+ #{money.class} into String.") unless money.respond_to?(:to_s)

  match    = REGEXP.match(money.to_s) || return
  currency = [match[1], match[4]].find{|c| Currency.find(c)} || Currency::XXX

  # TODO: Currency should have a .delimiter method I reckon that returns the major/minor delimiter.
  # For now '.' will do and everything else will be stripped.
  money = [match[2], match[3].gsub(/[^0-9.Ee]/, '')].join
  new(money, currency)
end