carlosbrando-money 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,39 @@
1
+ # encoding: utf-8
2
+
3
+ # Add more from http://www.xe.com/symbols.php
4
+
5
+ class Money
6
+ SYMBOLS = {
7
+ "GBP" => { :unit => "£", :separator => ".", :delimiter => "," },
8
+ "JPY" => { :unit => "¥", :separator => ".", :delimiter => "," },
9
+ "EUR" => { :unit => "€", :separator => ".", :delimiter => "," },
10
+ "ZWD" => { :unit => "Z$", :separator => ".", :delimiter => "," },
11
+ "CNY" => { :unit => "¥", :separator => ".", :delimiter => "," },
12
+ "INR" => { :unit => "₨", :separator => ".", :delimiter => "," },
13
+ "NPR" => { :unit => "₨", :separator => ".", :delimiter => "," },
14
+ "SCR" => { :unit => "₨", :separator => ".", :delimiter => "," },
15
+ "LKR" => { :unit => "₨", :separator => ".", :delimiter => "," },
16
+ "SEK" => { :unit => "kr", :separator => ".", :delimiter => "," },
17
+ "GHC" => { :unit => "¢", :separator => ".", :delimiter => "," },
18
+ "BRL" => { :unit => "R$ ", :separator => ",", :delimiter => "." }
19
+
20
+ # Everything else defaults to :unit => "$", :separator => ".", and :delimiter => ","
21
+ }
22
+
23
+ private
24
+ def symbol_attribute(attribute, default)
25
+ SYMBOLS.has_key?(currency) && SYMBOLS[currency].has_key?(attribute) ? SYMBOLS[currency][attribute] : default
26
+ end
27
+
28
+ def currency_unit
29
+ symbol_attribute :unit, '$'
30
+ end
31
+
32
+ def currency_separator
33
+ symbol_attribute :separator, '.'
34
+ end
35
+
36
+ def currency_delimiter
37
+ symbol_attribute :delimiter, ','
38
+ end
39
+ end
@@ -0,0 +1,72 @@
1
+ require 'thread'
2
+ require 'money/errors'
3
+
4
+ # Class for aiding in exchanging money between different currencies.
5
+ # By default, the Money class uses an object of this class (accessible through
6
+ # Money#bank) for performing currency exchanges.
7
+ #
8
+ # By default, VariableExchangeBank has no knowledge about conversion rates.
9
+ # One must manually specify them with +add_rate+, after which one can perform
10
+ # exchanges with +exchange+. For example:
11
+ #
12
+ # bank = Money::VariableExchangeBank.new
13
+ # bank.add_rate("USD", "CAD", 1.24515)
14
+ # bank.add_rate("CAD", "USD", 0.803115)
15
+ #
16
+ # # Exchange 100 CAD to USD:
17
+ # bank.exchange(100_00, "CAD", "USD") # => 124
18
+ # # Exchange 100 USD to CAD:
19
+ # bank.exchange(100_00, "USD", "CAD") # => 80
20
+ class Money
21
+ class VariableExchangeBank
22
+ # Returns the singleton instance of VariableExchangeBank.
23
+ #
24
+ # By default, <tt>Money.default_bank</tt> returns the same object.
25
+ def self.instance
26
+ @@singleton
27
+ end
28
+
29
+ def initialize
30
+ @rates = {}
31
+ @mutex = Mutex.new
32
+ end
33
+
34
+ # Registers a conversion rate. +from+ and +to+ are both currency names.
35
+ def add_rate(from, to, rate)
36
+ @mutex.synchronize do
37
+ @rates["#{from}_TO_#{to}".upcase] = rate
38
+ end
39
+ end
40
+
41
+ # Gets the rate for exchanging the currency named +from+ to the currency
42
+ # named +to+. Returns nil if the rate is unknown.
43
+ def get_rate(from, to)
44
+ @mutex.synchronize do
45
+ @rates["#{from}_TO_#{to}".upcase]
46
+ end
47
+ end
48
+
49
+ # Given two currency names, checks whether they're both the same currency.
50
+ #
51
+ # bank = VariableExchangeBank.new
52
+ # bank.same_currency?("usd", "USD") # => true
53
+ # bank.same_currency?("usd", "EUR") # => false
54
+ def same_currency?(currency1, currency2)
55
+ currency1.upcase == currency2.upcase
56
+ end
57
+
58
+ # Exchange the given amount of cents in +from_currency+ to +to_currency+.
59
+ # Returns the amount of cents in +to_currency+ as an integer, rounded down.
60
+ #
61
+ # If the conversion rate is unknown, then Money::UnknownRate will be raised.
62
+ def exchange(cents, from_currency, to_currency)
63
+ rate = get_rate(from_currency, to_currency)
64
+ if !rate
65
+ raise Money::UnknownRate, "No conversion rate known for '#{from_currency}' -> '#{to_currency}'"
66
+ end
67
+ (cents * rate).floor
68
+ end
69
+
70
+ @@singleton = VariableExchangeBank.new
71
+ end
72
+ end
data/money.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "carlosbrando-money"
3
+ s.version = "2.2.0"
4
+ s.summary = "Money and currency exchange support library"
5
+ s.email = "hongli@phusion.nl"
6
+ s.homepage = "http://money.rubyforge.org/"
7
+ s.description = "Money and currency exchange support library."
8
+ s.has_rdoc = true
9
+ s.rubyforge_project = "money"
10
+ s.authors = ["Tobias Luetke", "Hongli Lai", "Jeremy McNevin", "Carlos Brando"]
11
+
12
+ s.files = [
13
+ "README.rdoc", "MIT-LICENSE", "money.gemspec", "Rakefile",
14
+ "lib/money.rb",
15
+ "lib/money/core_extensions.rb",
16
+ "lib/money/errors.rb",
17
+ "lib/money/money.rb",
18
+ "lib/money/symbols.rb",
19
+ "lib/money/variable_exchange_bank.rb",
20
+ "test/core_extensions_spec.rb",
21
+ "test/exchange_bank_spec.rb",
22
+ "test/money_spec.rb"
23
+ ]
24
+ end
@@ -0,0 +1,73 @@
1
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
2
+ require 'money/core_extensions'
3
+
4
+ describe "Money core extensions" do
5
+ specify "Numberic#to_money works" do
6
+ money = 1234.to_money
7
+ money.cents.should == 1234_00
8
+ money.currency.should == Money.default_currency
9
+
10
+ money = 100.37.to_money
11
+ money.cents.should == 100_37
12
+ money.currency.should == Money.default_currency
13
+ end
14
+
15
+ specify "String#to_money works" do
16
+ "20.15".to_money.should == Money.new(20_15)
17
+ "100".to_money.should == Money.new(100_00)
18
+ "100.37".to_money.should == Money.new(100_37)
19
+ "100,37".to_money.should == Money.new(100_37)
20
+ "100 000".to_money.should == Money.new(100_000_00)
21
+ "100,000.00".to_money.should == Money.new(100_000_00)
22
+ "1,000".to_money.should == Money.new(1_000_00)
23
+ "-1,000".to_money.should == Money.new(-1_000_00)
24
+ "1,000.5".to_money.should == Money.new(1_000_50)
25
+ "1,000.51".to_money.should == Money.new(1_000_51)
26
+ "1,000.505".to_money.should == Money.new(1_000_51)
27
+ "1,000.504".to_money.should == Money.new(1_000_50)
28
+ "1,000.0000".to_money.should == Money.new(1_000_00)
29
+ "1,000.5000".to_money.should == Money.new(1_000_50)
30
+ "1,000.5099".to_money.should == Money.new(1_000_51)
31
+ "1.550".to_money.should == Money.new(1_55)
32
+ "25.".to_money.should == Money.new(25_00)
33
+ ".75".to_money.should == Money.new(75)
34
+
35
+ "100 USD".to_money.should == Money.new(100_00, "USD")
36
+ "-100 USD".to_money.should == Money.new(-100_00, "USD")
37
+ "100 EUR".to_money.should == Money.new(100_00, "EUR")
38
+ "100.37 EUR".to_money.should == Money.new(100_37, "EUR")
39
+ "100,37 EUR".to_money.should == Money.new(100_37, "EUR")
40
+ "100,000.00 USD".to_money.should == Money.new(100_000_00, "USD")
41
+ "100.000,00 EUR".to_money.should == Money.new(100_000_00, "EUR")
42
+ "1,000 USD".to_money.should == Money.new(1_000_00, "USD")
43
+ "-1,000 USD".to_money.should == Money.new(-1_000_00, "USD")
44
+ "1,000.5500 USD".to_money.should == Money.new(1_000_55, "USD")
45
+ "-1,000.6500 USD".to_money.should == Money.new(-1_000_65, "USD")
46
+ "1.550 USD".to_money.should == Money.new(1_55, "USD")
47
+
48
+ "USD 100".to_money.should == Money.new(100_00, "USD")
49
+ "EUR 100".to_money.should == Money.new(100_00, "EUR")
50
+ "EUR 100.37".to_money.should == Money.new(100_37, "EUR")
51
+ "CAD -100.37".to_money.should == Money.new(-100_37, "CAD")
52
+ "EUR 100,37".to_money.should == Money.new(100_37, "EUR")
53
+ "EUR -100,37".to_money.should == Money.new(-100_37, "EUR")
54
+ "USD 100,000.00".to_money.should == Money.new(100_000_00, "USD")
55
+ "EUR 100.000,00".to_money.should == Money.new(100_000_00, "EUR")
56
+ "USD 1,000".to_money.should == Money.new(1_000_00, "USD")
57
+ "USD -1,000".to_money.should == Money.new(-1_000_00, "USD")
58
+ "USD 1,000.9000".to_money.should == Money.new(1_000_90, "USD")
59
+ "USD -1,000.090".to_money.should == Money.new(-1_000_09, "USD")
60
+ "USD 1.5500".to_money.should == Money.new(1_55, "USD")
61
+
62
+ "$100 USD".to_money.should == Money.new(100_00, "USD")
63
+ "$1,194.59 USD".to_money.should == Money.new(1_194_59, "USD")
64
+ "$-1,955 USD".to_money.should == Money.new(-1_955_00, "USD")
65
+ "$1,194.5900 USD".to_money.should == Money.new(1_194_59, "USD")
66
+ "$-1,955.000 USD".to_money.should == Money.new(-1_955_00, "USD")
67
+ "$1.99000 USD".to_money.should == Money.new(1_99, "USD")
68
+ end
69
+
70
+ specify "String#to_money ignores unrecognized data" do
71
+ "hello 2000 world".to_money.should == Money.new(2000_00)
72
+ end
73
+ end
@@ -0,0 +1,45 @@
1
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
2
+ require 'money/variable_exchange_bank'
3
+
4
+ describe Money::VariableExchangeBank do
5
+ before :each do
6
+ @bank = Money::VariableExchangeBank.new
7
+ end
8
+
9
+ it "returns the previously specified conversion rate" do
10
+ @bank.add_rate("USD", "EUR", 0.788332676)
11
+ @bank.add_rate("EUR", "YEN", 122.631477)
12
+ @bank.get_rate("USD", "EUR").should == 0.788332676
13
+ @bank.get_rate("EUR", "YEN").should == 122.631477
14
+ end
15
+
16
+ it "treats currency names case-insensitively" do
17
+ @bank.add_rate("usd", "eur", 1)
18
+ @bank.get_rate("USD", "EUR").should == 1
19
+ @bank.same_currency?("USD", "usd").should be_true
20
+ @bank.same_currency?("EUR", "usd").should be_false
21
+ end
22
+
23
+ it "returns nil if the conversion rate is unknown" do
24
+ @bank.get_rate("American Pesos", "EUR").should be_nil
25
+ end
26
+
27
+ it "exchanges money from one currency to another according to the specified conversion rates" do
28
+ @bank.add_rate("USD", "EUR", 0.5)
29
+ @bank.add_rate("EUR", "YEN", 10)
30
+ @bank.exchange(10_00, "USD", "EUR").should == 5_00
31
+ @bank.exchange(500_00, "EUR", "YEN").should == 5000_00
32
+ end
33
+
34
+ it "rounds the exchanged result down" do
35
+ @bank.add_rate("USD", "EUR", 0.788332676)
36
+ @bank.add_rate("EUR", "YEN", 122.631477)
37
+ @bank.exchange(10_00, "USD", "EUR").should == 788
38
+ @bank.exchange(500_00, "EUR", "YEN").should == 6131573
39
+ end
40
+
41
+ it "raises Money::UnknownRate upon conversion if the conversion rate is unknown" do
42
+ block = lambda { @bank.exchange(10, "USD", "EUR") }
43
+ block.should raise_error(Money::UnknownRate)
44
+ end
45
+ end
@@ -0,0 +1,358 @@
1
+ # encoding: utf-8
2
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
3
+ require 'money/money'
4
+ require 'money/symbols'
5
+
6
+ describe Money do
7
+ it "is associated to the singleton instance of VariableExchangeBank by default" do
8
+ Money.new(0).bank.object_id.should == Money::VariableExchangeBank.instance.object_id
9
+ end
10
+
11
+ specify "#cents returns the amount of cents passed to the constructor" do
12
+ Money.new(200_00, "USD").cents.should == 200_00
13
+ end
14
+
15
+ it "rounds the given cents to an integer" do
16
+ Money.new(1.00, "USD").cents.should == 1
17
+ Money.new(1.01, "USD").cents.should == 1
18
+ Money.new(1.50, "USD").cents.should == 2
19
+ end
20
+
21
+ specify "#currency returns the currency passed to the constructor" do
22
+ Money.new(200_00, "USD").currency.should == "USD"
23
+ end
24
+
25
+ specify "#zero? returns whether the amount is 0" do
26
+ Money.new(0, "USD").should be_zero
27
+ Money.new(0, "EUR").should be_zero
28
+ Money.new(1, "USD").should_not be_zero
29
+ Money.new(10, "YEN").should_not be_zero
30
+ Money.new(-1, "EUR").should_not be_zero
31
+ end
32
+
33
+ specify "#exchange_to exchanges the amount via its exchange bank" do
34
+ money = Money.new(100_00, "USD")
35
+ money.bank.should_receive(:exchange).with(100_00, "USD", "EUR").and_return(200_00)
36
+ money.exchange_to("EUR")
37
+ end
38
+
39
+ specify "#exchange_to exchanges the amount properly" do
40
+ money = Money.new(100_00, "USD")
41
+ money.bank.should_receive(:exchange).with(100_00, "USD", "EUR").and_return(200_00)
42
+ money.exchange_to("EUR").should == Money.new(200_00, "EUR")
43
+ end
44
+
45
+ specify "#== returns true if and only if their amount and currency are equal" do
46
+ Money.new(1_00, "USD").should == Money.new(1_00, "USD")
47
+ Money.new(1_00, "USD").should_not == Money.new(1_00, "EUR")
48
+ Money.new(1_00, "USD").should_not == Money.new(2_00, "USD")
49
+ Money.new(1_00, "USD").should_not == Money.new(99_00, "EUR")
50
+ end
51
+
52
+ specify "#== can be used to compare with a String money value" do
53
+ Money.new(1_00, "USD").should == "1.00"
54
+ Money.new(1_00, "USD").should_not == "2.00"
55
+ Money.new(1_00, "GBP").should_not == "1.00"
56
+ end
57
+
58
+ specify "#== can be used to compare with a Numeric money value" do
59
+ Money.new(1_00, "USD").should == 1
60
+ Money.new(1_57, "USD").should == 1.57
61
+ Money.new(1_00, "USD").should_not == 2
62
+ Money.new(1_00, "GBP").should_not == 1
63
+ end
64
+
65
+ specify "#== can be used to compare with an object that responds to #to_money" do
66
+ klass = Class.new do
67
+ def initialize(money)
68
+ @money = money
69
+ end
70
+
71
+ def to_money
72
+ @money
73
+ end
74
+ end
75
+
76
+ Money.new(1_00, "USD").should == klass.new(Money.new(1_00, "USD"))
77
+ Money.new(2_50, "USD").should == klass.new(Money.new(2_50, "USD"))
78
+ Money.new(2_50, "USD").should_not == klass.new(Money.new(3_00, "USD"))
79
+ Money.new(1_00, "GBP").should_not == klass.new(Money.new(1_00, "USD"))
80
+ end
81
+
82
+ specify "#== returns false if used to compare with an object that doesn't respond to #to_money" do
83
+ Money.new(1_00, "USD").should_not == Object.new
84
+ Money.new(1_00, "USD").should_not == Class
85
+ Money.new(1_00, "USD").should_not == Kernel
86
+ Money.new(1_00, "USD").should_not == /foo/
87
+ Money.new(1_00, "USD").should_not == nil
88
+ end
89
+
90
+ specify "#<=> can be used to compare with a String money value" do
91
+ (Money.new(1_00) <=> "1.00").should == 0
92
+ (Money.new(1_00) <=> ".99").should > 0
93
+ (Money.new(1_00) <=> "2.00").should < 0
94
+ end
95
+
96
+ specify "#<=> can be used to compare with a Numeric money value" do
97
+ (Money.new(1_00) <=> 1).should == 0
98
+ (Money.new(1_00) <=> 0.99).should > 0
99
+ (Money.new(1_00) <=> 2.00).should < 0
100
+ end
101
+
102
+ specify "#<=> can be used to compare with an object that responds to #to_money" do
103
+ klass = Class.new do
104
+ def initialize(money)
105
+ @money = money
106
+ end
107
+
108
+ def to_money
109
+ @money
110
+ end
111
+ end
112
+
113
+ (Money.new(1_00) <=> klass.new(Money.new(1_00))).should == 0
114
+ (Money.new(1_00) <=> klass.new(Money.new(99))).should > 0
115
+ (Money.new(1_00) <=> klass.new(Money.new(2_00))).should < 0
116
+ end
117
+
118
+ specify "#<=> raises ArgumentError when used to compare with an object that doesn't respond to #to_money" do
119
+ expected_message = /comparison .+ failed/
120
+ lambda{ Money.new(1_00) <=> Object.new }.should raise_error(ArgumentError, expected_message)
121
+ lambda{ Money.new(1_00) <=> Class }.should raise_error(ArgumentError, expected_message)
122
+ lambda{ Money.new(1_00) <=> Kernel }.should raise_error(ArgumentError, expected_message)
123
+ lambda{ Money.new(1_00) <=> /foo/ }.should raise_error(ArgumentError, expected_message)
124
+ end
125
+
126
+ specify "#* multiplies the money's amount by the multiplier while retaining the currency" do
127
+ (Money.new(1_00, "USD") * 10).should == Money.new(10_00, "USD")
128
+ end
129
+
130
+ specify "#/ divides the money's amount by the divisor while retaining the currency" do
131
+ (Money.new(10_00, "USD") / 10).should == Money.new(1_00, "USD")
132
+ end
133
+
134
+ specify "Money.empty creates a new Money object of 0 cents" do
135
+ Money.empty.should == Money.new(0)
136
+ end
137
+
138
+ specify "Money.ca_dollar creates a new Money object of the given value in CAD" do
139
+ Money.ca_dollar(50).should == Money.new(50, "CAD")
140
+ end
141
+
142
+ specify "Money.ca_dollar creates a new Money object of the given value in USD" do
143
+ Money.us_dollar(50).should == Money.new(50, "USD")
144
+ end
145
+
146
+ specify "Money.ca_dollar creates a new Money object of the given value in EUR" do
147
+ Money.euro(50).should == Money.new(50, "EUR")
148
+ end
149
+
150
+ specify "Money.new accepts { :currency => 'foo' } as the value for the 'currency' argument" do
151
+ money = Money.new(20, :currency => "EUR")
152
+ money.currency.should == "EUR"
153
+
154
+ money = Money.new(20, :currency => nil)
155
+ money.currency.should == Money.default_currency
156
+ end
157
+
158
+ specify "Money.add_rate works" do
159
+ Money.add_rate("EUR", "USD", 10)
160
+ Money.new(10_00, "EUR").exchange_to("USD").should == Money.new(100_00, "USD")
161
+ end
162
+
163
+ specify "Money.to_s works" do
164
+ Money.new(10_00).to_s.should == "10.00"
165
+ end
166
+
167
+ specify "Money.to_f works" do
168
+ Money.new(10_00).to_f.should == 10.0
169
+ end
170
+
171
+ describe "#format" do
172
+ it "returns the monetary value as a string" do
173
+ Money.ca_dollar(100).format.should == "$1.00"
174
+ end
175
+
176
+ describe "if the monetary value is 0" do
177
+ before :each do
178
+ @money = Money.us_dollar(0)
179
+ end
180
+
181
+ it "returns 'free' when :display_free is true" do
182
+ @money.format(:display_free => true).should == 'free'
183
+ end
184
+
185
+ it "returns '$0.00' when :display_free is false or not given" do
186
+ @money.format.should == '$0.00'
187
+ @money.format(:display_free => false).should == '$0.00'
188
+ @money.format(:display_free => nil).should == '$0.00'
189
+ end
190
+
191
+ it "returns the value specified by :display_free if it's a string-like object" do
192
+ @money.format(:display_free => 'gratis').should == 'gratis'
193
+ end
194
+ end
195
+
196
+ specify "#format(:with_currency => true) works as documented" do
197
+ Money.ca_dollar(100).format(:with_currency => true).should == "$1.00 CAD"
198
+ Money.us_dollar(85).format(:with_currency => true).should == "$0.85 USD"
199
+ Money.brazilian_real(85).format(:with_currency).should == "R$ 0,85 BRL"
200
+ end
201
+
202
+ specify "#format(:with_currency) works as documented" do
203
+ Money.ca_dollar(100).format(:with_currency).should == "$1.00 CAD"
204
+ Money.us_dollar(85).format(:with_currency).should == "$0.85 USD"
205
+ end
206
+
207
+ specify "#format(:no_cents => true) works as documented" do
208
+ Money.ca_dollar(100).format(:no_cents => true).should == "$1"
209
+ Money.ca_dollar(599).format(:no_cents => true).should == "$5"
210
+ Money.ca_dollar(570).format(:no_cents => true, :with_currency => true).should == "$5 CAD"
211
+ Money.brazilian_real(390_00).format(:no_cents => true).should == "R$ 390"
212
+ end
213
+
214
+ specify "#format(:no_cents) works as documented" do
215
+ Money.ca_dollar(100).format(:no_cents).should == "$1"
216
+ Money.ca_dollar(599).format(:no_cents).should == "$5"
217
+ Money.ca_dollar(570).format(:no_cents, :with_currency).should == "$5 CAD"
218
+ Money.ca_dollar(39000).format(:no_cents).should == "$390"
219
+ end
220
+
221
+ specify "#format(:symbol => a symbol string) uses the given value as the money symbol" do
222
+ Money.new(100, "GBP").format(:symbol => "£").should == "£1.00"
223
+ end
224
+
225
+ specify "#format(:symbol => true) returns symbol based on the given currency code" do
226
+ one = Proc.new do |currency|
227
+ Money.new(1_000_00, currency).format(:symbol => true)
228
+ end
229
+
230
+ # Pounds
231
+ one["GBP"].should == "£1,000.00"
232
+
233
+ # Dollars
234
+ one["USD"].should == "$1,000.00"
235
+ one["CAD"].should == "$1,000.00"
236
+ one["AUD"].should == "$1,000.00"
237
+ one["NZD"].should == "$1,000.00"
238
+ one["ZWD"].should == "Z$1,000.00"
239
+
240
+ # Yen
241
+ one["JPY"].should == "¥1,000.00"
242
+ one["CNY"].should == "¥1,000.00"
243
+
244
+ # Euro
245
+ one["EUR"].should == "€1,000.00"
246
+
247
+ # Rupees
248
+ one["INR"].should == "₨1,000.00"
249
+ one["NPR"].should == "₨1,000.00"
250
+ one["SCR"].should == "₨1,000.00"
251
+ one["LKR"].should == "₨1,000.00"
252
+
253
+ # Brazilian Real
254
+ one["BRL"].should == "R$ 1.000,00"
255
+
256
+ # Other
257
+ one["SEK"].should == "kr1,000.00"
258
+ one["GHC"].should == "¢1,000.00"
259
+ end
260
+
261
+ specify "#format(:symbol => true) returns $ when currency code is not recognized" do
262
+ Money.new(100, "XYZ").format(:symbol => true).should == "$1.00"
263
+ end
264
+
265
+ specify "#format(:symbol => some non-Boolean value that evaluates to true) returs symbol based on the given currency code" do
266
+ Money.new(100, "GBP").format(:symbol => true).should == "£1.00"
267
+ Money.new(100, "EUR").format(:symbol => true).should == "€1.00"
268
+ Money.new(100, "SEK").format(:symbol => true).should == "kr1.00"
269
+ end
270
+
271
+ specify "#format with :symbol == "", nil or false returns the amount without a symbol" do
272
+ money = Money.new(100, "GBP")
273
+ money.format(:symbol => "").should == "1.00"
274
+ money.format(:symbol => nil).should == "1.00"
275
+ money.format(:symbol => false).should == "1.00"
276
+ end
277
+
278
+ specify "#format without :symbol assumes that :symbol is set to true" do
279
+ money = Money.new(100)
280
+ money.format.should == "$1.00"
281
+
282
+ money = Money.new(100, "GBP")
283
+ money.format.should == "£1.00"
284
+
285
+ money = Money.new(100, "XYZ")
286
+ money.format.should == "$1.00"
287
+ end
288
+
289
+ specify "#format(:html => true) works as documented" do
290
+ string = Money.ca_dollar(570).format(:html => true, :with_currency => true)
291
+ string.should == "$5.70 <span class=\"currency\">CAD</span>"
292
+ end
293
+
294
+ it "should insert commas into the result if the amount is sufficiently large" do
295
+ Money.us_dollar(1_000_000_000_12).format.should == "$1,000,000,000.12"
296
+ Money.us_dollar(1_000_000_000_12).format(:no_cents => true).should == "$1,000,000,000"
297
+
298
+ Money.brazilian_real(1_000_000_000_12).format.should == "R$ 1.000.000.000,12"
299
+ Money.brazilian_real(1_000_000_000_12).format(:no_cents => true).should == "R$ 1.000.000.000"
300
+ end
301
+ end
302
+ end
303
+
304
+ describe "Actions involving two Money objects" do
305
+ describe "if the other Money object has the same currency" do
306
+ specify "#<=> compares the two objects' amounts" do
307
+ (Money.new(1_00, "USD") <=> Money.new(1_00, "USD")).should == 0
308
+ (Money.new(1_00, "USD") <=> Money.new(99, "USD")).should > 0
309
+ (Money.new(1_00, "USD") <=> Money.new(2_00, "USD")).should < 0
310
+ end
311
+
312
+ specify "#+ adds the other object's amount to the current object's amount while retaining the currency" do
313
+ (Money.new(10_00, "USD") + Money.new(90, "USD")).should == Money.new(10_90, "USD")
314
+ end
315
+
316
+ specify "#- substracts the other object's amount from the current object's amount while retaining the currency" do
317
+ (Money.new(10_00, "USD") - Money.new(90, "USD")).should == Money.new(9_10, "USD")
318
+ end
319
+
320
+ specify "#/ divides the current object's amount by the other object's amount resulting in a float" do
321
+ (Money.new(10_00, "USD") / Money.new(100_00, "USD")).should == 0.1
322
+ end
323
+ end
324
+
325
+ describe "if the other Money object has a different currency" do
326
+ specify "#<=> compares the two objects' amount after converting the other object's amount to its own currency" do
327
+ target = Money.new(200_00, "EUR")
328
+ target.should_receive(:exchange_to).with("USD").and_return(Money.new(300_00, "USD"))
329
+ (Money.new(100_00, "USD") <=> target).should < 0
330
+
331
+ target = Money.new(200_00, "EUR")
332
+ target.should_receive(:exchange_to).with("USD").and_return(Money.new(100_00, "USD"))
333
+ (Money.new(100_00, "USD") <=> target).should == 0
334
+
335
+ target = Money.new(200_00, "EUR")
336
+ target.should_receive(:exchange_to).with("USD").and_return(Money.new(99_00, "USD"))
337
+ (Money.new(100_00, "USD") <=> target).should > 0
338
+ end
339
+
340
+ specify "#+ adds the other object's amount, converted to this object's currency, to this object's amount while retaining its currency" do
341
+ other = Money.new(90, "EUR")
342
+ other.should_receive(:exchange_to).with("USD").and_return(Money.new(9_00, "USD"))
343
+ (Money.new(10_00, "USD") + other).should == Money.new(19_00, "USD")
344
+ end
345
+
346
+ specify "#- substracts the other object's amount, converted to this object's currency, from this object's amount while retaining its currency" do
347
+ other = Money.new(90, "EUR")
348
+ other.should_receive(:exchange_to).with("USD").and_return(Money.new(9_00, "USD"))
349
+ (Money.new(10_00, "USD") - other).should == Money.new(1_00, "USD")
350
+ end
351
+
352
+ specify "#/ divides the this object's amount by the other objects's amount, converted to this object's currency, resulting in a float" do
353
+ other = Money.new(1000, "EUR")
354
+ other.should_receive(:exchange_to).with("USD").and_return(Money.new(100_00, "USD"))
355
+ (Money.new(10_00, "USD") / other).should == 0.1
356
+ end
357
+ end
358
+ end