Class: Exchange::Money

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/exchange/money.rb

Overview

Money Objects instantiated from the money class can be used for basic mathematical operations and currency conversions

Author:

  • Beat Richartz

Since:

  • 0.1

Version:

  • 0.1

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(value, currency_arg = nil, opts = {}) {|_self| ... } ⇒ Money

Intialize the currency with a number and a currency

Examples:

Instantiate a money object of 40 US Dollars

Exchange::Money.new(40, :usd) 
  #=> #<Exchange::Money @number=40.0 @currency=:usd @time=#<Time>>

Instantiate a money object of 40 US Dollars and convert it to Euro. It shows the conversion date and the original currency

Exchange::Money.new(40, :usd).to(:eur, :at => Time.gm(2012,9,1)) 
  #=> #<Exchange::Money @number=37.0 @currency=:usd @time=#<Time> @from=#<Exchange::Money @number=40.0 @currency=:usd>>

Parameters:

  • value (Integer, Float)

    The number the currency is instantiated from

  • currency_arg (Symbol) (defaults to: nil)

    The currency the money object is in as a downcased symbol

  • opts (Hash) (defaults to: {})

    Optional Parameters for instantiation

Options Hash (opts):

  • :at (Time)

    The time at which conversion took place

  • :from (String, Symbol)

    The money object this money object was converted from

Yields:

  • (_self)

Yield Parameters:

Since:

  • 0.1

Version:

  • 0.9


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

def initialize value, currency_arg=nil, opts={}, &block
  currency_arg      = ISO.assert_currency!(currency_arg) if currency_arg
  
  @from             = opts[:from]
  @api              = Exchange.configuration.api.subclass
  
  yield(self) if block_given?
  
  self.time             = Helper.assure_time(time || opts[:at], :default => :now)
  self.value            = ISO.instantiate(value, currency || currency_arg)
  self.currency         = currency || currency_arg
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object

Method missing is used to handle conversions from one money object to another. It only handles currencies which are available in the API class set in the configuration.

Examples:

convert to chf

Exchange::Money.new(40,:usd).to(:chf)    

convert to sek at a given time

Exchange::Money.new(40,:nok).to(:sek, :at => Time.gm(2012,2,2))

Since:

  • 0.1


72
73
74
# File 'lib/exchange/money.rb', line 72

def method_missing method, *args, &block
  value.send method, *args, &block
end

Instance Attribute Details

#apiExchange::ExternalAPI (readonly)

Returns The current api subclass

Returns:

Since:

  • 0.1


35
36
37
# File 'lib/exchange/money.rb', line 35

def api
  @api
end

#currencySymbol, String

Returns currency the currency of the money object

Returns:

  • (Symbol, String)

    currency the currency of the money object

Since:

  • 0.1


22
23
24
# File 'lib/exchange/money.rb', line 22

def currency
  @currency
end

#fromExchange::Money (readonly)

Returns The original money object this money object was converted from

Returns:

  • (Exchange::Money)

    The original money object this money object was converted from

Since:

  • 0.1


31
32
33
# File 'lib/exchange/money.rb', line 31

def from
  @from
end

#timeTime

Returns The time at which the conversion has taken place or should take place if the object is involved in operations

Returns:

  • (Time)

    The time at which the conversion has taken place or should take place if the object is involved in operations

Since:

  • 0.1


26
27
28
# File 'lib/exchange/money.rb', line 26

def time
  @time
end

#valueBigDecimal

Returns number The number the money object has been instantiated from

Returns:

  • (BigDecimal)

    number The number the money object has been instantiated from

Since:

  • 0.1


18
19
20
# File 'lib/exchange/money.rb', line 18

def value
  @value
end

Instance Method Details

#*(other) ⇒ Exchange::Money

Multiply a value with the currency

Examples:

Configuration disallows mixed operations

Exchange.configuration.implicit_conversions = false
Exchange::Money.new(20,:nok) * Exchange::Money.new(20,:sek)
  #=> #<ImplicitConversionError "You tried to mix currencies">

Configuration allows mixed operations (default)

Exchange::Money.new(20,:nok) * Exchange::Money.new(20,:sek)
  #=> #<Exchange::Money @value=70.56 @currency=:nok>

Parameters:

  • other (Integer, Float, Exchange::Money)

    The value to be multiplied with the currency. If an Exchange::Money, it is converted to the instance's currency and multiplied with the converted value.

Returns:

Raises:

  • (ImplicitConversionError)

    If the configuration does not allow mixed operations, this method will raise an error if two different currencies are used in the operation

Since:

  • 0.1

Version:

  • 0.7


233
# File 'lib/exchange/money.rb', line 233

base_operation '*'

#+(other) ⇒ Exchange::Money

Add value to the currency

Examples:

Configuration disallows mixed operations

Exchange.configuration.implicit_conversions = false
Exchange::Money.new(20,:nok) + Exchange::Money.new(20,:sek)
  #=> #<ImplicitConversionError "You tried to mix currencies">

