Class: Currency::Money

Inherits:
Object show all
Includes:
Comparable
Defined in:
lib/currency/macro.rb,
lib/currency/money.rb

Overview

Represents an amount of money in a particular currency.

A Money object stores its value using a scaled Integer representation and a Currency object.

A Money object also has a time, which is used in conversions against historical exchange rates.

Constant Summary collapse

@@money_attributes =
{ }
@@default_time =
nil
@@empty_hash =
{ }

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(x, currency = nil, time = nil) ⇒ Money

DO NOT CALL THIS DIRECTLY:

See Currency.Money() function.

Construct a Money value object from a pre-scaled external representation: where x is a Float, Integer, String, etc.

If a currency is not specified, Currency.default is used.

x.Money_rep(currency)

is invoked to coerce x into a Money representation value.

For example:

123.Money_rep(:USD) => 12300

Because the USD Currency object has a #scale of 100

See #Money_rep(currency) mixin.



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/currency/money.rb', line 50

def initialize(x, currency = nil, time = nil)
  @currency = ::Currency::Currency.get(currency)
  @time = time || ::Currency::Money.default_time
  @time = ::Currency::Money.now if @time == :now
  
  if x.kind_of?(String)
    if @currency
      m = @currency.parser_or_default.parse(x, :currency => @currency)
    else
      m = ::Currency::Parser.default.parse(x)
    end
    @currency = m.currency unless @currency
    @time = m.time if m.time
    @rep = m.rep
  else
    @currency = ::Currency::Currency.default unless @currency
    @rep = x.Money_rep(@currency)
  end

end

Class Method Details

.default_timeObject



17
18
19
# File 'lib/currency/money.rb', line 17

def self.default_time
  @@default_time
end

.default_time=(x) ⇒ Object



20
21
22
# File 'lib/currency/money.rb', line 20

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

.each_money_attribute(&blk) ⇒ Object

Iterates through all known money attributes in all classes.

each_money_attribute { | money_opts |

...

}



26
27
28
29
30
31
32
# File 'lib/currency/macro.rb', line 26

def self.each_money_attribute(&blk)
  @@money_attributes.each do | cls, hash |
    hash.each do | attr_name, attr_opts |
      yield attr_opts
    end
  end
end

.money_attributes_for_class(cls) ⇒ Object

Returns an array of option hashes for all the money attributes of this class.

Superclass attributes are not included.



17
18
19
# File 'lib/currency/macro.rb', line 17

def self.money_attributes_for_class(cls)
  (@@money_atttributes[cls] || { }).values
end

.new_rep(r, currency = nil, time = nil) ⇒ Object

Construct from post-scaled internal representation.



90
91
92
93
94
# File 'lib/currency/money.rb', line 90

def self.new_rep(r, currency = nil, time = nil)
  x = self.new(0, currency, time)
  x.set_rep(r)
  x
end

.nowObject

Returns a Time.new Can be modifed for special purposes.



73
74
75
# File 'lib/currency/money.rb', line 73

def self.now
  Time.new
end

.register_money_attribute(attr_opts) ⇒ Object

Called by money macro when a money attribute is created.



9
10
11
# File 'lib/currency/macro.rb', line 9

def self.register_money_attribute(attr_opts)
  (@@money_attributes[attr_opts[:class]] ||= { })[attr_opts[:attr_name]] = attr_opts
end

.us_dollar(x) ⇒ Object

Compatibility with Money package.



78
79
80
# File 'lib/currency/money.rb', line 78

def self.us_dollar(x)
  self.new(x, :USD)
end

Instance Method Details

#*(x) ⇒ Object

Money * Number => Money

Right side must be Number.



212
213
214
# File 'lib/currency/money.rb', line 212

def *(x)
   new_rep(@rep * x)
end

#+(x) ⇒ Object

Money + (Money | Number) => Money

Right side may be coerced to left side’s Currency.



198
199
200
# File 'lib/currency/money.rb', line 198

def +(x)
  new_rep(@rep + x.Money_rep(@currency))
end

#-(x) ⇒ Object

Money - (Money | Number) => Money

Right side may be coerced to left side’s Currency.



205
206
207
# File 'lib/currency/money.rb', line 205

def -(x)
  new_rep(@rep - x.Money_rep(@currency))
end

#-@Object

  • Money => Money

Negates a Money value.



191
192
193
# File 'lib/currency/money.rb', line 191

def -@
  new_rep(- @rep)
end

#/(x) ⇒ Object

Money / Money => Float (ratio)

Money / Number => Money

Right side must be Money or Number. Right side Integers are not coerced to Float before division.



222
223
224
225
226
227
228
# File 'lib/currency/money.rb', line 222

def /(x)
  if x.kind_of?(self.class)
    (@rep.to_f) / (x.Money_rep(@currency).to_f)
  else
    new_rep(@rep / x)
  end
end

#<=>(x) ⇒ Object

Compares Money values. Will convert x to self.currency before comparision.



179
180
181
182
183
184
185
# File 'lib/currency/money.rb', line 179

def <=>(x)
  if @currency == x.currency
    @rep <=> x.rep
  else
    @rep <=> convert(@currency, @time).rep
  end
