money 6.1.1 → 6.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 480b95f8096f52348bd524f899d7401a2668a05c
4
- data.tar.gz: 632d434f8c8e2e3f849f8f45d512d627c0c06e05
3
+ metadata.gz: bf365d84238e2c9219749009e8564d3fa7de6a9c
4
+ data.tar.gz: 38d09517c0104b59a32035a1f22c33a78e3f106c
5
5
  SHA512:
6
- metadata.gz: 6e1e62395c88cbeb0e369ea99499eef99f1fe7bfbc99d1e38d95c998298a2f64dfa197e965050b02abc3d6301bad8cdde601ba291220b4884ff6d46462daa799
7
- data.tar.gz: 05dc6ca4711769270130edd4ec05b5a67c4a6023e6db6d12b3a41db65fd26af147553c37ae6f66ec342eaf27f169ef4359e9867862f88b3c0765bd9d419c34b1
6
+ metadata.gz: b7564da6464a9ff9e054bc552ff1de1e8394b0313de0e937363b66c53aa5efbedc3082439e44f5c8b4d3b23a5ab652dcc42c437544a23372a26b24e3671f44dd
7
+ data.tar.gz: 89edeaf1d8e4f7237c598ba6fba0ddeb69ca79a09e6b9b73e8812db15d2b71cde25f206749954982314712deda29ce297d0cc289416a86e426d07020382d72ee
data/.travis.yml CHANGED
@@ -2,7 +2,8 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
- - 2.1.0
5
+ - 2.1.2
6
+ - rbx-2
6
7
  script: bundle exec rspec spec
7
8
  notifications:
8
9
  recipients:
data/AUTHORS CHANGED
@@ -16,6 +16,7 @@ Bodaniel Jeanes
16
16
  Brian Jones
17
17
  bUg.
18
18
  Casper Thomsen
19
+ Chad Boyd
19
20
  Choongmin Lee
20
21
  Chris Kampmeier
21
22
  Christian Billen
@@ -59,6 +60,7 @@ Mateusz Wolsza
59
60
  Matias Korhonen
60
61
  Matt Jankowski
61
62
  Matthew McEachen
63
+ Michael J. Cohen
62
64
  Michael Irwin
63
65
  Michael Reinsch
64
66
  Mikael Wikman
@@ -69,9 +71,11 @@ Nihad Abbasov
69
71
  Olek Janiszewski
70
72
  Orien Madgwick
71
73
  Paul McMahon
74
+ Paulo Diniz
72
75
  Pavel Gabriel
73
76
  Pavan Sudarshan
74
77
  pconnor
78
+ Pedro Nascimento
75
79
  Pelle Braendgaard
76
80
  Phil Cohen
77
81
  pivotal-cloudplanner
@@ -88,6 +92,7 @@ Spencer Rinehart
88
92
  Steve Morris
89
93
  Thomas E Enebo
90
94
  Ticean Bennett
95
+ Tim Hart
91
96
  Tobias Luetke
92
97
  Tobias Schmidt
93
98
  Tom Lianza
@@ -100,3 +105,4 @@ Yuusuke Takizawa
100
105
  Tien Nguyen
101
106
  Wei Zhu
102
107
  Zubin Henner
108
+ Troels Knak-Nielsen
data/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## Next release
4
+ - Fixes formatting error when both `thousands_separator` and `decimal_mark` was added to Money#format as options.
5
+ - Add Money#to_i which returns the whole part of the value. i.e.
6
+ Money.new(100, "USD").to_i # => 1
7
+ - Fix output on Ukrainian Hryvnia symbol in HTML.
8
+ - Add documentation about i18n in README.
9
+ - Update iso code, symbol, subunit for the new Turkmenistani manat (GH-181)
10
+ - Performance Improvements (1.99x faster on MRI, 1.85x on Rubinius, 41.4x faster on JRuby)
11
+ - Money can now add and subtract Fixnum 0
12
+ - Money#new uses Money.default_currency if currency arg is nil (GH-410)
13
+ - Fixed formatting of NOK, putting the symbol after numbers
14
+ - Fixed issue where rounded_infinite_precision formatting fails for some localized currencies (GH-422)
15
+
16
+ ## 6.1.1
17
+ - Remove lingering Monetize call
18
+
3
19
  ## 6.1.0
4
20
  - Remove deprecated methods.
