money 3.0.4 → 3.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,16 @@
1
+ == Money 3.0.5
2
+ * Added Money#abs
3
+ * Updated Currency#subunit_to_unit documentation (it's an integer not a
4
+ string)
5
+ * Fixed issue when exchanging currencies with different :subunit_to_unit
6
+ values
7
+ * Added ability to pass a block to VariableExchangeBank#new or #exchange,
8
+ specifying a custom truncation method
9
+ * Added optional currency argument to Numeric#to_money
10
+ * Added optional currency argument to String#to_money
11
+ * Numeric#to_money now respects :subunit_to_unit
12
+ * Use '¤' as the default currency symbol
13
+
1
14
  == Money 3.0.4
2
15
  * Updated #exchange to avoid floating point rounding errors
3
16
  * Use :subunit_to_unit in #to_s, #to_f and #format
@@ -19,6 +19,15 @@ Resources:
19
19
  - RDoc API: http://money.rubyforge.org
20
20
  - Git repository: http://github.com/FooBarWidget/money
21
21
 
22
+ == Attention
23
+
24
+ Starting in v3.1.0 we will be making two changes to the exchange process. First
25
+ a new `Bank::Base` class will be available. This will allow users to more
26
+ easily create custom `Bank` classes. Secondly the default `#exchange` method
27
+ will be depreciated and a new `#exchange_with` method will be used. Currently
28
+ `#exchange` passes the `cents` attribute. `#exchange_with` will pass the
29
+ actual `Money` object instead.
30
+
22
31
  == Download
23
32
 
24
33
  Install stable releases with the following command:
@@ -73,9 +82,9 @@ containing all the currency attributes.
73
82
  :name => "United States Dollar",
74
83
  :symbol => "$",
75
84
  :subunit => "Cent"
76
- :subunit_to_unit => "100",
85
+ :subunit_to_unit => 100,
77
86
  :separator => ".",
78
- :delimiter =? ","
87
+ :delimiter => ","
79
88
  }
80
89
 
81
90
  The pre-defined set of attributes includes:
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.0.4
1
+ 3.0.5
@@ -6,8 +6,9 @@ class Numeric
6
6
  # 100.37.to_money => #<Money @cents=10037>
7
7
  # require 'bigdecimal'
8
8
  # BigDecimal.new('100').to_money => #<Money @cents=10000>
9
- def to_money
10
- Money.new((self * 100).to_int)
9
+ def to_money(currency = Money.default_currency)
10
+ currency = Money::Currency.new(currency) unless currency.is_a?(Money::Currency)
11
+ Money.new((self * currency.subunit_to_unit).to_int, currency)
11
12
  end
12
13
  end
13
14
 
@@ -22,10 +23,23 @@ class String
22
23
  # 'USD 100'.to_money # => #<Money @cents=10000, @currency="USD">
23
24
  # '$100 USD'.to_money # => #<Money @cents=10000, @currency="USD">
24
25
  # 'hello 2000 world'.to_money # => #<Money @cents=200000 @currency="USD")>
25
- def to_money
26
+ def to_money(currency = nil)
26
27
  # Get the currency.
27
28
  matches = scan /([A-Z]{2,3})/
28
- currency = matches[0] ? matches[0][0] : Money.default_currency
29
+ _currency_ = matches[0] ? matches[0][0] : nil
30
+
31
+ # check that currency passed and embedded currency are the same, or only
32
+ # one or the other is present.
33
+ if currency.nil? and _currency_.nil?
34
+ currency = Money.default_currency
35
+ elsif currency.nil?
36
+ currency = _currency_
37
+ elsif _currency_.nil?
38
+ currency = currency
39
+ elsif currency != _currency_
40
+ raise "mismatching currencies"
41
+ end
42
+
29
43
  cents = calculate_cents(self)
30
44
  Money.new(cents, currency)
31
45
  end
@@ -41,7 +41,7 @@ class Money
41
41
  "SEK" => "kr",
42
42
  "GHC" => "¢",
43
43
  "BRL" => "R$ ",
44
- # Everything else defaults to '$'
44
+ # Everything else defaults to '¤'
45
45
  }, "Money::SYMBOLS has no longer effect. See Money::Currency#symbol.")
46
46
 
