Class: Currency::Parser

Inherits:
Object show all
Defined in:
lib/currency/parser.rb

Overview

This class parses a Money value from a String. Each Currency has a default Parser.

Constant Summary collapse

SYMBOLS_FOR_PATTERN =
Currency::Currency::Factory::UNIQUE_SYMBOLS.collect {|symbol| symbol.split("").collect {|c| c =~ /[a-z]/i ? c : '\\'+c }.join }.join("|")
VALID_MONEY_PATTERN =
/^(([a-zA-z][a-zA-z][a-zA-z])|(#{SYMBOLS_FOR_PATTERN}))?\s*([\-\+\d,\.]+)\s*(([a-zA-z][a-zA-z][a-zA-z])|(#{SYMBOLS_FOR_PATTERN}))?(\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d+)?Z)?$/
@@default =
nil
@@empty_hash =
{ }

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opt = { }) ⇒ Parser

Returns a new instance of Parser.



42
43
44
45
46
47
48
# File 'lib/currency/parser.rb', line 42

def initialize(opt = { })
  @time =
    @enforce_currency =
    @currency =
    nil
  opt.each_pair{ | k, v | self.send("#{k}=", v) }
end

Instance Attribute Details

#currencyObject

The default Currency to use if no Currency is specified.



16
17
18
# File 'lib/currency/parser.rb', line 16

def currency
  @currency
end

#enforce_currencyObject

If true and a parsed string contains a ISO currency code that is not the same as currency, #parse() will raise IncompatibleCurrency. Defaults to false.



22
23
24
# File 'lib/currency/parser.rb', line 22

def enforce_currency
  @enforce_currency
end

#timeObject

The default Time to use if no Time is specified in the string. If :now, time is set to Time.new.



26
27
28
# File 'lib/currency/parser.rb', line 26

def time
  @time
end

Class Method Details

.defaultObject

Get the default Formatter.



30
31
32
33
# File 'lib/currency/parser.rb', line 30

def self.default
  @@default ||=
    self.new
end

.default=(x) ⇒ Object

Set the default Formatter.



37
38
39
# File 'lib/currency/parser.rb', line 37

def self.default=(x)
  @@default = x
end

Instance Method Details

#_parse(str) ⇒ Object

:nodoc:



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/currency/parser.rb', line 50

def _parse(str) # :nodoc:
  x = str
  md = nil
  time = nil
  
  convert_currency = nil
  md = VALID_MONEY_PATTERN.match(x)
  if md && !@currency
    symbol = md[3] || md[7]
    code = md[2] || md[6]
    curr = Currency::Currency.get(code ? code.upcase : nil) || (symbol ? Currency::Currency::Factory.get_currency_from_symbol(symbol) : Currency::Currency.default)
    x = md[4]
    time = Time.xmlschema(md[8]) if md[8]
    time ||= @time
    time = Time.new if time == :now
    currency = curr
  else
    currency = @currency || ::Currency::Currency.default
    currency = ::Currency::Currency.get(currency)
  end

  # Remove placeholders and symbol.
  x.gsub!(/[, ]/, '')
  symbol = currency.symbol if symbol.nil?
  x.gsub!(symbol, '') if symbol
  
  # Match: whole Currency value.
  if md = /^([-+]?\d+)\.?$/.match(x)
    x = ::Currency::Money.new_rep(md[1].to_i * currency.scale, currency, @time)
    
  # Match: fractional Currency value.
  elsif md = /^([-+]?)(\d*)\.(\d+)$/.match(x)
    sign = md[1]
    whole = md[2]
    part = md[3]
    
    if part.length != currency.scale
      currency.scale = 10**part.length if part.length > 1
      
      # Pad decimal places with additional '0'
      while part.length < currency.scale_exp
        part << '0'
      end
      
      # Truncate to Currency's decimal size. 
      part = part[0 ... currency.scale_exp]        
    end
    
    # Put the string back together:
    whole = sign + whole + part
    
    x = whole.to_i
    x = ::Currency::Money.new_rep(x, currency, time)
  else
    raise ::Currency::Exception::InvalidMoneyString, 
    [
     "#{str.inspect} #{currency} #{x.inspect}",
     :string, str,
     :currency, currency,
     :state, x,
    ]
  end

  # Do conversion.
  if convert_currency
    x = x.convert(convert_currency)
  end

  x
end

#parse(str, opt = @@empty_hash) ⇒ Object

Parse a Money string in this Currency.

"123.45".money       # Using default Currency.
=> USD $123.45

"$123.45 USD".money   # Explicit Currency.
=> USD $123.45

"CAD 123.45".money
=> CAD $123.45

"123.45 CAD".money(:USD)  # Incompatible explicit Currency.
  !!! "123.45 CAD" USD (Currency::Exception::IncompatibleCurrency)


138
139
140
141
142
143
144
145
146
147
# File 'lib/currency/parser.rb', line 138

def parse(str, opt = @@empty_hash)
  prs = self

  unless opt.empty? 
    prs = prs.clone
    opt.each_pair{ | k, v | prs.send("#{k}=", v) }
  end
  
  prs._parse(str)
end