end

#==(x) ⇒ Object

True if money values have the same value and currency.



171
172
173
174
175
# File 'lib/currency/money.rb', line 171

def ==(x)
   self.class == x.class && 
    @rep == x.rep && 
    @currency == x.currency
end

#centsObject

Compatibility with Money package.



84
85
86
# File 'lib/currency/money.rb', line 84

def cents
  @rep
end

#convert(currency, time = nil) ⇒ Object

Convert Money to another Currency. currency can be a Symbol or a Currency object. If currency is nil, the Currency.default is used.



144
145
146
147
148
149
150
151
152
153
# File 'lib/currency/money.rb', line 144

def convert(currency, time = nil)
  currency = ::Currency::Currency.default if currency.nil?
  currency = ::Currency::Currency.get(currency) unless currency.kind_of?(Currency)
  if @currency == currency
    self
  else
    time = self.time if time == :money
    ::Currency::Exchange::Rate::Source.current.convert(self, currency, time)
  end
end

#currencyObject

Get the Money’s Currency.



132
133
134
# File 'lib/currency/money.rb', line 132

def currency
  @currency
end

#eql?(x) ⇒ Boolean

True if money values have the same value and currency.

Returns:

  • (Boolean)


164
165
166
167
168
# File 'lib/currency/money.rb', line 164

def eql?(x)
  self.class == x.class && 
    @rep == x.rep && 
    @currency == x.currency
end

#format(*opt) ⇒ Object

Formats the Money value as a String using the Currency’s Formatter.



231
232
233
# File 'lib/currency/money.rb', line 231

def format(*opt)
  @currency.format(self, *opt)
end

#hashObject

Hash for hash table: both value and currency. See #eql? below.



158
159
160
# File 'lib/currency/money.rb', line 158

def hash
  @rep.hash ^ @currency.hash
end

#inspect(*opts) ⇒ Object

Basic inspection, with symbol, currency code and time. The standard #inspect method is available as #inspect_deep.



281
282
283
# File 'lib/currency/money.rb', line 281

def inspect(*opts)
  self.format(:symbol => true, :code => true, :time => true)
end

#Money_rep(currency, time = nil) ⇒ Object

Returns the Money’s value representation in another currency.



268
269
270
271
272
273
274
275
276
277
# File 'lib/currency/money.rb', line 268

def Money_rep(currency, time = nil)
  # Attempt conversion?
  if @currency != currency || (time && @time != time)
    
    self.convert(currency, time).rep
    # raise ::Currency::Exception::Generic, "Incompatible Currency: #{@currency} != #{currency}"
  else
    @rep
  end
end

#negative?Boolean

True if the Money’s value is less than zero.

Returns:

  • (Boolean)


263
264
265
# File 'lib/currency/money.rb', line 263

def negative?
  @rep < 0
end

#new_rep(r, time = nil) ⇒ Object

Construct from post-scaled internal representation. using the same currency.

x = Currency.Money("1.98", :USD)
x.new_rep(123) => USD $1.23

time defaults to self.time.



104
105
106
107
108
109
# File 'lib/currency/money.rb', line 104

def new_rep(r, time = nil)
  time ||= @time
  x = self.class.new(0, @currency, time)
  x.set_rep(r)
  x
end

#positive?Boolean

True if the Money’s value is greater than zero.

Returns:

  • (Boolean)


258
259
260
# File 'lib/currency/money.rb', line 258

def positive?
  @rep > 0
end

#repObject

Returns the Money representation (usually an Integer).



127
128
129
# File 'lib/currency/money.rb', line 127

def rep
  @rep
end

#set_rep(r) ⇒ Object

Do not call this method directly. CLIENTS SHOULD NEVER CALL set_rep DIRECTLY. You have been warned in ALL CAPS.



114
115
116
117
# File 'lib/currency/money.rb', line 114

def set_rep(r) # :nodoc:
  r = r.to_i unless r.kind_of?(Integer)
  @rep = r
end

#set_time(time) ⇒ Object

Do not call this method directly. CLIENTS SHOULD NEVER CALL set_time DIRECTLY. You have been warned in ALL CAPS.



122
123
124
# File 'lib/currency/money.rb', line 122

def set_time(time) # :nodoc:
  @time = time
end

#timeObject

Get the Money’s time.



137
138
139
# File 'lib/currency/money.rb', line 137

def time
  @time
end

#to_fObject

Coerces the Money’s value to a Float. May cause loss of precision.



242
243
244
# File 'lib/currency/money.rb', line 242

def to_f
  Float(@rep) / @currency.scale
end

#to_iObject

Coerces the Money’s value to an Integer. May cause loss of precision.



248
249
250
# File 'lib/currency/money.rb', line 248

def to_i
  @rep / @currency.scale
end

#to_s(*opt) ⇒ Object

Formats the Money value as a String.



236
237
238
# File 'lib/currency/money.rb', line 236

def to_s(*opt)
  @currency.format(self, *opt)
end

#zero?Boolean

True if the Money’s value is zero.

Returns:

  • (Boolean)


253
254
255
# File 'lib/currency/money.rb', line 253

def zero?
  @rep == 0
end