money 3.6.1 → 3.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.md +335 -319
- data/LICENSE +21 -21
- data/README.md +214 -209
- data/Rakefile +49 -49
- data/lib/money.rb +27 -27
- data/lib/money/bank/base.rb +131 -131
- data/lib/money/bank/variable_exchange.rb +252 -251
- data/lib/money/core_extensions.rb +82 -63
- data/lib/money/currency.rb +422 -415
- data/lib/money/money.rb +387 -1210
- data/lib/money/money/arithmetic.rb +246 -0
- data/lib/money/money/formatting.rb +234 -0
- data/lib/money/money/parsing.rb +350 -0
- data/money.gemspec +34 -27
- data/spec/bank/base_spec.rb +72 -72
- data/spec/bank/variable_exchange_spec.rb +238 -238
- data/spec/core_extensions_spec.rb +158 -142
- data/spec/currency_spec.rb +133 -128
- data/spec/money/arithmetic_spec.rb +479 -0
- data/spec/money/formatting_spec.rb +352 -0
- data/spec/money/parsing_spec.rb +197 -0
- data/spec/money_spec.rb +271 -1268
- data/spec/spec_helper.rb +28 -17
- metadata +33 -23
- data/lib/money.rbc +0 -170
- data/lib/money/bank/base.rbc +0 -800
- data/lib/money/bank/variable_exchange.rbc +0 -2496
- data/lib/money/core_extensions.rbc +0 -474
- data/lib/money/currency.rbc +0 -22600
- data/lib/money/money.rbc +0 -10070
- data/spec/bank/base_spec.rbc +0 -2409
- data/spec/bank/variable_exchange_spec.rbc +0 -7389
- data/spec/core_extensions_spec.rbc +0 -5215
- data/spec/currency_spec.rbc +0 -4341
- data/spec/money_spec.rbc +0 -50121
- data/spec/spec_helper.rbc +0 -346
@@ -0,0 +1,350 @@
|
|
1
|
+
class Money
|
2
|
+
module Parsing
|
3
|
+
def self.included(base)
|
4
|
+
base.extend ClassMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
# Parses the current string and converts it to a +Money+ object.
|
9
|
+
# Excess characters will be discarded.
|
10
|
+
#
|
11
|
+
# @param [String, #to_s] input The input to parse.
|
12
|
+
# @param [Currency, String, Symbol] currency The currency format.
|
13
|
+
# The currency to set the resulting +Money+ object to.
|
14
|
+
#
|
15
|
+
# @return [Money]
|
16
|
+
#
|
17
|
+
# @raise [ArgumentError] If any +currency+ is supplied and
|
18
|
+
# given value doesn't match the one extracted from
|
19
|
+
# the +input+ string.
|
20
|
+
#
|
21
|
+
# @example
|
22
|
+
# '100'.to_money #=> #<Money @cents=10000>
|
23
|
+
# '100.37'.to_money #=> #<Money @cents=10037>
|
24
|
+
# '100 USD'.to_money #=> #<Money @cents=10000, @currency=#<Money::Currency id: usd>>
|
25
|
+
# 'USD 100'.to_money #=> #<Money @cents=10000, @currency=#<Money::Currency id: usd>>
|
26
|
+
# '$100 USD'.to_money #=> #<Money @cents=10000, @currency=#<Money::Currency id: usd>>
|
27
|
+
# 'hello 2000 world'.to_money #=> #<Money @cents=200000 @currency=#<Money::Currency id: usd>>
|
28
|
+
#
|
29
|
+
# @example Mismatching currencies
|
30
|
+
# 'USD 2000'.to_money("EUR") #=> ArgumentError
|
31
|
+
#
|
32
|
+
# @see Money.from_string
|
33
|
+
#
|
34
|
+
def parse(input, currency = nil)
|
35
|
+
i = input.to_s
|
36
|
+
|
37
|
+
# Get the currency.
|
38
|
+
m = i.scan /([A-Z]{2,3})/
|
39
|
+
c = m[0] ? m[0][0] : nil
|
40
|
+
|
41
|
+
# check that currency passed and embedded currency are the same,
|
42
|
+
# and negotiate the final currency
|
43
|
+
if currency.nil? and c.nil?
|
44
|
+
currency = Money.default_currency
|
45
|
+
elsif currency.nil?
|
46
|
+
currency = c
|
47
|
+
elsif c.nil?
|
48
|
+
currency = currency
|
49
|
+
elsif currency != c
|
50
|
+
# TODO: ParseError
|
51
|
+
raise ArgumentError, "Mismatching Currencies"
|
52
|
+
end
|
53
|
+
currency = Money::Currency.wrap(currency)
|
54
|
+
|
55
|
+
cents = extract_cents(i, currency)
|
56
|
+
new(cents, currency)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Converts a String into a Money object treating the +value+
|
60
|
+
# as dollars and converting them to the corresponding cents value,
|
61
|
+
# according to +currency+ subunit property,
|
62
|
+
# before instantiating the Money object.
|
63
|
+
#
|
64
|
+
# Behind the scenes, this method relies on {Money.from_bigdecimal}
|
65
|
+
# to avoid problems with string-to-numeric conversion.
|
66
|
+
#
|
67
|
+
# @param [String, #to_s] value The money amount, in dollars.
|
68
|
+
# @param [Currency, String, Symbol] currency
|
69
|
+
# The currency to set the resulting +Money+ object to.
|
70
|
+
#
|
71
|
+
# @return [Money]
|
72
|
+
#
|
73
|
+
# @example
|
74
|
+
# Money.from_string("100")
|
75
|
+
# #=> #<Money @cents=10000 @currency="USD">
|
76
|
+
# Money.from_string("100", "USD")
|
77
|
+
# #=> #<Money @cents=10000 @currency="USD">
|
78
|
+
# Money.from_string("100", "EUR")
|
79
|
+
# #=> #<Money @cents=10000 @currency="EUR">
|
80
|
+
# Money.from_string("100", "BHD")
|
81
|
+
# #=> #<Money @cents=100 @currency="BHD">
|
82
|
+
#
|
83
|
+
# @see String#to_money
|
84
|
+
# @see Money.parse
|
85
|
+
#
|
86
|
+
def from_string(value, currency = Money.default_currency)
|
87
|
+
from_bigdecimal(BigDecimal.new(value.to_s), currency)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Converts a Fixnum into a Money object treating the +value+
|
91
|
+
# as dollars and converting them to the corresponding cents value,
|
92
|
+
# according to +currency+ subunit property,
|
93
|
+
# before instantiating the Money object.
|
94
|
+
#
|
95
|
+
# @param [Fixnum] value The money amount, in dollars.
|
96
|
+
# @param [Currency, String, Symbol] currency The currency format.
|
97
|
+
#
|
98
|
+
# @return [Money]
|
99
|
+
#
|
100
|
+
# @example
|
101
|
+
# Money.from_fixnum(100)
|
102
|
+
# #=> #<Money @cents=10000 @currency="USD">
|
103
|
+
# Money.from_fixnum(100, "USD")
|
104
|
+
# #=> #<Money @cents=10000 @currency="USD">
|
105
|
+
# Money.from_fixnum(100, "EUR")
|
106
|
+
# #=> #<Money @cents=10000 @currency="EUR">
|
107
|
+
# Money.from_fixnum(100, "BHD")
|
108
|
+
# #=> #<Money @cents=100 @currency="BHD">
|
109
|
+
#
|
110
|
+
# @see Fixnum#to_money
|
111
|
+
# @see Money.from_numeric
|
112
|
+
#
|
113
|
+
def from_fixnum(value, currency = Money.default_currency)
|
114
|
+
currency = Money::Currency.wrap(currency)
|
115
|
+
amount = value * currency.subunit_to_unit
|
116
|
+
new(amount, currency)
|
117
|
+
end
|
118
|
+
|
119
|
+
# Converts a Float into a Money object treating the +value+
|
120
|
+
# as dollars and converting them to the corresponding cents value,
|
121
|
+
# according to +currency+ subunit property,
|
122
|
+
# before instantiating the Money object.
|
123
|
+
#
|
124
|
+
# Behind the scenes, this method relies on Money.from_bigdecimal
|
125
|
+
# to avoid problems with floating point precision.
|
126
|
+
#
|
127
|
+
# @param [Float] value The money amount, in dollars.
|
128
|
+
# @param [Currency, String, Symbol] currency The currency format.
|
129
|
+
#
|
130
|
+
# @return [Money]
|
131
|
+
#
|
132
|
+
# @example
|
133
|
+
# Money.from_float(100.0)
|
134
|
+
# #=> #<Money @cents=10000 @currency="USD">
|
135
|
+
# Money.from_float(100.0, "USD")
|
136
|
+
# #=> #<Money @cents=10000 @currency="USD">
|
137
|
+
# Money.from_float(100.0, "EUR")
|
138
|
+
# #=> #<Money @cents=10000 @currency="EUR">
|
139
|
+
# Money.from_float(100.0, "BHD")
|
140
|
+
# #=> #<Money @cents=100 @currency="BHD">
|
141
|
+
#
|
142
|
+
# @see Float#to_money
|
143
|
+
# @see Money.from_numeric
|
144
|
+
#
|
145
|
+
def from_float(value, currency = Money.default_currency)
|
146
|
+
from_bigdecimal(BigDecimal.new(value.to_s), currency)
|
147
|
+
end
|
148
|
+
|
149
|
+
# Converts a BigDecimal into a Money object treating the +value+
|
150
|
+
# as dollars and converting them to the corresponding cents value,
|
151
|
+
# according to +currency+ subunit property,
|
152
|
+
# before instantiating the Money object.
|
153
|
+
#
|
154
|
+
# @param [BigDecimal] value The money amount, in dollars.
|
155
|
+
# @param [Currency, String, Symbol] currency The currency format.
|
156
|
+
#
|
157
|
+
# @return [Money]
|
158
|
+
#
|
159
|
+
# @example
|
160
|
+
# Money.from_bigdecimal(BigDecimal.new("100")
|
161
|
+
# #=> #<Money @cents=10000 @currency="USD">
|
162
|
+
# Money.from_bigdecimal(BigDecimal.new("100", "USD")
|
163
|
+
# #=> #<Money @cents=10000 @currency="USD">
|
164
|
+
# Money.from_bigdecimal(BigDecimal.new("100", "EUR")
|
165
|
+
# #=> #<Money @cents=10000 @currency="EUR">
|
166
|
+
# Money.from_bigdecimal(BigDecimal.new("100", "BHD")
|
167
|
+
# #=> #<Money @cents=100 @currency="BHD">
|
168
|
+
#
|
169
|
+
# @see BigDecimal#to_money
|
170
|
+
# @see Money.from_numeric
|
171
|
+
#
|
172
|
+
def from_bigdecimal(value, currency = Money.default_currency)
|
173
|
+
currency = Money::Currency.wrap(currency)
|
174
|
+
amount = value * currency.subunit_to_unit
|
175
|
+
new(amount.fix, currency)
|
176
|
+
end
|
177
|
+
|
178
|
+
# Converts a Numeric value into a Money object treating the +value+
|
179
|
+
# as dollars and converting them to the corresponding cents value,
|
180
|
+
# according to +currency+ subunit property,
|
181
|
+
# before instantiating the Money object.
|
182
|
+
#
|
183
|
+
# This method relies on various +Money.from_*+ methods
|
184
|
+
# and tries to forwards the call to the most appropriate method
|
185
|
+
# in order to reduce computation effort.
|
186
|
+
# For instance, if +value+ is an Integer, this method calls
|
187
|
+
# {Money.from_fixnum} instead of using the default
|
188
|
+
# {Money.from_bigdecimal} which adds the overload to converts
|
189
|
+
# the value into a slower BigDecimal instance.
|
190
|
+
#
|
191
|
+
# @param [Numeric] value The money amount, in dollars.
|
192
|
+
# @param [Currency, String, Symbol] currency The currency format.
|
193
|
+
#
|
194
|
+
# @return [Money]
|
195
|
+
#
|
196
|
+
# @raise +ArgumentError+ Unless +value+ is a supported type.
|
197
|
+
#
|
198
|
+
# @example
|
199
|
+
# Money.from_numeric(100)
|
200
|
+
# #=> #<Money @cents=10000 @currency="USD">
|
201
|
+
# Money.from_numeric(100.00)
|
202
|
+
# #=> #<Money @cents=10000 @currency="USD">
|
203
|
+
# Money.from_numeric("100")
|
204
|
+
# #=> ArgumentError
|
205
|
+
#
|
206
|
+
# @see Numeric#to_money
|
207
|
+
# @see Money.from_fixnum
|
208
|
+
# @see Money.from_float
|
209
|
+
# @see Money.from_bigdecimal
|
210
|
+
#
|
211
|
+
def from_numeric(value, currency = Money.default_currency)
|
212
|
+
case value
|
213
|
+
when Fixnum
|
214
|
+
from_fixnum(value, currency)
|
215
|
+
when Numeric
|
216
|
+
from_bigdecimal(BigDecimal.new(value.to_s), currency)
|
217
|
+
else
|
218
|
+
raise ArgumentError, "`value' should be a Numeric object"
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# Takes a number string and attempts to massage out the number.
|
223
|
+
#
|
224
|
+
# @param [String] input The string containing a potential number.
|
225
|
+
#
|
226
|
+
# @return [Integer]
|
227
|
+
#
|
228
|
+
def extract_cents(input, currency = Money.default_currency)
|
229
|
+
# remove anything that's not a number, potential thousands_separator, or minus sign
|
230
|
+
num = input.gsub(/[^\d|\.|,|\'|\-]/, '').strip
|
231
|
+
|
232
|
+
# set a boolean flag for if the number is negative or not
|
233
|
+
negative = num.split(//).first == "-"
|
234
|
+
|
235
|
+
# if negative, remove the minus sign from the number
|
236
|
+
# if it's not negative, the hyphen makes the value invalid
|
237
|
+
if negative
|
238
|
+
num = num.gsub(/^-/, '')
|
239
|
+
else
|
240
|
+
raise ArgumentError, "Invalid currency amount (hyphen)" if num.include?('-')
|
241
|
+
end
|
242
|
+
|
243
|
+
#if the number ends with punctuation, just throw it out. If it means decimal,
|
244
|
+
#it won't hurt anything. If it means a literal period or comma, this will
|
245
|
+
#save it from being mis-interpreted as a decimal.
|
246
|
+
num.chop! if num.match /[\.|,]$/
|
247
|
+
|
248
|
+
# gather all decimal_marks within the result number
|
249
|
+
used_decimal_marks = num.scan /[^\d]/
|
250
|
+
|
251
|
+
# determine the number of unique decimal_marks within the number
|
252
|
+
#
|
253
|
+
# e.g.
|
254
|
+
# $1,234,567.89 would return 2 (, and .)
|
255
|
+
# $125,00 would return 1
|
256
|
+
# $199 would return 0
|
257
|
+
# $1 234,567.89 would raise an error (decimal_marks are space, comma, and period)
|
258
|
+
case used_decimal_marks.uniq.length
|
259
|
+
# no decimal_mark or thousands_separator; major (dollars) is the number, and minor (cents) is 0
|
260
|
+
when 0 then major, minor = num, 0
|
261
|
+
|
262
|
+
# two decimal_marks, so we know the last item in this array is the
|
263
|
+
# major/minor thousands_separator and the rest are decimal_marks
|
264
|
+
when 2
|
265
|
+
decimal_mark, thousands_separator = used_decimal_marks.uniq
|
266
|
+
# remove all decimal_marks, split on the thousands_separator
|
267
|
+
major, minor = num.gsub(decimal_mark, '').split(thousands_separator)
|
268
|
+
min = 0 unless min
|
269
|
+
when 1
|
270
|
+
# we can't determine if the comma or period is supposed to be a decimal_mark or a thousands_separator
|
271
|
+
# e.g.
|
272
|
+
# 1,00 - comma is a thousands_separator
|
273
|
+
# 1.000 - period is a thousands_separator
|
274
|
+
# 1,000 - comma is a decimal_mark
|
275
|
+
# 1,000,000 - comma is a decimal_mark
|
276
|
+
# 10000,00 - comma is a thousands_separator
|
277
|
+
# 1000,000 - comma is a thousands_separator
|
278
|
+
|
279
|
+
# assign first decimal_mark for reusability
|
280
|
+
decimal_mark = used_decimal_marks.first
|
281
|
+
|
282
|
+
# decimal_mark is used as a decimal_mark when there are multiple instances, always
|
283
|
+
if num.scan(decimal_mark).length > 1 # multiple matches; treat as decimal_mark
|
284
|
+
major, minor = num.gsub(decimal_mark, ''), 0
|
285
|
+
else
|
286
|
+
# ex: 1,000 - 1.0000 - 10001.000
|
287
|
+
# split number into possible major (dollars) and minor (cents) values
|
288
|
+
possible_major, possible_minor = num.split(decimal_mark)
|
289
|
+
possible_major ||= "0"
|
290
|
+
possible_minor ||= "00"
|
291
|
+
|
292
|
+
# if the minor (cents) length isn't 3, assign major/minor from the possibles
|
293
|
+
# e.g.
|
294
|
+
# 1,00 => 1.00
|
295
|
+
# 1.0000 => 1.00
|
296
|
+
# 1.2 => 1.20
|
297
|
+
if possible_minor.length != 3 # thousands_separator
|
298
|
+
major, minor = possible_major, possible_minor
|
299
|
+
else
|
300
|
+
# minor length is three
|
301
|
+
# let's try to figure out intent of the thousands_separator
|
302
|
+
|
303
|
+
# the major length is greater than three, which means
|
304
|
+
# the comma or period is used as a thousands_separator
|
305
|
+
# e.g.
|
306
|
+
# 1000,000
|
307
|
+
# 100000,000
|
308
|
+
if possible_major.length > 3
|
309
|
+
major, minor = possible_major, possible_minor
|
310
|
+
else
|
311
|
+
# number is in format ###{sep}### or ##{sep}### or #{sep}###
|
312
|
+
# handle as , is sep, . is thousands_separator
|
313
|
+
if decimal_mark == '.'
|
314
|
+
major, minor = possible_major, possible_minor
|
315
|
+
else
|
316
|
+
major, minor = "#{possible_major}#{possible_minor}", 0
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
321
|
+
else
|
322
|
+
# TODO: ParseError
|
323
|
+
raise ArgumentError, "Invalid currency amount"
|
324
|
+
end
|
325
|
+
|
326
|
+
# build the string based on major/minor since decimal_mark/thousands_separator have been removed
|
327
|
+
# avoiding floating point arithmetic here to ensure accuracy
|
328
|
+
cents = (major.to_i * currency.subunit_to_unit)
|
329
|
+
# Because of an bug in JRuby, we can't just call #floor
|
330
|
+
minor = minor.to_s
|
331
|
+
minor = if minor.size < currency.decimal_places
|
332
|
+
(minor + ("0" * currency.decimal_places))[0,currency.decimal_places].to_i
|
333
|
+
elsif minor.size > currency.decimal_places
|
334
|
+
if minor[currency.decimal_places,1].to_i >= 5
|
335
|
+
minor[0,currency.decimal_places].to_i+1
|
336
|
+
else
|
337
|
+
minor[0,currency.decimal_places].to_i
|
338
|
+
end
|
339
|
+
else
|
340
|
+
minor.to_i
|
341
|
+
end
|
342
|
+
cents += minor
|
343
|
+
|
344
|
+
# if negative, multiply by -1; otherwise, return positive cents
|
345
|
+
negative ? cents * -1 : cents
|
346
|
+
end
|
347
|
+
|
348
|
+
end
|
349
|
+
end
|
350
|
+
end
|
data/money.gemspec
CHANGED
@@ -1,27 +1,34 @@
|
|
1
|
-
Gem::Specification.new do |s|
|
2
|
-
s.name = "money"
|
3
|
-
s.version = "3.6.
|
4
|
-
s.platform = Gem::Platform::RUBY
|
5
|
-
s.authors = ["Tobias Luetke", "Hongli Lai", "Jeremy McNevin",
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
s.
|
15
|
-
|
16
|
-
s.
|
17
|
-
|
18
|
-
s.
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
s.
|
24
|
-
s.
|
25
|
-
|
26
|
-
|
27
|
-
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "money"
|
3
|
+
s.version = "3.6.2"
|
4
|
+
s.platform = Gem::Platform::RUBY
|
5
|
+
s.authors = ["Tobias Luetke", "Hongli Lai", "Jeremy McNevin",
|
6
|
+
"Shane Emmons", "Simone Carletti", "Jean-Louis Giordano",
|
7
|
+
"Joshua Clayton", "Bodaniel Jeanes", "Tobias Schmidt",
|
8
|
+
"Chris Kampmeier", "Romain Gérard", "Eloy", "Josh Delsman",
|
9
|
+
"Pelle Braendgaard", "Tom Lianza", "James Cotterill",
|
10
|
+
"François Beausoleil", "Abhay Kumar", "pconnor",
|
11
|
+
"Christian Billen", "Ilia Lobsanov",
|
12
|
+
]
|
13
|
+
s.email = ["hongli@phusion.nl", "semmons99+RubyMoney@gmail.com"]
|
14
|
+
s.homepage = "http://money.rubyforge.org"
|
15
|
+
s.summary = "Money and currency exchange support library."
|
16
|
+
s.description = "This library aids one in handling money and different currencies."
|
17
|
+
|
18
|
+
s.required_rubygems_version = ">= 1.3.6"
|
19
|
+
s.rubyforge_project = "money"
|
20
|
+
|
21
|
+
s.add_dependency "i18n", "~> 0.4"
|
22
|
+
|
23
|
+
s.add_development_dependency "rspec", ">= 2.0.0"
|
24
|
+
s.add_development_dependency "yard"
|
25
|
+
s.add_development_dependency "json"
|
26
|
+
|
27
|
+
s.requirements << "json if you plan to import/export rates formatted as json"
|
28
|
+
|
29
|
+
s.files = Dir.glob("{lib,spec}/**/*")
|
30
|
+
s.files += %w(CHANGELOG.md LICENSE README.md)
|
31
|
+
s.files += %w(Rakefile .gemtest money.gemspec)
|
32
|
+
|
33
|
+
s.require_path = "lib"
|
34
|
+
end
|
data/spec/bank/base_spec.rb
CHANGED
@@ -1,72 +1,72 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe Money::Bank::Base do
|
4
|
-
before :each do
|
5
|
-
@bank = Money::Bank::Base.new
|
6
|
-
end
|
7
|
-
|
8
|
-
describe '#new with &block' do
|
9
|
-
it 'should store @rounding_method' do
|
10
|
-
proc = Proc.new{|n| n.ceil}
|
11
|
-
bank = Money::Bank::Base.new(&proc)
|
12
|
-
bank.rounding_method.should == proc
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
describe '#setup' do
|
17
|
-
it 'should call #setup after #initialize' do
|
18
|
-
class MyBank < Money::Bank::Base
|
19
|
-
attr_reader :setup_called
|
20
|
-
|
21
|
-
def setup
|
22
|
-
@setup_called = true
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
bank = MyBank.new
|
27
|
-
bank.setup_called.should == true
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
describe '#exchange_with' do
|
32
|
-
it 'should raise NotImplementedError' do
|
33
|
-
lambda { @bank.exchange_with(Money.new(100, 'USD'), 'EUR') }.should raise_exception(NotImplementedError)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
describe '#same_currency?' do
|
38
|
-
it 'should accept str/str' do
|
39
|
-
lambda{@bank.send(:same_currency?, 'USD', 'EUR')}.should_not raise_exception
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'should accept currency/str' do
|
43
|
-
lambda{@bank.send(:same_currency?, Money::Currency.wrap('USD'), 'EUR')}.should_not raise_exception
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'should accept str/currency' do
|
47
|
-
lambda{@bank.send(:same_currency?, 'USD', Money::Currency.wrap('EUR'))}.should_not raise_exception
|
48
|
-
end
|
49
|
-
|
50
|
-
it 'should accept currency/currency' do
|
51
|
-
lambda{@bank.send(:same_currency?, Money::Currency.wrap('USD'), Money::Currency.wrap('EUR'))}.should_not raise_exception
|
52
|
-
end
|
53
|
-
|
54
|
-
it 'should return `true` when currencies match' do
|
55
|
-
@bank.send(:same_currency?, 'USD', 'USD').should == true
|
56
|
-
@bank.send(:same_currency?, Money::Currency.wrap('USD'), 'USD').should == true
|
57
|
-
@bank.send(:same_currency?, 'USD', Money::Currency.wrap('USD')).should == true
|
58
|
-
@bank.send(:same_currency?, Money::Currency.wrap('USD'), Money::Currency.wrap('USD')).should == true
|
59
|
-
end
|
60
|
-
|
61
|
-
it 'should return `false` when currencies do not match' do
|
62
|
-
@bank.send(:same_currency?, 'USD', 'EUR').should == false
|
63
|
-
@bank.send(:same_currency?, Money::Currency.wrap('USD'), 'EUR').should == false
|
64
|
-
@bank.send(:same_currency?, 'USD', Money::Currency.wrap('EUR')).should == false
|
65
|
-
@bank.send(:same_currency?, Money::Currency.wrap('USD'), Money::Currency.wrap('EUR')).should == false
|
66
|
-
end
|
67
|
-
|
68
|
-
it 'should raise an UnknownCurrency exception when an unknown currency is passed' do
|
69
|
-
lambda{@bank.send(:same_currency?, 'AAA', 'BBB')}.should raise_exception(Money::Currency::UnknownCurrency)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Money::Bank::Base do
|
4
|
+
before :each do
|
5
|
+
@bank = Money::Bank::Base.new
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '#new with &block' do
|
9
|
+
it 'should store @rounding_method' do
|
10
|
+
proc = Proc.new{|n| n.ceil}
|
11
|
+
bank = Money::Bank::Base.new(&proc)
|
12
|
+
bank.rounding_method.should == proc
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#setup' do
|
17
|
+
it 'should call #setup after #initialize' do
|
18
|
+
class MyBank < Money::Bank::Base
|
19
|
+
attr_reader :setup_called
|
20
|
+
|
21
|
+
def setup
|
22
|
+
@setup_called = true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
bank = MyBank.new
|
27
|
+
bank.setup_called.should == true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#exchange_with' do
|
32
|
+
it 'should raise NotImplementedError' do
|
33
|
+
lambda { @bank.exchange_with(Money.new(100, 'USD'), 'EUR') }.should raise_exception(NotImplementedError)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#same_currency?' do
|
38
|
+
it 'should accept str/str' do
|
39
|
+
lambda{@bank.send(:same_currency?, 'USD', 'EUR')}.should_not raise_exception
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should accept currency/str' do
|
43
|
+
lambda{@bank.send(:same_currency?, Money::Currency.wrap('USD'), 'EUR')}.should_not raise_exception
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should accept str/currency' do
|
47
|
+
lambda{@bank.send(:same_currency?, 'USD', Money::Currency.wrap('EUR'))}.should_not raise_exception
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should accept currency/currency' do
|
51
|
+
lambda{@bank.send(:same_currency?, Money::Currency.wrap('USD'), Money::Currency.wrap('EUR'))}.should_not raise_exception
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should return `true` when currencies match' do
|
55
|
+
@bank.send(:same_currency?, 'USD', 'USD').should == true
|
56
|
+
@bank.send(:same_currency?, Money::Currency.wrap('USD'), 'USD').should == true
|
57
|
+
@bank.send(:same_currency?, 'USD', Money::Currency.wrap('USD')).should == true
|
58
|
+
@bank.send(:same_currency?, Money::Currency.wrap('USD'), Money::Currency.wrap('USD')).should == true
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should return `false` when currencies do not match' do
|
62
|
+
@bank.send(:same_currency?, 'USD', 'EUR').should == false
|
63
|
+
@bank.send(:same_currency?, Money::Currency.wrap('USD'), 'EUR').should == false
|
64
|
+
@bank.send(:same_currency?, 'USD', Money::Currency.wrap('EUR')).should == false
|
65
|
+
@bank.send(:same_currency?, Money::Currency.wrap('USD'), Money::Currency.wrap('EUR')).should == false
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should raise an UnknownCurrency exception when an unknown currency is passed' do
|
69
|
+
lambda{@bank.send(:same_currency?, 'AAA', 'BBB')}.should raise_exception(Money::Currency::UnknownCurrency)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|