money 3.7.1 → 4.0.0

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.
Files changed (43) hide show
  1. data/CHANGELOG.md +384 -351
  2. data/LICENSE +21 -21
  3. data/README.md +243 -214
  4. data/Rakefile +49 -49
  5. data/lib/money.rb +28 -27
  6. data/lib/money/bank/base.rb +131 -131
  7. data/lib/money/bank/variable_exchange.rb +252 -252
  8. data/lib/money/core_extensions.rb +82 -82
  9. data/lib/money/currency.rb +263 -422
  10. data/lib/money/currency_loader.rb +19 -0
  11. data/lib/money/money.rb +405 -405
  12. data/lib/money/money/arithmetic.rb +246 -246
  13. data/lib/money/money/formatting.rb +260 -244
  14. data/lib/money/money/parsing.rb +350 -350
  15. data/money.gemspec +29 -35
  16. data/spec/bank/base_spec.rb +72 -72
  17. data/spec/bank/variable_exchange_spec.rb +238 -238
  18. data/spec/core_extensions_spec.rb +158 -158
  19. data/spec/currency_spec.rb +120 -133
  20. data/spec/money/arithmetic_spec.rb +479 -479
  21. data/spec/money/formatting_spec.rb +383 -375
  22. data/spec/money/parsing_spec.rb +197 -197
  23. data/spec/money_spec.rb +292 -292
  24. data/spec/spec_helper.rb +28 -28
  25. metadata +54 -126
  26. data/lib/money.rbc +0 -184
  27. data/lib/money/bank/base.rbc +0 -818
  28. data/lib/money/bank/variable_exchange.rbc +0 -2550
  29. data/lib/money/core_extensions.rbc +0 -664
  30. data/lib/money/currency.rbc +0 -22708
  31. data/lib/money/money.rbc +0 -3861
  32. data/lib/money/money/arithmetic.rbc +0 -2778
  33. data/lib/money/money/formatting.rbc +0 -2265
  34. data/lib/money/money/parsing.rbc +0 -2737
  35. data/spec/bank/base_spec.rbc +0 -2461
  36. data/spec/bank/variable_exchange_spec.rbc +0 -7541
  37. data/spec/core_extensions_spec.rbc +0 -5921
  38. data/spec/currency_spec.rbc +0 -4535
  39. data/spec/money/arithmetic_spec.rbc +0 -25140
  40. data/spec/money/formatting_spec.rbc +0 -12545
  41. data/spec/money/parsing_spec.rbc +0 -6511
  42. data/spec/money_spec.rbc +0 -9824
  43. data/spec/spec_helper.rbc +0 -575