Configuration allows mixed operations (default)

Exchange::Money.new(20,:nok) + Exchange::Money.new(20,:sek)
  #=> #<Exchange::Money @value=37.56 @currency=:nok>

Parameters:

  • other (Integer, Float, Exchange::Money)

    The value to be added to the currency. If an Exchange::Money, it is converted to the instance's currency and then the converted value is added.

Returns:

Raises:

  • (ImplicitConversionError)

    If the configuration does not allow mixed operations, this method will raise an error if two different currencies are used in the operation

Since:

  • 0.1

Version:

  • 0.7


201
# File 'lib/exchange/money.rb', line 201

base_operation '+'

#-(other) ⇒ Exchange::Money

Subtract a value from the currency

Examples:

Configuration disallows implicit conversions

Exchange.configuration.implicit_conversions = false
Exchange::Money.new(20,:nok) - Exchange::Money.new(20,:sek)
  #=> #<ImplicitConversionError "You tried to mix currencies">

Configuration allows mixed operations (default)

Exchange::Money.new(20,:nok) - Exchange::Money.new(20,:sek)
  #=> #<Exchange::Money @value=7.56 @currency=:nok>

Parameters:

  • other (Integer, Float, Exchange::Money)

    The value to be subtracted from the currency. If an Exchange::Money, it is converted to the instance's currency and then subtracted from the converted value.

Returns:

Raises:

  • (ImplicitConversionError)

    If the configuration does not allow mixed operations, this method will raise an error if two different currencies are used in the operation

Since:

  • 0.1

Version:

  • 0.7


217
# File 'lib/exchange/money.rb', line 217

base_operation '-'

#/(other) ⇒ Exchange::Money

Divide the currency by a value

Examples:

Configuration disallows mixed operations

Exchange.configuration.implicit_conversions = false
Exchange::Money.new(20,:nok) / Exchange::Money.new(20,:sek)
  #=> #<ImplicitConversionError "You tried to mix currencies">

Configuration allows mixed operations (default)

Exchange::Money.new(20,:nok) / Exchange::Money.new(20,:sek)
  #=> #<Exchange::Money @value=1.56 @currency=:nok>

Parameters:

  • other (Integer, Float, Exchange::Money)

    The value to be divided by the currency. If an Exchange::Money, it is converted to the instance's currency and divided by the converted value.

Returns:

Raises:

  • (ImplicitConversionError)

    If the configuration does not allow mixed operations, this method will raise an error if two different currencies are used in the operation

Since:

  • 0.1

Version:

  • 0.7


249
# File 'lib/exchange/money.rb', line 249

base_operation '/'

#<=>(other) ⇒ Fixed

TODO:

which historic conversion should be used when two are present?

Sortcompare a currency with another currency. If the other is not an instance of Exchange::Money, the value of the currency is compared. Different currencies will be converted to the comparing instances currency

Examples:

Compare two currencies in terms of value

Exchange::Money.new(40, :usd) <=> Exchange::Money.new(28, :usd) #=> -1

Compare two different currencies, the other will get converted for comparison

Exchange::Money.new(40, :usd) <=> Exchange::Money.new(28, :eur) #=> -1

Sort multiple currencies in an array

[1.usd, 1.eur, 1.chf].sort.map(&:currency) #=> [:usd, :chf, :eur]

Parameters:

  • other (Whatever you want to throw at it)

    The counterpart to compare

Returns:

  • (Fixed)

    a number which can be used for sorting

Since:

  • 0.3

Version:

  • 0.11


289
290
291
292
293
294
295
296
297
298
# File 'lib/exchange/money.rb', line 289

def <=> other
  if is_same_currency?(other)
    value <=> other.value
  elsif is_other_currency?(other)
    test_for_currency_mix_error(other)
    value <=> other.to(currency, :at => other.time).value
  else
    value <=> other
  end
end

#==(other) ⇒ Boolean

Compare a currency with another currency or another value. If the other is not an instance of Exchange::Money, the value of the currency is compared

Examples:

Compare two currencies

Exchange::Money.new(40, :usd) == Exchange::Money.new(34, :usd) #=> true

Compare two different currencies, the other will get converted for comparison

Exchange::Money.new(40, :usd) == Exchange::Money.new(34, :eur) #=> true, will implicitly convert eur to usd at the actual rate

Compare a currency with a number, the value of the currency will get compared

Exchange::Money.new(35, :usd) == 35 #=> true

Parameters:

  • other (Whatever you want to throw at it)

    The counterpart to compare

Returns:

  • (Boolean)

    true if the other is equal, false if not

Since:

  • 0.1

Version:

  • 0.11


264
265
266
267
268
269
270
271
272
273
# File 'lib/exchange/money.rb', line 264

def == other
  if is_same_currency?(other)
    other.round.value == self.round.value
  elsif is_other_currency?(other)
    test_for_currency_mix_error(other)
    other.to(currency, :at => other.time).round.value == self.round.value
  else
    value == other
  end
