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
70
71
72
# File 'lib/currency/money.rb', line 50

def initialize(x, currency = nil, time = nil)
  opts ||= @@empty_hash

  # Set ivars.
  currency = ::Currency::Currency.get(currency)
  @currency = 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.



93
94
95
96
97
# File 'lib/currency/money.rb', line 93

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.



76
77
78
# File 'lib/currency/money.rb', line 76

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.



81
82
83
# File 'lib/currency/money.rb', line 81

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

Instance Method Details

#*(x) ⇒ Object

Money * Number => Money

Right side must be Number.



215
216
217
# File 'lib/currency/money.rb', line 215

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

#+(x) ⇒ Object

Money + (Money | Number) => Money

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



201
202
203
# File 'lib/currency/money.rb', line 201

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.



208
209
210
# File 'lib/currency/money.rb', line 208

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

#-@Object

  • Money => Money

Negates a Money value.



194
195
196
# File 'lib/currency/money.rb', line 194

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.



225
226
227
228
229
230
231
# File 'lib/currency/money.rb', line 225

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.



182
183
184
185
186
187
188
# File 'lib/currency/money.rb', line 182

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.



174
175
176
177
178
# File 'lib/currency/money.rb', line 174

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

#centsObject

Compatibility with Money package.



87
88
89
# File 'lib/currency/money.rb', line 87

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.



147
148
149
150
151
152
153
154
155
156
# File 'lib/currency/money.rb', line 147

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.



135
136
137
# File 'lib/currency/money.rb', line 135

def currency
  @currency
end

#eql?(x) ⇒ Boolean

True if money values have the same value and currency.

Returns:

  • (Boolean)


167
168
169
170
171
# File 'lib/currency/money.rb', line 167

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.



234
235
236
# File 'lib/currency/money.rb', line 234

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

#hashObject

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



161
162
163
# File 'lib/currency/money.rb', line 161

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.



283
284
285
# File 'lib/currency/money.rb', line 283

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.



271
272
273
274
275
276
277
278
279
# File 'lib/currency/money.rb', line 271

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)


266
267
268
# File 'lib/currency/money.rb', line 266

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.



107
108
109
110
111
112
# File 'lib/currency/money.rb', line 107

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)


261
262
263
# File 'lib/currency/money.rb', line 261

def positive?
  @rep > 0
end

#repObject

Returns the Money representation (usually an Integer).



130
131
132
# File 'lib/currency/money.rb', line 130

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.



117
118
119
120
# File 'lib/currency/money.rb', line 117

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.



125
126
127
# File 'lib/currency/money.rb', line 125

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

#timeObject

Get the Money’s time.



140
141
142
# File 'lib/currency/money.rb', line 140

def time
  @time
end

#to_fObject

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



245
246
247
# File 'lib/currency/money.rb', line 245

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

#to_iObject

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



251
252
253
# File 'lib/currency/money.rb', line 251

def to_i
  @rep / @currency.scale
end

#to_s(*opt) ⇒ Object

Formats the Money value as a String.



239
240
241
# File 'lib/currency/money.rb', line 239

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

#zero?Boolean

True if the Money’s value is zero.

Returns:

  • (Boolean)


256
257
258
# File 'lib/currency/money.rb', line 256

def zero?
  @rep == 0
end