@@ -1,197 +1,197 @@
1
- # encoding: utf-8
2
-
3
- require "spec_helper"
4
-
5
- describe Money do
6
- describe "Money.parse" do
7
-
8
- it "should be able to parse european-formatted inputs under 10EUR" do
9
- five_ninety_five = Money.new(595, 'EUR')
10
-
11
- Money.parse('EUR 5,95').should == five_ninety_five
12
- #TODO: try and handle these
13
- #Money.parse('€5,95').should == five_ninety_five
14
- #Money.parse('$5.95').should == five_ninety_five
15
- end
16
-
17
- it "should be able to parse european-formatted inputs with multiple thousands-seperators" do
18
- Money.parse('EUR 1.234.567,89').should == Money.new(123456789, 'EUR')
19
- Money.parse('EUR 1.111.234.567,89').should == Money.new(111123456789, 'EUR')
20
- end
21
-
22
- it "should be able to parse USD-formatted inputs under $10" do
23
- five_ninety_five = Money.new(595, 'USD')
24
-
25
- Money.parse(5.95).should == five_ninety_five
26
- Money.parse('5.95').should == five_ninety_five
27
- Money.parse('$5.95').should == five_ninety_five
28
- Money.parse("\n $5.95 \n").should == five_ninety_five
29
- Money.parse('$ 5.95').should == five_ninety_five
30
- Money.parse('$5.95 ea.').should == five_ninety_five
31
- Money.parse('$5.95, each').should == five_ninety_five
32
- end
33
-
34
- it "should be able to parse USD-formatted inputs with multiple thousands-seperators" do
35
- Money.parse('1,234,567.89').should == Money.new(123456789, 'USD')
36
- Money.parse('1,111,234,567.89').should == Money.new(111123456789, 'USD')
37
- end
38
-
39
- it "should not return a price if there is a price range" do
40
- lambda {Money.parse('$5.95-10.95')}.should raise_error ArgumentError
41
- lambda {Money.parse('$5.95 - 10.95')}.should raise_error ArgumentError
42
- lambda {Money.parse('$5.95 - $10.95')}.should raise_error ArgumentError
43
- end
44
-
45
- it "should not return a price for completely invalid input" do
46
- # TODO: shouldn't these throw an error instead of being considered
47
- # equal to $0.0?
48
- empty_price = Money.new(0, 'USD')
49
-
50
- Money.parse(nil).should == empty_price
51
- Money.parse('hellothere').should == empty_price
52
- Money.parse('').should == empty_price
53
- end
54
- end
55
-
56
- describe "Money.from_string" do
57
- it "converts given amount to cents" do
58
- Money.from_string("1").should == Money.new(1_00)
59
- Money.from_string("1").should == Money.new(1_00, "USD")
60
- Money.from_string("1", "EUR").should == Money.new(1_00, "EUR")
61
- end
62
-
63
- it "should respect :subunit_to_unit currency property" do
64
- Money.from_string("1", "USD").should == Money.new(1_00, "USD")
65
- Money.from_string("1", "TND").should == Money.new(1_000, "TND")
66
- Money.from_string("1", "CLP").should == Money.new(1, "CLP")
67
- end
68
-
69
- it "accepts a currency options" do
70
- m = Money.from_string("1")
71
- m.currency.should == Money.default_currency
72
-
73
- m = Money.from_string("1", Money::Currency.wrap("EUR"))
74
- m.currency.should == Money::Currency.wrap("EUR")
75
-
76
- m = Money.from_string("1", "EUR")
77
- m.currency.should == Money::Currency.wrap("EUR")
78
- end
79
- end
80
-
81
- describe "Money.from_fixnum" do
82
- it "converts given amount to cents" do
83
- Money.from_fixnum(1).should == Money.new(1_00)
84
- Money.from_fixnum(1).should == Money.new(1_00, "USD")
85
- Money.from_fixnum(1, "EUR").should == Money.new(1_00, "EUR")
86
- end
87
-
88
- it "should respect :subunit_to_unit currency property" do
89
- Money.from_fixnum(1, "USD").should == Money.new(1_00, "USD")
90
- Money.from_fixnum(1, "TND").should == Money.new(1_000, "TND")
91
- Money.from_fixnum(1, "CLP").should == Money.new(1, "CLP")
92
- end
93
-
94
- it "accepts a currency options" do
95
- m = Money.from_fixnum(1)
96
- m.currency.should == Money.default_currency
97
-
98
- m = Money.from_fixnum(1, Money::Currency.wrap("EUR"))
99
- m.currency.should == Money::Currency.wrap("EUR")
100
-
101
- m = Money.from_fixnum(1, "EUR")
102
- m.currency.should == Money::Currency.wrap("EUR")
103
- end
104
- end
105
-
106
- describe "Money.from_float" do
107
- it "converts given amount to cents" do
108
- Money.from_float(1.2).should == Money.new(1_20)
109
- Money.from_float(1.2).should == Money.new(1_20, "USD")
110
- Money.from_float(1.2, "EUR").should == Money.new(1_20, "EUR")
111
- end
112
-
113
- it "should respect :subunit_to_unit currency property" do
114
- Money.from_float(1.2, "USD").should == Money.new(1_20, "USD")
115
- Money.from_float(1.2, "TND").should == Money.new(1_200, "TND")
116
- Money.from_float(1.2, "CLP").should == Money.new(1, "CLP")
117
- end
118
-
119
- it "accepts a currency options" do
120
- m = Money.from_float(1.2)
121
- m.currency.should == Money.default_currency
122
-
123
- m = Money.from_float(1.2, Money::Currency.wrap("EUR"))
124
- m.currency.should == Money::Currency.wrap("EUR")
125
-
126
- m = Money.from_float(1.2, "EUR")
127
- m.currency.should == Money::Currency.wrap("EUR")
128
- end
129
- end
130
-
131
- describe "Money.from_bigdecimal" do
132
- it "converts given amount to cents" do
133
- Money.from_bigdecimal(BigDecimal.new("1")).should == Money.new(1_00)
134
- Money.from_bigdecimal(BigDecimal.new("1")).should == Money.new(1_00, "USD")
135
- Money.from_bigdecimal(BigDecimal.new("1"), "EUR").should == Money.new(1_00, "EUR")
136
- end
137
-
138
- it "should respect :subunit_to_unit currency property" do
139
- Money.from_bigdecimal(BigDecimal.new("1"), "USD").should == Money.new(1_00, "USD")
140
- Money.from_bigdecimal(BigDecimal.new("1"), "TND").should == Money.new(1_000, "TND")
141
- Money.from_bigdecimal(BigDecimal.new("1"), "CLP").should == Money.new(1, "CLP")
142
- end
143
-
144
- it "accepts a currency options" do
145
- m = Money.from_bigdecimal(BigDecimal.new("1"))
146
- m.currency.should == Money.default_currency
147
-
148
- m = Money.from_bigdecimal(BigDecimal.new("1"), Money::Currency.wrap("EUR"))
149
- m.currency.should == Money::Currency.wrap("EUR")
150
-
151
- m = Money.from_bigdecimal(BigDecimal.new("1"), "EUR")
152
- m.currency.should == Money::Currency.wrap("EUR")
153
- end
154
- end
155
-
156
- describe "Money.from_numeric" do
157
- it "converts given amount to cents" do
158
- Money.from_numeric(1).should == Money.new(1_00)
159
- Money.from_numeric(1.0).should == Money.new(1_00)
160
- Money.from_numeric(BigDecimal.new("1")).should == Money.new(1_00)
161
- end
162
-
163
- it "should raise ArgumentError with unsupported argument" do
164
- lambda { Money.from_numeric("100") }.should raise_error(ArgumentError)
165
- end
166
-
167
- it "should optimize workload" do
168
- Money.should_receive(:from_fixnum).with(1, "USD").and_return(Money.new(1_00, "USD"))
169
- Money.from_numeric(1, "USD").should == Money.new(1_00, "USD")
170
- Money.should_receive(:from_bigdecimal).with(BigDecimal.new("1.0"), "USD").and_return(Money.new(1_00, "USD"))
171
- Money.from_numeric(1.0, "USD").should == Money.new(1_00, "USD")
172
- end
173
-
174
- it "should respect :subunit_to_unit currency property" do
175
- Money.from_numeric(1, "USD").should == Money.new(1_00, "USD")
176
- Money.from_numeric(1, "TND").should == Money.new(1_000, "TND")
177
- Money.from_numeric(1, "CLP").should == Money.new(1, "CLP")
178
- end
179
-
180
- it "accepts a bank option" do
181
- Money.from_numeric(1).should == Money.new(1_00)
182
- Money.from_numeric(1).should == Money.new(1_00, "USD")
183
- Money.from_numeric(1, "EUR").should == Money.new(1_00, "EUR")
184
- end
185
-
186
- it "accepts a currency options" do
187
- m = Money.from_numeric(1)
188
- m.currency.should == Money.default_currency
189
-
190
- m = Money.from_numeric(1, Money::Currency.wrap("EUR"))
191
- m.currency.should == Money::Currency.wrap("EUR")
192
-
193
- m = Money.from_numeric(1, "EUR")
194
- m.currency.should == Money::Currency.wrap("EUR")
195
- end
196
- end
197
- end
1
+ # encoding: utf-8
2
+
3
+ require "spec_helper"
4
+
5
+ describe Money do
6
+ describe "Money.parse" do
7
+
8
+ it "should be able to parse european-formatted inputs under 10EUR" do
9
+ five_ninety_five = Money.new(595, 'EUR')
10
+
11
+ Money.parse('EUR 5,95').should == five_ninety_five
12
+ #TODO: try and handle these
13
+ #Money.parse('€5,95').should == five_ninety_five
14
+ #Money.parse('$5.95').should == five_ninety_five
15
+ end
16
+
17
+ it "should be able to parse european-formatted inputs with multiple thousands-seperators" do
18
+ Money.parse('EUR 1.234.567,89').should == Money.new(123456789, 'EUR')
19
+ Money.parse('EUR 1.111.234.567,89').should == Money.new(111123456789, 'EUR')
20
+ end
21
+
22
+ it "should be able to parse USD-formatted inputs under $10" do
23
+ five_ninety_five = Money.new(595, 'USD')
24
+
25
+ Money.parse(5.95).should == five_ninety_five
26
+ Money.parse('5.95').should == five_ninety_five
27
+ Money.parse('$5.95').should == five_ninety_five
28
+ Money.parse("\n $5.95 \n").should == five_ninety_five
29
+ Money.parse('$ 5.95').should == five_ninety_five
30
+ Money.parse('$5.95 ea.').should == five_ninety_five
31
+ Money.parse('$5.95, each').should == five_ninety_five
32
+ end
33
+
34
+ it "should be able to parse USD-formatted inputs with multiple thousands-seperators" do
35
+ Money.parse('1,234,567.89').should == Money.new(123456789, 'USD')
36
+ Money.parse('1,111,234,567.89').should == Money.new(111123456789, 'USD')
37
+ end
38
+
39
+ it "should not return a price if there is a price range" do
40
+ lambda {Money.parse('$5.95-10.95')}.should raise_error ArgumentError
41
+ lambda {Money.parse('$5.95 - 10.95')}.should raise_error ArgumentError
42
+ lambda {Money.parse('$5.95 - $10.95')}.should raise_error ArgumentError
43
+ end
44
+
45
+ it "should not return a price for completely invalid input" do
46
+ # TODO: shouldn't these throw an error instead of being considered
47
+ # equal to $0.0?
48
+ empty_price = Money.new(0, 'USD')
49
+
50
+ Money.parse(nil).should == empty_price
51
+ Money.parse('hellothere').should == empty_price
52
+ Money.parse('').should == empty_price
53
+ end
54
+ end
55
+
56
+ describe "Money.from_string" do
57
+ it "converts given amount to cents" do
58
+ Money.from_string("1").should == Money.new(1_00)
59
+ Money.from_string("1").should == Money.new(1_00, "USD")
60
+ Money.from_string("1", "EUR").should == Money.new(1_00, "EUR")
61
+ end
62
+
63
+ it "should respect :subunit_to_unit currency property" do
64
+ Money.from_string("1", "USD").should == Money.new(1_00, "USD")
65
+ Money.from_string("1", "TND").should == Money.new(1_000, "TND")
66
+ Money.from_string("1", "CLP").should == Money.new(1, "CLP")
67
+ end
68
+
69
+ it "accepts a currency options" do
70
+ m = Money.from_string("1")
71
+ m.currency.should == Money.default_currency
72
+
73
+ m = Money.from_string("1", Money::Currency.wrap("EUR"))
74
+ m.currency.should == Money::Currency.wrap("EUR")
75
+
76
+ m = Money.from_string("1", "EUR")
77
+ m.currency.should == Money::Currency.wrap("EUR")
78
+ end
79
+ end
80
+
81
+ describe "Money.from_fixnum" do
82
+ it "converts given amount to cents" do
83
+ Money.from_fixnum(1).should == Money.new(1_00)
84
+ Money.from_fixnum(1).should == Money.new(1_00, "USD")
85
+ Money.from_fixnum(1, "EUR").should == Money.new(1_00, "EUR")
86
+ end
87
+
88
+ it "should respect :subunit_to_unit currency property" do
89
+ Money.from_fixnum(1, "USD").should == Money.new(1_00, "USD")
90
+ Money.from_fixnum(1, "TND").should == Money.new(1_000, "TND")
91
+ Money.from_fixnum(1, "CLP").should == Money.new(1, "CLP")
92
+ end
93
+
94
+ it "accepts a currency options" do
95
+ m = Money.from_fixnum(1)
96
+ m.currency.should == Money.default_currency
97
+
98
+ m = Money.from_fixnum(1, Money::Currency.wrap("EUR"))
99
+ m.currency.should == Money::Currency.wrap("EUR")
100
+
101
+ m = Money.from_fixnum(1, "EUR")
102
+ m.currency.should == Money::Currency.wrap("EUR")
103
+ end
104
+ end
105
+
106
+ describe "Money.from_float" do
107
+ it "converts given amount to cents" do
108
+ Money.from_float(1.2).should == Money.new(1_20)
109
+ Money.from_float(1.2).should == Money.new(1_20, "USD")
110
+ Money.from_float(1.2, "EUR").should == Money.new(1_20, "EUR")
111
+ end
112
+
113
+ it "should respect :subunit_to_unit currency property" do
114
+ Money.from_float(1.2, "USD").should == Money.new(1_20, "USD")
115
+ Money.from_float(1.2, "TND").should == Money.new(1_200, "TND")
116
+ Money.from_float(1.2, "CLP").should == Money.new(1, "CLP")
117
+ end
118
+
119
+ it "accepts a currency options" do
120
+ m = Money.from_float(1.2)
121
+ m.currency.should == Money.default_currency
122
+
123
+ m = Money.from_float(1.2, Money::Currency.wrap("EUR"))
124
+ m.currency.should == Money::Currency.wrap("EUR")
125
+
126
+ m = Money.from_float(1.2, "EUR")
127
+ m.currency.should == Money::Currency.wrap("EUR")
128
+ end
129
+ end
130
+
131
+ describe "Money.from_bigdecimal" do
132
+ it "converts given amount to cents" do
133
+ Money.from_bigdecimal(BigDecimal.new("1")).should == Money.new(1_00)
134
+ Money.from_bigdecimal(BigDecimal.new("1")).should == Money.new(1_00, "USD")
135
+ Money.from_bigdecimal(BigDecimal.new("1"), "EUR").should == Money.new(1_00, "EUR")
136
+ end
137
+
138
+ it "should respect :subunit_to_unit currency property" do
139
+ Money.from_bigdecimal(BigDecimal.new("1"), "USD").should == Money.new(1_00, "USD")
140
+ Money.from_bigdecimal(BigDecimal.new("1"), "TND").should == Money.new(1_000, "TND")
141
+ Money.from_bigdecimal(BigDecimal.new("1"), "CLP").should == Money.new(1, "CLP")
142
+ end
143
+
144
+ it "accepts a currency options" do
145
+ m = Money.from_bigdecimal(BigDecimal.new("1"))
146
+ m.currency.should == Money.default_currency
147
+
148
+ m = Money.from_bigdecimal(BigDecimal.new("1"), Money::Currency.wrap("EUR"))
149
+ m.currency.should == Money::Currency.wrap("EUR")
150
+
151
+ m = Money.from_bigdecimal(BigDecimal.new("1"), "EUR")
152
+ m.currency.should == Money::Currency.wrap("EUR")
153
+ end
154
+ end
155
+
156
+ describe "Money.from_numeric" do
157
+ it "converts given amount to cents" do
158
+ Money.from_numeric(1).should == Money.new(1_00)
159
+ Money.from_numeric(1.0).should == Money.new(1_00)
160
+ Money.from_numeric(BigDecimal.new("1")).should == Money.new(1_00)
161
+ end
162
+
163
+ it "should raise ArgumentError with unsupported argument" do
164
+ lambda { Money.from_numeric("100") }.should raise_error(ArgumentError)
165
+ end
166
+
167
+ it "should optimize workload" do
168
+ Money.should_receive(:from_fixnum).with(1, "USD").and_return(Money.new(1_00, "USD"))
169
+ Money.from_numeric(1, "USD").should == Money.new(1_00, "USD")
170
+ Money.should_receive(:from_bigdecimal).with(BigDecimal.new("1.0"), "USD").and_return(Money.new(1_00, "USD"))
171
+ Money.from_numeric(1.0, "USD").should == Money.new(1_00, "USD")
172
+ end
173
+
174
+ it "should respect :subunit_to_unit currency property" do
175
+ Money.from_numeric(1, "USD").should == Money.new(1_00, "USD")
176
+ Money.from_numeric(1, "TND").should == Money.new(1_000, "TND")
177
+ Money.from_numeric(1, "CLP").should == Money.new(1, "CLP")
178
+ end
179
+
180
+ it "accepts a bank option" do
181
+ Money.from_numeric(1).should == Money.new(1_00)
182
+ Money.from_numeric(1).should == Money.new(1_00, "USD")
183
+ Money.from_numeric(1, "EUR").should == Money.new(1_00, "EUR")
184
+ end
185
+
186
+ it "accepts a currency options" do
187
+ m = Money.from_numeric(1)
188
+ m.currency.should == Money.default_currency
189
+
190
+ m = Money.from_numeric(1, Money::Currency.wrap("EUR"))
191
+ m.currency.should == Money::Currency.wrap("EUR")
192
+
193
+ m = Money.from_numeric(1, "EUR")
194
+ m.currency.should == Money::Currency.wrap("EUR")
195
+ end
196
+ end
197
+ end
data/spec/money_spec.rb CHANGED
@@ -1,292 +1,292 @@
1
- # encoding: utf-8
2
-
3
- require "spec_helper"
4
-
5
- describe Money do
6
-
7
- describe "#new" do
8
- it "rounds the given cents to an integer" do
9
- Money.new(1.00, "USD").cents.should == 1
10
- Money.new(1.01, "USD").cents.should == 1
11
- Money.new(1.50, "USD").cents.should == 2
12
- end
13
-
14
- it "is associated to the singleton instance of Bank::VariableExchange by default" do
15
- Money.new(0).bank.should be_equal(Money::Bank::VariableExchange.instance)
16
- end
17
-
18
- end
19
-
20
- describe "#cents" do
21
- it "returns the amount of cents passed to the constructor" do
22
- Money.new(200_00, "USD").cents.should == 200_00
23
- end
24
-
25
- it "stores cents as an integer regardless of what is passed into the constructor" do
26
- [ Money.new(100), 1.to_money, 1.00.to_money, BigDecimal('1.00').to_money ].each do |m|
27
- m.cents.should == 100
28
- m.cents.should be_an_instance_of(Fixnum)
29
- end
30
- end
31
- end
32
-
33
- describe "#dollars" do
34
- it "gets cents as dollars" do
35
- Money.new_with_dollars(1).should == Money.new(100)
36
- Money.new_with_dollars(1, "USD").should == Money.new(100, "USD")
37
- Money.new_with_dollars(1, "EUR").should == Money.new(100, "EUR")
38
- end
39
-
40
- it "should respect :subunit_to_unit currency property" do
41
- Money.new(1_00, "USD").dollars.should == 1
42
- Money.new(1_000, "TND").dollars.should == 1
43
- Money.new(1, "CLP").dollars.should == 1
44
- end
45
-
46
- it "should not loose precision" do
47
- Money.new(100_37).dollars.should == 100.37
48
- Money.new_with_dollars(100.37).dollars.should == 100.37
49
- end
50
- end
51
-
52
- specify "#currency returns the currency passed to the constructor" do
53
- Money.new(200_00, "USD").currency.should == Money::Currency.new("USD")
54
- end
55
-
56
- specify "#currency_string returns the iso_code of the currency object" do
57
- Money.new(200_00, "USD").currency_as_string.should == Money::Currency.new("USD").to_s
58
- Money.new(200_00, "USD").currency_as_string.should == "USD"
59
- Money.new(200_00, "EUR").currency_as_string.should == "EUR"
60
- Money.new(200_00, "YEN").currency_as_string.should == "YEN"
61
- end
62
-
63
- specify "#currency_string= set the currency object using the provided string" do
64
- obj = Money.new(200_00, "USD")
65
- obj.currency_as_string = "EUR"
66
- obj.currency.should == Money::Currency.new("EUR")
67
- obj.currency_as_string = "YEN"
68
- obj.currency.should == Money::Currency.new("YEN")
69
- obj.currency_as_string = "USD"
70
- obj.currency.should == Money::Currency.new("USD")
71
- end
72
-
73
-
74
- specify "#exchange_to exchanges the amount via its exchange bank" do
75
- money = Money.new(100_00, "USD")
76
- money.bank.should_receive(:exchange_with).with(Money.new(100_00, Money::Currency.new("USD")), Money::Currency.new("EUR")).and_return(Money.new(200_00, Money::Currency.new('EUR')))
77
- money.exchange_to("EUR")
78
- end
79
-
80
- specify "#exchange_to exchanges the amount properly" do
81
- money = Money.new(100_00, "USD")
82
- money.bank.should_receive(:exchange_with).with(Money.new(100_00, Money::Currency.new("USD")), Money::Currency.new("EUR")).and_return(Money.new(200_00, Money::Currency.new('EUR')))
83
- money.exchange_to("EUR").should == Money.new(200_00, "EUR")
84
- end
85
-
86
- specify "#hash should return the same value for equal objects" do
87
- Money.new(1_00, :eur).hash.should == Money.new(1_00, :eur).hash
88
- Money.new(2_00, :usd).hash.should == Money.new(2_00, :usd).hash
89
- Money.new(1_00, :eur).hash.should_not == Money.new(2_00, :eur).hash
90
- Money.new(1_00, :eur).hash.should_not == Money.new(1_00, :usd).hash
91
- Money.new(1_00, :eur).hash.should_not == Money.new(2_00, :usd).hash
92
- end
93
-
94
- specify "#hash can be used to return the intersection of Money object arrays" do
95
- intersection = [Money.new(1_00, :eur), Money.new(1_00, :usd)] & [Money.new(1_00, :eur)]
96
- intersection.should == [Money.new(1_00, :eur)]
97
- end
98
-
99
-
100
- specify "Money.to_s works" do
101
- Money.new(10_00).to_s.should == "10.00"
102
- Money.new(400_08).to_s.should == "400.08"
103
- Money.new(-237_43).to_s.should == "-237.43"
104
- end
105
-
106
- specify "Money.to_s should respect :subunit_to_unit currency property" do
107
- Money.new(10_00, "BHD").to_s.should == "1.000"
108
- Money.new(10_00, "CNY").to_s.should == "10.00"
109
- end
110
-
111
- specify "Money.to_s shouldn't have decimal when :subunit_to_unit is 1" do
112
- Money.new(10_00, "CLP").to_s.should == "1000"
113
- end
114
-
115
- specify "Money.to_s should work with :subunit_to_unit == 5" do
116
- Money.new(10_00, "MGA").to_s.should == "200.0"
117
- end
118
-
119
- specify "Money.to_s should respect :decimal_mark" do
120
- Money.new(10_00, "BRL").to_s.should == "10,00"
121
- end
122
-
123
- specify "Money.to_d works" do
124
- decimal = Money.new(10_00).to_d
125
- decimal.should be_instance_of(BigDecimal)
126
- decimal.should == 10.0
127
- end
128
-
129
- specify "Money.to_d should respect :subunit_to_unit currency property" do
130
- decimal = Money.new(10_00, "BHD").to_d
131
- decimal.should be_instance_of(BigDecimal)
132
- decimal.should == 1.0
133
- end
134
-
135
- specify "Money.to_d should work with float :subunit_to_unit currency property" do
136
- money = Money.new(10_00, "BHD")
137
- money.currency.stub(:subunit_to_unit).and_return(1000.0)
138
-
139
- decimal = money.to_d
140
- decimal.should be_instance_of(BigDecimal)
141
- decimal.should == 1.0
142
- end
143
-
144
- specify "Money.to_f works" do
145
- Money.new(10_00).to_f.should == 10.0
146
- end
147
-
148
- specify "Money.to_f should respect :subunit_to_unit currency property" do
149
- Money.new(10_00, "BHD").to_f.should == 1.0
150
- end
151
-
152
- specify "#symbol works as documented" do
153
- currency = Money::Currency.new("EUR")
154
- currency.should_receive(:symbol).and_return("€")
155
- Money.empty(currency).symbol.should == "€"
156
-
157
- currency = Money::Currency.new("EUR")
158
- currency.should_receive(:symbol).and_return(nil)
159
- Money.empty(currency).symbol.should == "¤"
160
- end
161
-
162
- describe "Money.empty" do
163
- it "Money.empty creates a new Money object of 0 cents" do
164
- Money.empty.should == Money.new(0)
165
- end
166
- end
167
-
168
- describe "Money.ca_dollar" do
169
- it "creates a new Money object of the given value in CAD" do
170
- Money.ca_dollar(50).should == Money.new(50, "CAD")
171
- end
172
- end
173
-
174
- describe "Money.us_dollar" do
175
- it "creates a new Money object of the given value in USD" do
176
- Money.us_dollar(50).should == Money.new(50, "USD")
177
- end
178
- end
179
-
180
- describe "Money.euro" do
181
- it "creates a new Money object of the given value in EUR" do
182
- Money.euro(50).should == Money.new(50, "EUR")
183
- end
184
- end
185
-
186
-
187
- describe "Money.new_with_dollars" do
188
- it "converts given amount to cents" do
189
- Money.new_with_dollars(1).should == Money.new(100)
190
- Money.new_with_dollars(1, "USD").should == Money.new(100, "USD")
191
- Money.new_with_dollars(1, "EUR").should == Money.new(100, "EUR")
192
- end
193
-
194
- it "should respect :subunit_to_unit currency property" do
195
- Money.new_with_dollars(1, "USD").should == Money.new(1_00, "USD")
196
- Money.new_with_dollars(1, "TND").should == Money.new(1_000, "TND")
197
- Money.new_with_dollars(1, "CLP").should == Money.new(1, "CLP")
198
- end
199
-
200
- it "should not loose precision" do
201
- Money.new_with_dollars(1234).cents.should == 1234_00
202
- Money.new_with_dollars(100.37).cents.should == 100_37
203
- Money.new_with_dollars(BigDecimal.new('1234')).cents.should == 1234_00
204
- end
205
-
206
- it "accepts a currency options" do
207
- m = Money.new_with_dollars(1)
208
- m.currency.should == Money.default_currency
209
-
210
- m = Money.new_with_dollars(1, Money::Currency.wrap("EUR"))
211
- m.currency.should == Money::Currency.wrap("EUR")
212
-
213
- m = Money.new_with_dollars(1, "EUR")
214
- m.currency.should == Money::Currency.wrap("EUR")
215
- end
216
-
217
- it "accepts a bank options" do
218
- m = Money.new_with_dollars(1)
219
- m.bank.should == Money.default_bank
220
-
221
- m = Money.new_with_dollars(1, "EUR", bank = Object.new)
222
- m.bank.should == bank
223
- end
224
-
225
- it "is associated to the singleton instance of Bank::VariableExchange by default" do
226
- Money.new_with_dollars(0).bank.should be_equal(Money::Bank::VariableExchange.instance)
227
- end
228
- end
229
-
230
- describe "split" do
231
- specify "#split needs at least one party" do
232
- lambda {Money.us_dollar(1).split(0)}.should raise_error(ArgumentError)
233
- lambda {Money.us_dollar(1).split(-1)}.should raise_error(ArgumentError)
234
- end
235
-
236
-
237
- specify "#gives 1 cent to both people if we start with 2" do
238
- Money.us_dollar(2).split(2).should == [Money.us_dollar(1), Money.us_dollar(1)]
239
- end
240
-
241
- specify "#split may distribute no money to some parties if there isnt enough to go around" do
242
- Money.us_dollar(2).split(3).should == [Money.us_dollar(1), Money.us_dollar(1), Money.us_dollar(0)]
243
- end
244
-
245
- specify "#split does not lose pennies" do
246
- Money.us_dollar(5).split(2).should == [Money.us_dollar(3), Money.us_dollar(2)]
247
- end
248
-
249
- specify "#split a dollar" do
250
- moneys = Money.us_dollar(100).split(3)
251
- moneys[0].cents.should == 34
252
- moneys[1].cents.should == 33
253
- moneys[2].cents.should == 33
254
- end
255
- end
256
-
257
- describe "allocation" do
258
- specify "#allocate takes no action when one gets all" do
259
- Money.us_dollar(005).allocate([1.0]).should == [Money.us_dollar(5)]
260
- end
261
-
262
- specify "#allocate keeps currencies intact" do
263
- Money.ca_dollar(005).allocate([1]).should == [Money.ca_dollar(5)]
264
- end
265
-
266
- specify "#allocate does not loose pennies" do
267
- moneys = Money.us_dollar(5).allocate([0.3,0.7])
268
- moneys[0].should == Money.us_dollar(2)
269
- moneys[1].should == Money.us_dollar(3)
270
- end
271
-
272
- specify "#allocate does not loose pennies" do
273
- moneys = Money.us_dollar(100).allocate([0.333,0.333, 0.333])
274
- moneys[0].cents.should == 34
275
- moneys[1].cents.should == 33
276
- moneys[2].cents.should == 33
277
- end
278
-
279
- specify "#allocate requires total to be less then 1" do
280
- lambda { Money.us_dollar(0.05).allocate([0.5,0.6]) }.should raise_error(ArgumentError)
281
- end
282
- end
283
-
284
- describe "Money.add_rate" do
285
- it "saves rate into current bank" do
286
- Money.add_rate("EUR", "USD", 10)
287
- Money.new(10_00, "EUR").exchange_to("USD").should == Money.new(100_00, "USD")
288
- end
289
- end
290
-
291
- end
292
-
1
+ # encoding: utf-8
2
+
3
+ require "spec_helper"
4
+
5
+ describe Money do
6
+
7
+ describe "#new" do
8
+ it "rounds the given cents to an integer" do
9
+ Money.new(1.00, "USD").cents.should == 1
10
+ Money.new(1.01, "USD").cents.should == 1
11
+ Money.new(1.50, "USD").cents.should == 2
12
+ end
13
+
14
+ it "is associated to the singleton instance of Bank::VariableExchange by default" do
15
+ Money.new(0).bank.should be_equal(Money::Bank::VariableExchange.instance)
16
+ end
17
+
18
+ end
19
+
20
+ describe "#cents" do
21
+ it "returns the amount of cents passed to the constructor" do
22
+ Money.new(200_00, "USD").cents.should == 200_00
23
+ end
24
+
25
+ it "stores cents as an integer regardless of what is passed into the constructor" do
26
+ [ Money.new(100), 1.to_money, 1.00.to_money, BigDecimal('1.00').to_money ].each do |m|
27
+ m.cents.should == 100
28
+ m.cents.should be_an_instance_of(Fixnum)
29
+ end
30
+ end
31
+ end
32
+
33
+ describe "#dollars" do
34
+ it "gets cents as dollars" do
35
+ Money.new_with_dollars(1).should == Money.new(100)
36
+ Money.new_with_dollars(1, "USD").should == Money.new(100, "USD")
37
+ Money.new_with_dollars(1, "EUR").should == Money.new(100, "EUR")
38
+ end
39
+
40
+ it "should respect :subunit_to_unit currency property" do
41
+ Money.new(1_00, "USD").dollars.should == 1
42
+ Money.new(1_000, "TND").dollars.should == 1
43
+ Money.new(1, "CLP").dollars.should == 1
44
+ end
45
+
46
+ it "should not loose precision" do
47
+ Money.new(100_37).dollars.should == 100.37
48
+ Money.new_with_dollars(100.37).dollars.should == 100.37
49
+ end
50
+ end
51
+
52
+ specify "#currency returns the currency passed to the constructor" do
53
+ Money.new(200_00, "USD").currency.should == Money::Currency.new("USD")
54
+ end
55
+
56
+ specify "#currency_string returns the iso_code of the currency object" do
57
+ Money.new(200_00, "USD").currency_as_string.should == Money::Currency.new("USD").to_s
58
+ Money.new(200_00, "USD").currency_as_string.should == "USD"
59
+ Money.new(200_00, "EUR").currency_as_string.should == "EUR"
60
+ Money.new(200_00, "YEN").currency_as_string.should == "YEN"
61
+ end
62
+
63
+ specify "#currency_string= set the currency object using the provided string" do
64
+ obj = Money.new(200_00, "USD")
65
+ obj.currency_as_string = "EUR"
66
+ obj.currency.should == Money::Currency.new("EUR")
67
+ obj.currency_as_string = "YEN"
68
+ obj.currency.should == Money::Currency.new("YEN")
69
+ obj.currency_as_string = "USD"
70
+ obj.currency.should == Money::Currency.new("USD")
71
+ end
72
+
73
+
74
+ specify "#exchange_to exchanges the amount via its exchange bank" do
75
+ money = Money.new(100_00, "USD")
76
+ money.bank.should_receive(:exchange_with).with(Money.new(100_00, Money::Currency.new("USD")), Money::Currency.new("EUR")).and_return(Money.new(200_00, Money::Currency.new('EUR')))
77
+ money.exchange_to("EUR")
78
+ end
79
+
80
+ specify "#exchange_to exchanges the amount properly" do
81
+ money = Money.new(100_00, "USD")
82
+ money.bank.should_receive(:exchange_with).with(Money.new(100_00, Money::Currency.new("USD")), Money::Currency.new("EUR")).and_return(Money.new(200_00, Money::Currency.new('EUR')))
83
+ money.exchange_to("EUR").should == Money.new(200_00, "EUR")
84
+ end
85
+
86
+ specify "#hash should return the same value for equal objects" do
87
+ Money.new(1_00, :eur).hash.should == Money.new(1_00, :eur).hash
88
+ Money.new(2_00, :usd).hash.should == Money.new(2_00, :usd).hash
89
+ Money.new(1_00, :eur).hash.should_not == Money.new(2_00, :eur).hash
90
+ Money.new(1_00, :eur).hash.should_not == Money.new(1_00, :usd).hash
91
+ Money.new(1_00, :eur).hash.should_not == Money.new(2_00, :usd).hash
92
+ end
93
+
94
+ specify "#hash can be used to return the intersection of Money object arrays" do
95
+ intersection = [Money.new(1_00, :eur), Money.new(1_00, :usd)] & [Money.new(1_00, :eur)]
96
+ intersection.should == [Money.new(1_00, :eur)]
97
+ end
98
+
99
+
100
+ specify "Money.to_s works" do
101
+ Money.new(10_00).to_s.should == "10.00"
102
+ Money.new(400_08).to_s.should == "400.08"
103
+ Money.new(-237_43).to_s.should == "-237.43"
104
+ end
105
+
106
+ specify "Money.to_s should respect :subunit_to_unit currency property" do
107
+ Money.new(10_00, "BHD").to_s.should == "1.000"
108
+ Money.new(10_00, "CNY").to_s.should == "10.00"
109
+ end
110
+
111
+ specify "Money.to_s shouldn't have decimal when :subunit_to_unit is 1" do
112
+ Money.new(10_00, "CLP").to_s.should == "1000"
113
+ end
114
+
115
+ specify "Money.to_s should work with :subunit_to_unit == 5" do
116
+ Money.new(10_00, "MGA").to_s.should == "200.0"
117
+ end
118
+
119
+ specify "Money.to_s should respect :decimal_mark" do
120
+ Money.new(10_00, "BRL").to_s.should == "10,00"
121
+ end
122
+
123
+ specify "Money.to_d works" do
124
+ decimal = Money.new(10_00).to_d
125
+ decimal.should be_instance_of(BigDecimal)
126
+ decimal.should == 10.0
127
+ end
128
+
129
+ specify "Money.to_d should respect :subunit_to_unit currency property" do
130
+ decimal = Money.new(10_00, "BHD").to_d
131
+ decimal.should be_instance_of(BigDecimal)
132
+ decimal.should == 1.0
133
+ end
134
+
135
+ specify "Money.to_d should work with float :subunit_to_unit currency property" do
136
+ money = Money.new(10_00, "BHD")
137
+ money.currency.stub(:subunit_to_unit).and_return(1000.0)
138
+
139
+ decimal = money.to_d
140
+ decimal.should be_instance_of(BigDecimal)
141
+ decimal.should == 1.0
142
+ end
143
+
144
+ specify "Money.to_f works" do
145
+ Money.new(10_00).to_f.should == 10.0
146
+ end
147
+
148
+ specify "Money.to_f should respect :subunit_to_unit currency property" do
149
+ Money.new(10_00, "BHD").to_f.should == 1.0
150
+ end
151
+
152
+ specify "#symbol works as documented" do
153
+ currency = Money::Currency.new("EUR")
154
+ currency.should_receive(:symbol).and_return("€")
155
+ Money.empty(currency).symbol.should == "€"
156
+
157
+ currency = Money::Currency.new("EUR")
158
+ currency.should_receive(:symbol).and_return(nil)
159
+ Money.empty(currency).symbol.should == "¤"
160
+ end
161
+
162
+ describe "Money.empty" do
163
+ it "Money.empty creates a new Money object of 0 cents" do
164
+ Money.empty.should == Money.new(0)
165
+ end
166
+ end
167
+
168
+ describe "Money.ca_dollar" do
169
+ it "creates a new Money object of the given value in CAD" do
170
+ Money.ca_dollar(50).should == Money.new(50, "CAD")
171
+ end
172
+ end
173
+
174
+ describe "Money.us_dollar" do
175
+ it "creates a new Money object of the given value in USD" do
176
+ Money.us_dollar(50).should == Money.new(50, "USD")
177
+ end
178
+ end
179
+
180
+ describe "Money.euro" do
181
+ it "creates a new Money object of the given value in EUR" do
182
+ Money.euro(50).should == Money.new(50, "EUR")
183
+ end
184
+ end
185
+
186
+
187
+ describe "Money.new_with_dollars" do
188
+ it "converts given amount to cents" do
189
+ Money.new_with_dollars(1).should == Money.new(100)
190
+ Money.new_with_dollars(1, "USD").should == Money.new(100, "USD")
191
+ Money.new_with_dollars(1, "EUR").should == Money.new(100, "EUR")
192
+ end
193
+
194
+ it "should respect :subunit_to_unit currency property" do
195
+ Money.new_with_dollars(1, "USD").should == Money.new(1_00, "USD")
196
+ Money.new_with_dollars(1, "TND").should == Money.new(1_000, "TND")
197
+ Money.new_with_dollars(1, "CLP").should == Money.new(1, "CLP")
198
+ end
199
+
200
+ it "should not loose precision" do
201
+ Money.new_with_dollars(1234).cents.should == 1234_00
202
+ Money.new_with_dollars(100.37).cents.should == 100_37
203
+ Money.new_with_dollars(BigDecimal.new('1234')).cents.should == 1234_00
204
+ end
205
+
206
+ it "accepts a currency options" do
207
+ m = Money.new_with_dollars(1)
208
+ m.currency.should == Money.default_currency
209
+
210
+ m = Money.new_with_dollars(1, Money::Currency.wrap("EUR"))
211
+ m.currency.should == Money::Currency.wrap("EUR")
212
+
213
+ m = Money.new_with_dollars(1, "EUR")
214
+ m.currency.should == Money::Currency.wrap("EUR")
215
+ end
216
+
217
+ it "accepts a bank options" do
218
+ m = Money.new_with_dollars(1)
219
+ m.bank.should == Money.default_bank
220
+
221
+ m = Money.new_with_dollars(1, "EUR", bank = Object.new)
222
+ m.bank.should == bank
223
+ end
224
+
225
+ it "is associated to the singleton instance of Bank::VariableExchange by default" do
226
+ Money.new_with_dollars(0).bank.should be_equal(Money::Bank::VariableExchange.instance)
227
+ end
228
+ end
229
+
230
+ describe "split" do
231
+ specify "#split needs at least one party" do
232
+ lambda {Money.us_dollar(1).split(0)}.should raise_error(ArgumentError)
233
+ lambda {Money.us_dollar(1).split(-1)}.should raise_error(ArgumentError)
234
+ end
235
+
236
+
237
+ specify "#gives 1 cent to both people if we start with 2" do
238
+ Money.us_dollar(2).split(2).should == [Money.us_dollar(1), Money.us_dollar(1)]
239
+ end
240
+
241
+ specify "#split may distribute no money to some parties if there isnt enough to go around" do
242
+ Money.us_dollar(2).split(3).should == [Money.us_dollar(1), Money.us_dollar(1), Money.us_dollar(0)]
243
+ end
244
+
245
+ specify "#split does not lose pennies" do
246
+ Money.us_dollar(5).split(2).should == [Money.us_dollar(3), Money.us_dollar(2)]
247
+ end
248
+
249
+ specify "#split a dollar" do
250
+ moneys = Money.us_dollar(100).split(3)
251
+ moneys[0].cents.should == 34
252
+ moneys[1].cents.should == 33
253
+ moneys[2].cents.should == 33
254
+ end
255
+ end
256
+
257
+ describe "allocation" do
258
+ specify "#allocate takes no action when one gets all" do
259
+ Money.us_dollar(005).allocate([1.0]).should == [Money.us_dollar(5)]
260
+ end
261
+
262
+ specify "#allocate keeps currencies intact" do
263
+ Money.ca_dollar(005).allocate([1]).should == [Money.ca_dollar(5)]
264
+ end
265
+
266
+ specify "#allocate does not loose pennies" do
267
+ moneys = Money.us_dollar(5).allocate([0.3,0.7])
268
+ moneys[0].should == Money.us_dollar(2)
269
+ moneys[1].should == Money.us_dollar(3)
270
+ end
271
+
272
+ specify "#allocate does not loose pennies" do
273
+ moneys = Money.us_dollar(100).allocate([0.333,0.333, 0.333])
274
+ moneys[0].cents.should == 34
275
+ moneys[1].cents.should == 33
276
+ moneys[2].cents.should == 33
277
+ end
278
+
279
+ specify "#allocate requires total to be less then 1" do
280
+ lambda { Money.us_dollar(0.05).allocate([0.5,0.6]) }.should raise_error(ArgumentError)
281
+ end
282
+ end
283
+
284
+ describe "Money.add_rate" do
285
+ it "saves rate into current bank" do
286
+ Money.add_rate("EUR", "USD", 10)
287
+ Money.new(10_00, "EUR").exchange_to("USD").should == Money.new(100_00, "USD")
288
+ end
289
+ end
290
+
291
+ end
292
+