end

#ceilExchange::Money

Ceil the currency. Since this is a currency, it will ceil to the standard decimal value. If you want to ceil it to another precision, you have to specifically ask for it.

Examples:

Ceil your currency to the iso standard number of decimals

Exchange::Money.new(40.544, :usd).ceil
  #=> #<Exchange::Money @value=40.55 @currency=:usd>

Ceil your currency to another number of decimals

Exchange::Money.new(40.445, :usd).ceil(0)
  #=> #<Exchange::Money @value=41 @currency=:usd>

Parameters:

  • precision (Integer)

    The precision you want the ceiling to have. Defaults to the ISO 4217 standard value for the currency

Returns:

Since:

  • 0.1

Version:

  • 0.7.1


168
# File 'lib/exchange/money.rb', line 168

install_operation :ceil

#floorExchange::Money

Floor the currency. Since this is a currency, it will ceil to the standard decimal value. If you want to ceil it to another precision, you have to specifically ask for it.

Examples:

Floor your currency to the iso standard number of decimals

Exchange::Money.new(40.545, :usd).floor
  #=> #<Exchange::Money @value=40.54 @currency=:usd>

Floor your currency to another number of decimals

Exchange::Money.new(40.545, :usd).floor(0)
  #=> #<Exchange::Money @value=40 @currency=:usd>

Parameters:

  • precision (Integer)

    The precision you want the flooring to have. Defaults to the ISO 4217 standard value for the currency

Returns:

Since:

  • 0.1

Version:

  • 0.7.1


184
# File 'lib/exchange/money.rb', line 184

install_operation :floor

#roundExchange::Money

Round the currency. Since this is a currency, it will round to the standard decimal value. If you want to round it to another precision, you have to specifically ask for it.

Examples:

Round your currency to the iso standard number of decimals

Exchange::Money.new(40.545, :usd).round
  #=> #<Exchange::Money @value=40.55 @currency=:usd>

Round your currency to another number of decimals

Exchange::Money.new(40.545, :usd).round(0)
  #=> #<Exchange::Money @value=41 @currency=:usd>

Parameters:

  • precision (Integer)

    The precision you want the rounding to have. Defaults to the ISO 4217 standard value for the currency

Returns:

Since:

  • 0.1

Version:

  • 0.7.1


152
# File 'lib/exchange/money.rb', line 152

install_operation :round

#to(other, options = {}) ⇒ Exchange::Money Also known as: in

Converts this instance of currency into another currency

Examples:

convert to 'chf'

Exchange::Money.new(40,:usd).to(:chf)

convert to 'sek' at a specific rate

Exchange::Money.new(40,:nok).to(:sek, :at => Time.gm(2012,2,2))

Parameters:

  • other (Symbol, String)

    The currency to convert the number to

  • options (Hash) (defaults to: {})

    An options hash

  • [Time] (Hash)

    a customizable set of options

Returns:

  • (Exchange::Money)

    An instance of Exchange::Money with the converted number and the converted currency

Since:

  • 0.1


86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/exchange/money.rb', line 86

def to other, options={}
  other = ISO.assert_currency!(other)

  if api_supports_currency?(currency) && api_supports_currency?(other)
    opts = { :at => time, :from => self }.merge(options)
    Money.new(api.new.convert(value, currency, other, opts), other, opts)
  elsif fallback!
    to other, options
  else
    raise_no_rate_error(other)
  end
rescue ExternalAPI::APIError
  if fallback!
    to other, options
  else
    raise
  end
end

#to_s(format = :currency) ⇒ String

Converts the currency to a string in ISO 4217 standardized format, either with or without the currency. This leaves you with no worries how to display the currency.

Examples:

Convert a currency to a string

Exchange::Money.new(49.567, :usd).to_s #=> "USD 49.57"

Convert a currency without minor to a string

Exchange::Money.new(45, :jpy).to_s #=> "JPY 45"

Convert a currency with a three decimal minor to a string

Exchange::Money.new(34.34, :omr).to_s #=> "OMR 34.340"

Convert a currency with a three decimal minor to a string with a currency symbol

Exchange::Money.new(34.34, :usd).to_s(:symbol) #=> "$34.34"

Convert a currency with a three decimal minor to a string with just the amount

Exchange::Money.new(3423.34, :usd).to_s(:amount) #=> "3,423.34"

Convert a currency with just the plain amount using decimal notation

Exchange::Money.new(3423.34, :omr).to_s(:plain) #=> "3423.340"

Parameters:

  • format (Symbol) (defaults to: :currency)

    :currency (default) if you want a string with currency, :amount if you want just the amount.

Returns:

  • (String)

    The formatted string

Since:

  • 0.3

Version:

  • 0.3


319
320
321
# File 'lib/exchange/money.rb', line 319

def to_s format=:currency
  ISO.stringify(value, currency, :format => format)
end