-
Notifications
You must be signed in to change notification settings - Fork 619
/
base.rb
125 lines (118 loc) · 4.34 KB
/
base.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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
120
121
122
123
124
125
class Money
# Provides classes that aid in the ability of exchange one currency with
# another.
module Bank
# The lowest Money::Bank error class.
# All Money::Bank errors should inherit from it.
class Error < StandardError
end
# Raised when the bank doesn't know about the conversion rate
# for specified currencies.
class UnknownRate < Error
end
# Money::Bank::Base is the basic interface for creating a money exchange
# object, also called Bank.
#
# A Bank is responsible for storing exchange rates, take a Money object as
# input and returns the corresponding Money object converted into an other
# currency.
#
# This class exists for aiding in the creating of other classes to exchange
# money between different currencies. When creating a subclass you will
# need to implement the following methods to exchange money between
# currencies:
#
# - #exchange_with(Money) #=> Money
#
# See Money::Bank::VariableExchange for a real example.
#
# Also, you can extend +Money::Bank::VariableExchange+ instead of
# +Money::Bank::Base+ if your bank implementation needs to store rates
# internally.
#
# @abstract Subclass and override +#exchange_with+ to implement a custom
# +Money::Bank+ class. You can also override +#setup+ instead of
# +#initialize+ to setup initial variables, etc.
class Base
# Returns the singleton instance of the Base bank.
#
# @return [Money::Bank::Base]
def self.instance
@singleton ||= self.new
end
# The rounding method to use when exchanging rates.
#
# @return [Proc]
attr_reader :rounding_method
# Initializes a new +Money::Bank::Base+ object. An optional block can be
# passed to dictate the rounding method that +#exchange_with+ can use.
#
# @yield [n] Optional block to use when rounding after exchanging one
# currency for another.
# @yieldparam [Float] n The resulting float after exchanging one currency
# for another.
# @yieldreturn [Integer]
#
# @return [Money::Bank::Base]
#
# @example
# Money::Bank::Base.new #=> #<Money::Bank::Base @rounding_method=nil>
# Money::Bank::Base.new {|n|
# n.floor
# } #=> #<Money::Bank::Base @round_method=#<Proc>>
def initialize(&block)
@rounding_method = block
setup
end
# Called after initialize. Subclasses can use this method to setup
# variables, etc that they normally would in +#initialize+.
#
# @abstract Subclass and override +#setup+ to implement a custom
# +Money::Bank+ class.
#
# @return [self]
def setup
end
# Exchanges the given +Money+ object to a new +Money+ object in
# +to_currency+.
#
# @abstract Subclass and override +#exchange_with+ to implement a custom
# +Money::Bank+ class.
#
# @raise NotImplementedError
#
# @param [Money] from The +Money+ object to exchange from.
# @param [Money::Currency, String, Symbol] to_currency The currency
# string or object to exchange to.
# @yield [n] Optional block to use to round the result after making
# the exchange.
# @yieldparam [Float] n The result after exchanging from one currency to
# the other.
# @yieldreturn [Integer]
#
# @return [Money]
def exchange_with(from, to_currency, &block)
raise NotImplementedError, "#exchange_with must be implemented"
end
# Given two currency strings or object, checks whether they're both the
# same currency. Return +true+ if the currencies are the same, +false+
# otherwise.
#
# @param [Money::Currency, String, Symbol] currency1 The first currency
# to compare.
# @param [Money::Currency, String, Symbol] currency2 The second currency
# to compare.
#
# @return [Boolean]
#
# @example
# same_currency?("usd", "USD") #=> true
# same_currency?("usd", "EUR") #=> false
# same_currency?("usd", Currency.new("USD")) #=> true
# same_currency?("usd", "USD") #=> true
def same_currency?(currency1, currency2)
Currency.wrap(currency1) == Currency.wrap(currency2)
end
end
end
end