47
47
  SEPARATORS = DeprecatedHash.new({
@@ -218,6 +218,11 @@ class Money
218
218
  a.modulo(b) - (b.is_a?(Money) ? b : Money.new(b, a.currency))
219
219
  end
220
220
 
221
+ # Return absolute value of self as a new Money object
222
+ def abs
223
+ Money.new(self.cents.abs, self.currency)
224
+ end
225
+
221
226
  # Test if the money amount is zero
222
227
  def zero?
223
228
  cents == 0
@@ -232,9 +237,9 @@ class Money
232
237
  # Attempts to pick a symbol that's suitable for the given currency
233
238
  # looking up the Currency::TABLE hashtable.
234
239
  # If the symbol for the given currency isn't known,
235
- # then it will default to "$".
240
+ # then it will default to "¤".
236
241
  def symbol
237
- currency.symbol || "$"
242
+ currency.symbol || "¤"
238
243
  end
239
244
 
240
245
  # Uses :delimiter from the Currency hash. If it is not specified defaults to
@@ -303,9 +308,9 @@ class Money
303
308
  #
304
309
  #
305
310
  # If the symbol for the given currency isn't known, then it will default
306
- # to "$" as symbol:
311
+ # to "¤" as symbol:
307
312
  #
308
- # Money.new(100, "AWG").format(:symbol => true) => "$1.00"
313
+ # Money.new(100, "AWG").format(:symbol => true) => "¤1.00"
309
314
  #
310
315
  # You can specify a string as value to enforce using a particular symbol:
311
316
  #
@@ -27,9 +27,10 @@ class Money
27
27
  @@singleton
28
28
  end
29
29
 
30
- def initialize
30
+ def initialize(&block)
31
31
  @rates = {}
32
32
  @mutex = Mutex.new
33
+ @rounding_method = block
33
34
  end
34
35
 
35
36
  # Registers a conversion rate. +from+ and +to+ are both currency names.
@@ -60,12 +61,20 @@ class Money
60
61
  # Returns the amount of cents in +to_currency+ as an integer, rounded down.
61
62
  #
62
63
  # If the conversion rate is unknown, then Money::UnknownRate will be raised.
63
- def exchange(cents, from_currency, to_currency)
64
+ def exchange(cents, from_currency, to_currency, &block)
64
65
  rate = get_rate(from_currency, to_currency)
65
66
  if !rate
66
67
  raise Money::UnknownRate, "No conversion rate known for '#{from_currency}' -> '#{to_currency}'"
67
68
  end
68
- (cents * rate).to_s.to_i
69
+ _from_currency_ = Currency.wrap(from_currency)
70
+ _to_currency_ = Currency.wrap(to_currency)
71
+
72
+ _cents_ = cents / (_from_currency_.subunit_to_unit.to_f / _to_currency_.subunit_to_unit.to_f)
73
+
74
+ ex = _cents_ * rate
75
+ return block.call(ex) if block_given?
76
+ return @rounding_method.call(ex) unless @rounding_method.nil?
77
+ ex.to_s.to_i
69
78
  end
70
79
 
71
80
  @@singleton = VariableExchangeBank.new
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{money}
8
- s.version = "3.0.4"
8
+ s.version = "3.0.5"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Tobias Luetke", "Hongli Lai", "Jeremy McNevin", "Shane Emmons"]
12
- s.date = %q{2010-06-24}
12
+ s.date = %q{2010-07-16}
13
13
  s.description = %q{Money and currency exchange support library.}
14
14
  s.email = %q{hongli@phusion.nl}
15
15
  s.extra_rdoc_files = [
@@ -17,6 +17,17 @@ describe "Money core extensions" do
17
17
  money.cents.should == 1234_00
18
18
  money.currency.should == Money.default_currency
19
19
  end
20
+
21
+ specify "Numeric#to_money accepts optional currency" do
22
+ 1234.to_money('USD').should == Money.new(123400, 'USD')
23
+ 1234.to_money('EUR').should == Money.new(123400, 'EUR')
24
+ end
25
+
26
+ specify "Numeric#to_money should respect :subunit_to_unit" do
27
+ 10.to_money('USD').should == Money.new(10_00, 'USD')
28
+ 10.to_money('TND').should == Money.new(10_000, 'TND')
29
+ 10.to_money('CLP').should == Money.new(10, 'CLP')
30
+ end
20
31
 
21
32
  specify "String#to_money works" do
22
33
  "20.15".to_money.should == Money.new(20_15)
@@ -73,6 +84,13 @@ describe "Money core extensions" do
73
84
  "$1.99000 USD".to_money.should == Money.new(1_99, "USD")
74
85
  end
75
86
 
87
+ specify "String#to_money should accept optional currency" do
88
+ "10.10".to_money('USD').should == Money.new(1010, 'USD')
89
+ "10.10".to_money('EUR').should == Money.new(1010, 'EUR')
90
+ "10.10 USD".to_money('USD').should == Money.new(1010, 'USD')
91
+ lambda{"10.10 USD".to_money('EUR')}.should raise_error
92
+ end
93
+
76
94
  specify "String#to_money ignores unrecognized data" do
77
95
  "hello 2000 world".to_money.should == Money.new(2000_00)
78
96
  end
@@ -57,5 +57,45 @@ describe Money::VariableExchangeBank do
57
57
  @bank.exchange(10000, 'USD', 'EUR').should == 8600
58
58
  end
59
59
  end
60
+
61
+ context 'TND to USD using a rate of 0.67138' do
62
+ it 'returns the correct amount' do
63
+ @bank.add_rate('TND', 'USD', 0.67138)
64
+ @bank.exchange(1000, 'TND', 'USD').should == 67
65
+ end
66
+ end
67
+
68
+ context 'USD to TND using a rate of 1.32862' do
69
+ it 'returns the correct amount' do
70
+ @bank.add_rate('USD', 'TND', 1.32862)
71
+ @bank.exchange(1000, 'USD', 'TND').should == 13286
72
+ end
73
+ end
74
+ end
75
+
76
+ context 'using custom rounding methods' do
77
+ describe 'passing a rounding method to #new' do
78
+ before :each do
79
+ mth = Proc.new{|ex| ex.ceil }
80
+ @bank = Money::VariableExchangeBank.new(&mth)
81
+ end
82
+
83
+ it 'should use @rounding_method' do
84
+ @bank.add_rate('USD', 'EUR', 0.86)
85
+ @bank.exchange(10, 'USD', 'EUR').should == 9
86
+ end
87
+ end
88
+
89
+ describe 'passing a rounding method to #exchange' do
90
+ it 'should use &block' do
91
+ @bank.add_rate('USD', 'EUR', 0.86)
92
+ @bank.exchange(10, 'USD', 'EUR').should == 8
93
+
94
+ mth = Proc.new{|ex| ex.ceil }
95
+ @bank.exchange(10, 'USD', 'EUR', &mth).should == 9
96
+
97
+ @bank.exchange(10, 'USD', 'EUR'){|ex| ex.ceil }.should == 9
98
+ end
99
+ end
60
100
  end
61
101
  end
@@ -430,6 +430,12 @@ describe Money do
430
430
  end
431
431
  end
432
432
 
433
+ specify "#abs correctly returns the absolute value as a new Money object" do
434
+ n = Money.new(-1, :USD)
435
+ n.abs.should == Money.new( 1, :USD)
436
+ n.should == Money.new(-1, :USD)
437
+ end
438
+
433
439
  specify "Money.empty creates a new Money object of 0 cents" do
434
440
  Money.empty.should == Money.new(0)
435
441
  end
@@ -556,7 +562,7 @@ describe Money do
556
562
 
557
563
  currency = Money::Currency.new("EUR")
558
564
  currency.should_receive(:symbol).and_return(nil)
559
- Money.empty(currency).symbol.should == "$"
565
+ Money.empty(currency).symbol.should == "¤"
560
566
  end
561
567
 
562
568
  specify "#delimiter works as documented" do
@@ -647,7 +653,7 @@ describe Money do
647
653
  specify "#format(:symbol => true) returns $ when currency code is not recognized" do
648
654
  currency = Money::Currency.new("EUR")
649
655
  currency.should_receive(:symbol).and_return(nil)
650
- Money.new(100, currency).format(:symbol => true).should == "$1.00"
656
+ Money.new(100, currency).format(:symbol => true).should == "¤1.00"
651
657
  end
652
658
 
653
659
  specify "#format(:symbol => some non-Boolean value that evaluates to true) returs symbol based on the given currency code" do
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: money
3
3
  version: !ruby/object:Gem::Version
4
- hash: 15
4
+ hash: 13
5
5
  prerelease: false
6
6
  segments:
7
7
  - 3
8
8
  - 0
9
- - 4
10
- version: 3.0.4
9
+ - 5
10
+ version: 3.0.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Tobias Luetke
@@ -18,7 +18,7 @@ autorequire:
18
18
  bindir: bin
19
19
  cert_chain: []
20
20
 
21
- date: 2010-06-24 00:00:00 -04:00
21
+ date: 2010-07-16 00:00:00 -04:00
22
22
  default_executable:
23
23
  dependencies:
24
24
  - !ruby/object:Gem::Dependency