money 6.1.1 → 6.2.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.
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