5
21
  - Fix issue with block form of rounding_mode.
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![Build Status](https://travis-ci.org/RubyMoney/money.png?branch=master)](https://travis-ci.org/RubyMoney/money)
5
5
  [![Code Climate](https://codeclimate.com/github/RubyMoney/money.png)](https://codeclimate.com/github/RubyMoney/money)
6
6
  [![Coverage Status](https://coveralls.io/repos/RubyMoney/money/badge.png?branch=master)](https://coveralls.io/r/RubyMoney/money?branch=master)
7
- [![Inline docs](http://inch-pages.github.io/github/RubyMoney/money.png)](http://inch-pages.github.io/github/RubyMoney/money)
7
+ [![Inline docs](http://inch-ci.org/github/RubyMoney/money.png)](http://inch-ci.org/github/RubyMoney/money)
8
8
  [![Dependency Status](https://gemnasium.com/RubyMoney/money.png)](https://gemnasium.com/RubyMoney/money)
9
9
  [![License](http://img.shields.io/license/MIT.png?color=green)](http://opensource.org/licenses/MIT)
10
10
 
@@ -266,6 +266,35 @@ To integrate money in a Rails application use [money-rails](http://github.com/Ru
266
266
 
267
267
  For deprecated methods of integrating with Rails, check [the wiki](https://github.com/RubyMoney/money/wiki).
268
268
 
269
+ ## I18n
270
+
271
+ If you want thousands seperator and decimal mark to be same across all
272
+ currencies this can be defined in your `I18n` translation files.
273
+
274
+ In an rails application this may look like:
275
+ ```yml
276
+ # config/locale/en.yml
277
+ en:
278
+ number:
279
+ format:
280
+ delimeter: ","
281
+ separator: "."
282
+ # or
283
+ number:
284
+ currency:
285
+ format:
286
+ delimeter: ","
287
+ separator: "."
288
+ ```
289
+
290
+ For this example `Money.new(123456789, "SEK").format` will return `1,234,567.89
291
+ kr` which otherwise will return `1 234 567,89 kr`.
292
+
293
+ If you wish to disable this feature:
294
+ ``` ruby
295
+ Money.use_i18n = false
296
+ ```
297
+
269
298
  ## Migration Notes
270
299
 
271
300
  #### Version 6.0.0
@@ -129,7 +129,7 @@
129
129
  "priority": 100,
130
130
  "iso_code": "AZN",
131
131
  "name": "Azerbaijani Manat",
132
- "symbol": null,
132
+ "symbol": "₼",
133
133
  "alternate_symbols": ["m", "man"],
134
134
  "subunit": "Qəpik",
135
135
  "subunit_to_unit": 100,
@@ -1448,7 +1448,7 @@
1448
1448
  "alternate_symbols": [",-"],
1449
1449
  "subunit": "Øre",
1450
1450
  "subunit_to_unit": 100,
1451
- "symbol_first": true,
1451
+ "symbol_first": false,
1452
1452
  "html_entity": "kr",
1453
1453
  "decimal_mark": ",",
1454
1454
  "thousands_separator": ".",
@@ -1918,11 +1918,11 @@
1918
1918
  },
1919
1919
  "tmt": {
1920
1920
  "priority": 100,
1921
- "iso_code": "TMM",
1921
+ "iso_code": "TMT",
1922
1922
  "name": "Turkmenistani Manat",
1923
- "symbol": "m",
1923
+ "symbol": "T",
1924
1924
  "alternate_symbols": [],
1925
- "subunit": "Tennesi",
1925
+ "subunit": "Tenge",
1926
1926
  "subunit_to_unit": 100,
1927
1927
  "symbol_first": false,
1928
1928
  "html_entity": "",
@@ -2023,7 +2023,7 @@
2023
2023
  "subunit": "Kopiyka",
2024
2024
  "subunit_to_unit": 100,
2025
2025
  "symbol_first": false,
2026
- "html_entity": "&#x20B4",
2026
+ "html_entity": "₴",
2027
2027
  "decimal_mark": ".",
2028
2028
  "thousands_separator": ",",
2029
2029
  "iso_numeric": "980"
@@ -71,7 +71,9 @@ class Money
71
71
  # Money::Currency.wrap(c1) #=> #<Money::Currency id: usd ...>
72
72
  # Money::Currency.wrap("usd") #=> #<Money::Currency id: usd ...>
73
73
  def wrap(object)
74
- if object.nil? || object.is_a?(Currency)
74
+ if object.nil?
75
+ nil
76
+ elsif object.is_a?(Currency)
75
77
  object
76
78
  else
77
79
  Currency.new(object)
@@ -125,7 +127,7 @@ class Money
125
127
  private
126
128
 
127
129
  def stringify_keys
128
- table.keys.map{|k| k.to_s.downcase}
130
+ table.keys.each_with_object(Set.new) { |k, set| set.add(k.to_s.downcase) }
129
131
  end
130
132
  end
131
133
 
@@ -172,9 +174,18 @@ class Money
172
174
  if self.class.stringified_keys.include?(id)
173
175
  @id = id.to_sym
174
176
  data = self.class.table[@id]
175
- data.each_pair do |key, value|
176
- instance_variable_set(:"@#{key}", value)
177
- end
177
+ @priority = data[:priority]
178
+ @iso_code = data[:iso_code]
179
+ @name = data[:name]
180
+ @symbol = data[:symbol]
181
+ @alternate_symbols = data[:alternate_symbols]
182
+ @subunit = data[:subunit]
183
+ @subunit_to_unit = data[:subunit_to_unit]
184
+ @symbol_first = data[:symbol_first]
185
+ @html_entity = data[:html_entity]
186
+ @decimal_mark = data[:decimal_mark]
187
+ @thousands_separator = data[:thousands_separator]
188
+ @iso_numeric = data[:iso_numeric]
178
189
  else
179
190
  raise UnknownCurrency, "Unknown currency '#{id}'"
180
191
  end
@@ -23,10 +23,12 @@ class Money
23
23
  # Money.new(100) == Money.new(101) #=> false
24
24
  # Money.new(100) == Money.new(100) #=> true
25
25
  def ==(other_money)
26
- other_money = other_money.to_money
27
- fractional == other_money.fractional && currency == other_money.currency
28
- rescue NoMethodError
29
- false
26
+ if other_money.respond_to?(:to_money)
27
+ other_money = other_money.to_money
28
+ fractional == other_money.fractional && currency == other_money.currency
29
+ else
30
+ false
31
+ end
30
32
  end
31
33
 
32
34
  # Synonymous with +#==+.
@@ -41,13 +43,15 @@ class Money
41
43
  end
42
44
 
43
45
  def <=>(val)
44
- val = val.to_money
45
- unless fractional == 0 || val.fractional == 0 || currency == val.currency
46
- val = val.exchange_to(currency)
46
+ if val.respond_to?(:to_money)
47
+ val = val.to_money unless val.respond_to?(:fractional)
48
+ if fractional != 0 && val.fractional != 0 && currency != val.currency
49
+ val = val.exchange_to(currency)
50
+ end
51
+ fractional <=> val.fractional
52
+ else
53
+ raise ArgumentError, "Comparison of #{self.class} with #{val.inspect} failed"
47
54
  end
48
- fractional <=> val.fractional
49
- rescue NoMethodError
50
- raise ArgumentError, "Comparison of #{self.class} with #{val.inspect} failed"
51
55
  end
52
56
 
53
57
  # Test if the amount is positive. Returns +true+ if the money amount is
@@ -87,6 +91,7 @@ class Money
87
91
  # @example
88
92
  # Money.new(100) + Money.new(100) #=> #<Money @fractional=200>
89
93
  def +(other_money)
94
+ return self if other_money == 0
90
95
  other_money = other_money.exchange_to(currency)
91
96
  Money.new(fractional + other_money.fractional, currency)
92
97
  end
@@ -103,6 +108,7 @@ class Money
103
108
  # @example
104
109
  # Money.new(100) - Money.new(99) #=> #<Money @fractional=1>
105
110
  def -(other_money)
111
+ return self if other_money == 0
106
112
  other_money = other_money.exchange_to(currency)
107
113
  Money.new(fractional - other_money.fractional, currency)
108
114
  end
@@ -3,8 +3,8 @@ class Money
3
3
  module Formatting
4
4
  def self.included(base)
5
5
  [
6
- [:thousands_separator, :delimiter, "."],
7
- [:decimal_mark, :separator, ","]
6
+ [:thousands_separator, :delimiter, ","],
7
+ [:decimal_mark, :separator, "."]
8
8
  ].each do |method, name, character|
9
9
  define_i18n_method(method, name, character)
10
10
  end
@@ -199,11 +199,13 @@ class Money
199
199
  formatted = self.abs.to_s
200
200
 
201
201
  if rules[:rounded_infinite_precision]
202
+ formatted.gsub!(/#{currency.decimal_mark}/, '.') unless '.' == currency.decimal_mark
202
203
  formatted = ((BigDecimal(formatted) * currency.subunit_to_unit).round / BigDecimal(currency.subunit_to_unit.to_s)).to_s("F")
203
204
  formatted.gsub!(/\..*/) do |decimal_part|
204
205
  decimal_part << '0' while decimal_part.length < (currency.decimal_places + 1)
205
206
  decimal_part
206
207
  end
208
+ formatted.gsub!(/\./, currency.decimal_mark) unless '.' == currency.decimal_mark
207
209
  end
208
210
 
209
211
  sign = self.negative? ? '-' : ''
@@ -247,10 +249,7 @@ class Money
247
249
  formatted="#{sign_before}#{sign}#{formatted}"
248
250
  end
249
251
 
250
- if rules.has_key?(:decimal_mark) && rules[:decimal_mark] &&
251
- rules[:decimal_mark] != decimal_mark
252
- formatted.sub!(decimal_mark, rules[:decimal_mark])
253
- end
252
+ apply_decimal_mark_from_rules(formatted, rules)
254
253
 
255
254
  if rules[:with_currency]
256
255
  formatted << " "
@@ -283,6 +282,20 @@ class Money
283
282
  end
284
283
  rules
285
284
  end
285
+
286
+ # Applies decimal mark from rules to formatted
287
+ #
288
+ # @param [String] formatted
289
+ # @param [Hash] rules
290
+ def apply_decimal_mark_from_rules(formatted, rules)
291
+ if rules.has_key?(:decimal_mark) && rules[:decimal_mark] &&
292
+ rules[:decimal_mark] != decimal_mark
293
+
294
+ regexp_decimal = Regexp.escape(decimal_mark)
295
+ formatted.sub!(/(.*)(#{regexp_decimal})(.*)\Z/,
296
+ "\\1#{rules[:decimal_mark]}\\3")
297
+ end
298
+ end
286
299
  end
287
300
 
288
301
  def regexp_format(formatted, rules, decimal_mark, symbol_value)
data/lib/money/money.rb CHANGED
@@ -92,7 +92,7 @@ class Money
92
92
  # Money.empty #=> #<Money @fractional=0>
93
93
  def empty(currency = default_currency)
94
94
  @empty ||= {}
95
- @empty[currency] ||= Money.new(0, currency)
95
+ @empty[currency] ||= Money.new(0, currency).freeze
96
96
  end
97
97
  alias_method :zero, :empty
98
98
  end
@@ -238,13 +238,10 @@ class Money
238
238
  # Money.new(100, "EUR") #=> #<Money @fractional=100 @currency="EUR">
239
239
  #
240
240
  def initialize(obj, currency = Money.default_currency, bank = Money.default_bank)
241
- @fractional = obj.fractional
242
- @currency = obj.currency
243
- @bank = obj.bank
244
- rescue NoMethodError
245
- @fractional = as_d(obj)
246
- @currency = Currency.wrap(currency)
247
- @bank = bank
241
+ @fractional = obj.respond_to?(:fractional) ? obj.fractional : as_d(obj)
242
+ @currency = obj.respond_to?(:currency) ? obj.currency : Currency.wrap(currency)
243
+ @currency ||= Money.default_currency
244
+ @bank = obj.respond_to?(:bank) ? obj.bank : bank
248
245
  end
249
246
 
250
247
  # Assuming using a currency using dollars:
@@ -362,6 +359,16 @@ class Money
362
359
  as_d(fractional) / as_d(currency.subunit_to_unit)
363
360
  end
364
361
 
362
+ # Return the amount of money as a Integer.
363
+ #
364
+ # @return [Integer]
365
+ #
366
+ # @example
367
+ # Money.us_dollar(1_00).to_i #=> 1
368
+ def to_i
369
+ to_d.to_i
370
+ end
371
+
365
372
  # Return the amount of money as a float. Floating points cannot guarantee
366
373
  # precision. Therefore, this function should only be used when you no longer
367
374
  # need to represent currency or working with another system that requires
@@ -521,13 +528,11 @@ class Money
521
528
  private
522
529
 
523
530
  def as_d(num)
524
- if num.is_a?(Rational)
525
- num.to_d(self.class.conversion_precision)
531
+ if num.respond_to?(:to_d)
532
+ num.is_a?(Rational) ? num.to_d(self.class.conversion_precision) : num.to_d
526
533
  else
527
- num.to_d
534
+ BigDecimal.new(num.to_s)
528
535
  end
529
- rescue NoMethodError
530
- BigDecimal.new(num.to_s)
531
536
  end
532
537
 
533
538
  def strings_from_fractional
data/lib/money/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class Money
2
- VERSION = "6.1.1"
2
+ VERSION = "6.2.0"
3
3
  end
data/money.gemspec CHANGED
@@ -25,11 +25,11 @@ and choose the migration that best suits your application.
25
25
  Test responsibly :-)
26
26
  MSG
27
27
 
28
- s.add_dependency "i18n", "~> 0.6.4"
28
+ s.add_dependency 'i18n', ['>= 0.6.4', '<= 0.7.0.dev']
29
29
 
30
30
  s.add_development_dependency "bundler", "~> 1.3"
31
31
  s.add_development_dependency "rake"
32
- s.add_development_dependency "rspec", "~> 2.14"
32
+ s.add_development_dependency "rspec", "~> 3.0.0"
33
33
  s.add_development_dependency "yard", "~> 0.8"
34
34
  s.add_development_dependency "kramdown", "~> 1.1"
35
35
 
@@ -6,7 +6,7 @@ describe Money::Bank::Base do
6
6
  it "is local to one class" do
7
7
  klass = Money::Bank::Base
8
8
  subclass = Class.new(Money::Bank::Base)
9
- klass.instance.should_not == subclass.instance
9
+ expect(klass.instance).not_to eq subclass.instance
10
10
  end
11
11
  end
12
12
 
@@ -14,7 +14,7 @@ describe Money::Bank::Base do
14
14
  it "accepts a block and stores @rounding_method" do
15
15
  proc = Proc.new { |n| n.ceil }
16
16
  bank = Money::Bank::Base.new(&proc)
17
- bank.rounding_method.should == proc
17
+ expect(bank.rounding_method).to eq proc
18
18
  end
19
19
  end
20
20
 
@@ -29,7 +29,7 @@ describe Money::Bank::Base do
29
29
  end
30
30
 
31
31
  bank = MyBank.new
32
- bank.setup_called.should == true
32
+ expect(bank.setup_called).to eq true
33
33
  end
34
34
  end
35
35
 
@@ -57,17 +57,17 @@ describe Money::Bank::Base do
57
57
  end
58
58
 
59
59
  it "returns true when currencies match" do
60
- subject.send(:same_currency?, 'USD', 'USD').should be_true
61
- subject.send(:same_currency?, Money::Currency.wrap('USD'), 'USD').should be_true
62
- subject.send(:same_currency?, 'USD', Money::Currency.wrap('USD')).should be_true
63
- subject.send(:same_currency?, Money::Currency.wrap('USD'), Money::Currency.wrap('USD')).should be_true
60
+ expect(subject.send(:same_currency?, 'USD', 'USD')).to be true
61
+ expect(subject.send(:same_currency?, Money::Currency.wrap('USD'), 'USD')).to be true
62
+ expect(subject.send(:same_currency?, 'USD', Money::Currency.wrap('USD'))).to be true
63
+ expect(subject.send(:same_currency?, Money::Currency.wrap('USD'), Money::Currency.wrap('USD'))).to be true
64
64
  end
65
65
 
66
66
  it "returns false when currencies do not match" do
67
- subject.send(:same_currency?, 'USD', 'EUR').should be_false
68
- subject.send(:same_currency?, Money::Currency.wrap('USD'), 'EUR').should be_false
69
- subject.send(:same_currency?, 'USD', Money::Currency.wrap('EUR')).should be_false
70
- subject.send(:same_currency?, Money::Currency.wrap('USD'), Money::Currency.wrap('EUR')).should be_false
67
+ expect(subject.send(:same_currency?, 'USD', 'EUR')).to be false
68
+ expect(subject.send(:same_currency?, Money::Currency.wrap('USD'), 'EUR')).to be false
69
+ expect(subject.send(:same_currency?, 'USD', Money::Currency.wrap('EUR'))).to be false
70
+ expect(subject.send(:same_currency?, Money::Currency.wrap('USD'), Money::Currency.wrap('EUR'))).to be false
71
71
  end
72
72
 
73
73
  it "raises an UnknownCurrency exception when an unknown currency is passed" do