money 5.1.1 → 6.0.0.pre

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 88dd59a388f0deda85a64606f284c552825752ee
4
+ data.tar.gz: 95521d4753cb2dd4d03d8f17860b65457c96e40b
5
+ SHA512:
6
+ metadata.gz: 29413cd78ec039b35a772c0c12b1161b023f83a5fd4ce6ec54e30fd11709a1ab58e457f476a59e5bdd757bc144c44d8b2a321a08240037763a1fc3d2ca2afad4
7
+ data.tar.gz: 9b08dea3b163c0c655454143adb0f59d865de445b7b9cc328a3679069de4ab945d49efe8c0ff648b5619a79278c21bab1aef4dab4aed5895d2be1400955156c6
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## master
4
+ - Fix typo
5
+ - Wrap the currency symbol in a span if :html is specified in the rules
6
+ - Added Money::Currency.all method
7
+ - Allow combined comparison operator to handle zero values without rates
8
+ - Added Money::Currency.unregister method
9
+ - Works on Ruby 1.8.7
10
+ - Update deps
11
+ - Depreciate Money.parse
12
+
3
13
  ## 5.1.1
4
14
 
5
15
  - Added :sign_before_symbol option to format negative numbers as -£1 rather than £-1
@@ -42,6 +52,7 @@
42
52
  - TravisBot is now watching Pull Request!!! (GH-171)
43
53
  - Minor code cleaning
44
54
  - Remove subunit from South Korean won (KRW)
55
+ - Fixed bug where bankers rounding wasn't being used everywhere.
45
56
 
46
57
  ## 5.0.0
47
58
 
data/README.md CHANGED
@@ -34,7 +34,7 @@ This library aids one in handling money and different currencies.
34
34
 
35
35
  - Your app must use UTF-8 to function with this library. There are a
36
36
  number of non-ASCII currency attributes.
37
- - This app requires Ruby 1.9 and JSON. If you're using JRuby < 1.7.0
37
+ - This app requires JSON. If you're using JRuby < 1.7.0
38
38
  you'll need to add `gem "json"` to your Gemfile or similar.
39
39
 
40
40
  ## Downloading
@@ -112,7 +112,7 @@ curr = {
112
112
  :iso_numeric => "840",
113
113
  :name => "United States Dollar",
114
114
  :symbol => "$",
115
- :subunit => "Cent"
115
+ :subunit => "Cent",
116
116
  :subunit_to_unit => 100,
117
117
  :separator => ".",
118
118
  :delimiter => ","
@@ -254,4 +254,4 @@ implementations.
254
254
 
255
255
  To integrate money in a Rails application use [money-rails](http://github.com/RubyMoney/money-rails).
256
256
 
257
- For depreceated methods of integrating with Rails, check [the wiki](https://github.com/RubyMoney/money/wiki).
257
+ For deprecated methods of integrating with Rails, check [the wiki](https://github.com/RubyMoney/money/wiki).
@@ -27,6 +27,20 @@
27
27
  "thousands_separator": ",",
28
28
  "iso_numeric": "288"
29
29
  },
30
+ "mtl": {
31
+ "priority": 100,
32
+ "iso_code": "MTL",
33
+ "name": "Maltese Lira",
34
+ "symbol": "₤",
35
+ "alternate_symbols": ["Lm"],
36
+ "subunit": "Cent",
37
+ "subunit_to_unit": 100,
38
+ "symbol_first": true,
39
+ "html_entity": "&#x00A3;",
40
+ "decimal_mark": ".",
41
+ "thousands_separator": ",",
42
+ "iso_numeric": "470"
43
+ },
30
44
  "tmm": {
31
45
  "priority": 100,
32
46
  "iso_code": "TMM",
@@ -390,6 +390,20 @@
390
390
  "thousands_separator": ",",
391
391
  "iso_numeric": "756"
392
392
  },
393
+ "clf": {
394
+ "priority": 100,
395
+ "iso_code": "CLF",
396
+ "name": "Unidad de Fomento",
397
+ "symbol": "UF",
398
+ "alternate_symbols": [],
399
+ "subunit": "Peso",
400
+ "subunit_to_unit": 1,
401
+ "symbol_first": true,
402
+ "html_entity": "&#x20B1;",
403
+ "decimal_mark": ",",
404
+ "thousands_separator": ".",
405
+ "iso_numeric": "990"
406
+ },
393
407
  "clp": {
394
408
  "priority": 100,
395
409
  "iso_code": "CLP",
@@ -1561,7 +1575,7 @@
1561
1575
  "subunit": "Grosz",
1562
1576
  "subunit_to_unit": 100,
1563
1577
  "symbol_first": false,
1564
- "html_entity": "",
1578
+ "html_entity": "z&#322;",
1565
1579
  "decimal_mark": ",",
1566
1580
  "thousands_separator": " ",
1567
1581
  "iso_numeric": "985"
@@ -1598,9 +1612,9 @@
1598
1612
  "priority": 100,
1599
1613
  "iso_code": "RON",
1600
1614
  "name": "Romanian Leu",
1601
- "symbol": "L",
1602
- "alternate_symbols": ["lei"],
1603
- "subunit": "Ban",
1615
+ "symbol": "Lei",
1616
+ "alternate_symbols": [],
1617
+ "subunit": "Bani",
1604
1618
  "subunit_to_unit": 100,
1605
1619
  "symbol_first": true,
1606
1620
  "html_entity": "",
@@ -1804,6 +1818,20 @@
1804
1818
  "thousands_separator": ",",
1805
1819
  "iso_numeric": "968"
1806
1820
  },
1821
+ "ssp": {
1822
+ "priority": 100,
1823
+ "iso_code": "SHP",
1824
+ "name": "South Sudanese Pound",
1825
+ "symbol": "£",
1826
+ "alternate_symbols": [],
1827
+ "subunit": "piaster",
1828
+ "subunit_to_unit": 100,
1829
+ "symbol_first": false,
1830
+ "html_entity": "&#x00A3;",
1831
+ "decimal_mark": ".",
1832
+ "thousands_separator": ",",
1833
+ "iso_numeric": "728"
1834
+ },
1807
1835
  "std": {
1808
1836
  "priority": 100,
1809
1837
  "iso_code": "STD",
@@ -1940,8 +1968,8 @@
1940
1968
  "subunit_to_unit": 100,
1941
1969
  "symbol_first": false,
1942
1970
  "html_entity": "",
1943
- "decimal_mark": ".",
1944
- "thousands_separator": ",",
1971
+ "decimal_mark": ",",
1972
+ "thousands_separator": ".",
1945
1973
  "iso_numeric": "949"
1946
1974
  },
1947
1975
  "ttd": {
@@ -2126,6 +2154,34 @@
2126
2154
  "thousands_separator": ",",
2127
2155
  "iso_numeric": "950"
2128
2156
  },
2157
+ "xag": {
2158
+ "priority": 100,
2159
+ "iso_code": "XAG",
2160
+ "name": "Silver (Troy Ounce)",
2161
+ "symbol": "oz t",
2162
+ "alternate_symbols": [],
2163
+ "subunit": "oz",
2164
+ "subunit_to_unit": 1,
2165
+ "symbol_first": false,
2166
+ "html_entity": "",
2167
+ "decimal_mark": ".",
2168
+ "thousands_separator": ",",
2169
+ "iso_numeric": "961"
2170
+ },
2171
+ "xau": {
2172
+ "priority": 100,
2173
+ "iso_code": "XAU",
2174
+ "name": "Gold (Troy Ounce)",
2175
+ "symbol": "oz t",
2176
+ "alternate_symbols": [],
2177
+ "subunit": "oz",
2178
+ "subunit_to_unit": 1,
2179
+ "symbol_first": false,
2180
+ "html_entity": "",
2181
+ "decimal_mark": ".",
2182
+ "thousands_separator": ",",
2183
+ "iso_numeric": "959"
2184
+ },
2129
2185
  "xcd": {
2130
2186
  "priority": 100,
2131
2187
  "iso_code": "XCD",
@@ -2140,6 +2196,20 @@
2140
2196
  "thousands_separator": ",",
2141
2197
  "iso_numeric": "951"
2142
2198
  },
2199
+ "xdr": {
2200
+ "priority": 100,
2201
+ "iso_code": "XDR",
2202
+ "name": "Special Drawing Rights",
2203
+ "symbol": "SDR",
2204
+ "alternate_symbols": ["XDR"],
2205
+ "subunit": "",
2206
+ "subunit_to_unit": 1,
2207
+ "symbol_first": false,
2208
+ "html_entity": "$",
2209
+ "decimal_mark": ".",
2210
+ "thousands_separator": ",",
2211
+ "iso_numeric": "960"
2212
+ },
2143
2213
  "xof": {
2144
2214
  "priority": 100,
2145
2215
  "iso_code": "XOF",
@@ -2209,5 +2279,19 @@
2209
2279
  "decimal_mark": ".",
2210
2280
  "thousands_separator": ",",
2211
2281
  "iso_numeric": "894"
2282
+ },
2283
+ "zmw": {
2284
+ "priority": 100,
2285
+ "iso_code": "ZMW",
2286
+ "name": "Zambian Kwacha",
2287
+ "symbol": "ZK",
2288
+ "alternate_symbols": [],
2289
+ "subunit": "Ngwee",
2290
+ "subunit_to_unit": 100,
2291
+ "symbol_first": false,
2292
+ "html_entity": "",
2293
+ "decimal_mark": ".",
2294
+ "thousands_separator": ",",
2295
+ "iso_numeric": "967"
2212
2296
  }
2213
2297
  }
@@ -0,0 +1,30 @@
1
+ {
2
+ "btc": {
3
+ "priority": 100,
4
+ "iso_code": "BTC",
5
+ "name": "Bitcoin",
6
+ "symbol": "B⃦",
7
+ "alternate_symbols": [],
8
+ "subunit": "Satoshi",
9
+ "subunit_to_unit": 10000000,
10
+ "symbol_first": true,
11
+ "html_entity": "",
12
+ "decimal_mark": ".",
13
+ "thousands_separator": ",",
14
+ "iso_numeric": ""
15
+ },
16
+ "jep": {
17
+ "priority": 100,
18
+ "iso_code": "JEP",
19
+ "name": "Jersey Pound",
20
+ "symbol": "£",
21
+ "alternate_symbols": [],
22
+ "subunit": "Penny",
23
+ "subunit_to_unit": 100,
24
+ "symbol_first": true,
25
+ "html_entity": "&#x00A3;",
26
+ "decimal_mark": ".",
27
+ "thousands_separator": ",",
28
+ "iso_numeric": ""
29
+ }
30
+ }
data/lib/money.rb CHANGED
@@ -4,3 +4,4 @@ require "i18n" rescue LoadError
4
4
  require "money/currency"
5
5
  require "money/money"
6
6
  require "money/core_extensions"
7
+ require "money/deprecations"
@@ -48,7 +48,7 @@ class Money
48
48
  # Money::Currency.find_by_iso_numeric('001') #=> nil
49
49
  def find_by_iso_numeric(num)
50
50
  num = num.to_s
51
- id, garbage = self.table.find{|key, currency| currency[:iso_numeric] == num}
51
+ id, _ = self.table.find{|key, currency| currency[:iso_numeric] == num}
52
52
  new(id) if self.table[id]
53
53
  end
54
54
 
@@ -90,6 +90,16 @@ class Money
90
90
  @table ||= load_currencies
91
91
  end
92
92
 
93
+ # List the currencies imported and registered
94
+ # @return [Array]
95
+ #
96
+ # @example
97
+ # Money::Currency.iso_codes()
98
+ # [#<Currency ..USD>, 'CAD', 'EUR']...
99
+ def all
100
+ table.keys.map {|curr| Currency.new(curr)}.sort_by(&:priority)
101
+ end
102
+
93
103
  # We need a string-based validator before creating an unbounded number of symbols.
94
104
  # http://www.randomhacks.net/articles/2007/01/20/13-ways-of-looking-at-a-ruby-symbol#11
95
105
  # https://github.com/RubyMoney/money/issues/132
@@ -103,6 +113,12 @@ class Money
103
113
  @stringified_keys = stringify_keys
104
114
  end
105
115
 
116
+ def unregister(curr)
117
+ key = curr[:iso_code].downcase.to_sym
118
+ @table.delete(key)
119
+ @stringified_keys = stringify_keys
120
+ end
121
+
106
122
  private
107
123
 
108
124
  def stringify_keys
@@ -156,11 +172,6 @@ class Money
156
172
  # @return [Integer]
157
173
  attr_reader :subunit_to_unit
158
174
 
159
- # The number of digits after the decimal separator.
160
- #
161
- # @return [Float]
162
- attr_reader :exponent
163
-
164
175
  # The decimal mark, or character used to separate the whole unit from the subunit.
165
176
  #
166
177
  # @return [String]
@@ -175,7 +186,7 @@ class Money
175
186
 
176
187
  # Should the currency symbol precede the amount, or should it come after?
177
188
  #
178
- # @return [boolean]
189
+ # @return [Boolean]
179
190
  attr_reader :symbol_first
180
191
 
181
192
  # Create a new +Currency+ object.
@@ -229,7 +240,7 @@ class Money
229
240
  # c1 == c2 #=> false
230
241
  def ==(other_currency)
231
242
  self.equal?(other_currency) ||
232
- self.id == other_currency.id
243
+ self.id.to_s.downcase == (other_currency.is_a?(Currency) ? other_currency.id.to_s.downcase : other_currency.to_s.downcase)
233
244
  end
234
245
 
235
246
  # Compares +self+ with +other_currency+ and returns +true+ if the are the
@@ -7,8 +7,9 @@ module Money::Currency::Loader
7
7
  #
8
8
  # @return [Hash]
9
9
  def load_currencies
10
- currencies = parse_currency_file("currency.json")
11
- currencies.merge! parse_currency_file("currency_bc.json")
10
+ currencies = parse_currency_file("currency_iso.json")
11
+ currencies.merge! parse_currency_file("currency_non_iso.json")
12
+ currencies.merge! parse_currency_file("currency_backwards_compatible.json")
12
13
  end
13
14
 
14
15
  private
@@ -0,0 +1,10 @@
1
+ class Money
2
+ # Displays a deprecation warning message.
3
+ #
4
+ # @param [String] message The message to display.
5
+ #
6
+ # @return [nil]
7
+ def self.deprecate(message)
8
+ warn "DEPRECATION WARNING: #{message}"
9
+ end
10
+ end
data/lib/money/money.rb CHANGED
@@ -221,7 +221,7 @@ class Money
221
221
  # Alternatively you can use the convenience
222
222
  # methods like {Money.ca_dollar} and {Money.us_dollar}.
223
223
  #
224
- # @param [Integer] The value given in the fractional unit.
224
+ # @param [Numeric] fractional The value given in the fractional unit.
225
225
  # @param [Currency, String, Symbol] currency The currency format.
226
226
  # @param [Money::Bank::*] bank The exchange bank to use.
227
227
  #
@@ -468,7 +468,7 @@ class Money
468
468
  # be distributed round-robin amongst the parties. This means that parties
469
469
  # listed first will likely recieve more pennies then ones that are listed later
470
470
  #
471
- # @param [0.50, 0.25, 0.25] to give 50% of the cash to party1, 25% ot party2, and 25% to party3.
471
+ # @param [Array<Float, Float, Float>] splits [0.50, 0.25, 0.25] to give 50% of the cash to party1, 25% to party2, and 25% to party3.
472
472
  #
473
473
  # @return [Array<Money, Money, Money>]
474
474
  #
@@ -506,7 +506,7 @@ class Money
506
506
 
507
507
  # Split money amongst parties evenly without loosing pennies.
508
508
  #
509
- # @param [2] number of parties.
509
+ # @param [Numeric] num number of parties.
510
510
  #
511
511
  # @return [Array<Money, Money, Money>]
512
512
  #
@@ -46,7 +46,7 @@ class Money
46
46
  def <=>(other_money)
47
47
  if other_money.respond_to?(:to_money)
48
48
  other_money = other_money.to_money
49
- if self.currency == other_money.currency
49
+ if fractional == 0 || other_money.fractional == 0 || currency == other_money.currency
50
50
  fractional <=> other_money.fractional
51
51
  else
52
52
  fractional <=> other_money.exchange_to(currency).fractional
@@ -47,7 +47,7 @@ class Money
47
47
 
48
48
  # Creates a formatted price string according to several rules.
49
49
  #
50
- # @param [Hash] *rules The options used to format the string.
50
+ # @param [Hash] rules The options used to format the string.
51
51
  #
52
52
  # @return [String]
53
53
  #
@@ -214,6 +214,16 @@ class Money
214
214
  formatted = "#{self.to_s.to_i}"
215
215
  end
216
216
 
217
+ thousands_separator_value = thousands_separator
218
+ # Determine thousands_separator
219
+ if rules.has_key?(:thousands_separator)
220
+ thousands_separator_value = rules[:thousands_separator] || ''
221
+ end
222
+
223
+ # Apply thousands_separator
224
+ formatted.gsub!(regexp_format(formatted, rules, decimal_mark, symbol_value),
225
+ "\\1#{thousands_separator_value}")
226
+
217
227
  symbol_position =
218
228
  if rules.has_key?(:symbol_position)
219
229
  rules[:symbol_position]
@@ -230,6 +240,8 @@ class Money
230
240
  end
231
241
 
232
242
  if symbol_value && !symbol_value.empty?
243
+ symbol_value = "<span class=\"currency_symbol\">#{symbol_value}</span>" if rules[:html_wrap_symbol]
244
+
233
245
  formatted = if symbol_position == :before
234
246
  symbol_space = rules[:symbol_before_without_space] === false ? " " : ""
235
247
  "#{sign}#{symbol_value}#{symbol_space}#{formatted}"
@@ -244,16 +256,6 @@ class Money
244
256
  formatted.sub!(decimal_mark, rules[:decimal_mark])
245
257
  end
246
258
 
247
- thousands_separator_value = thousands_separator
248
- # Determine thousands_separator
249
- if rules.has_key?(:thousands_separator)
250
- thousands_separator_value = rules[:thousands_separator] || ''
251
- end
252
-
253
- # Apply thousands_separator
254
- formatted.gsub!(regexp_format(formatted, rules, decimal_mark, symbol_value),
255
- "\\1#{thousands_separator_value}")
256
-
257
259
  if rules[:with_currency]
258
260
  formatted << " "
259
261
  formatted << '<span class="currency">' if rules[:html]
@@ -268,7 +270,7 @@ class Money
268
270
 
269
271
  # Cleans up formatting rules.
270
272
  #
271
- # @param [Hash]
273
+ # @param [Hash] rules
272
274
  #
273
275
  # @return [Hash]
274
276
  def normalize_formatting_rules(rules)
@@ -294,7 +296,7 @@ class Money
294
296
  /(\d+?)(?=(\d\d)+(\d)(?:\.))/
295
297
  else
296
298
  # Symbols may contain decimal marks (E.g "դր.")
297
- if formatted.sub(symbol_value, "") =~ /#{regexp_decimal}/
299
+ if formatted.sub(symbol_value.to_s, "") =~ /#{regexp_decimal}/
298
300
  /(\d)(?=(?:\d{3})+(?:#{regexp_decimal}))/
299
301
  else
300
302
  /(\d)(?=(?:\d{3})+(?:[^\d]{1}|$))/
@@ -31,9 +31,10 @@ class Money
31
31
  # @example Mismatching currencies
32
32
  # 'USD 2000'.to_money("EUR") #=> ArgumentError
33
33
  #
34
- # @see Money.from_string
34
+ # @see #from_string
35
35
  #
36
36
  def parse(input, currency = nil)
37
+ Money.deprecate ".parse is depreciated and will be remove in 6.1.0. Please write your own parsing methods."
37
38
  i = input.to_s.strip
38
39
 
39
40
  # raise Money::Currency.table.collect{|c| c[1][:symbol]}.inspect
@@ -73,7 +74,7 @@ class Money
73
74
  # according to +currency+ subunit property,
74
75
  # before instantiating the Money object.
75
76
  #
76
- # Behind the scenes, this method relies on {Money.from_bigdecimal}
77
+ # Behind the scenes, this method relies on {#from_bigdecimal}
77
78
  # to avoid problems with string-to-numeric conversion.
78
79
  #
79
80
  # @param [String, #to_s] value The money amount, in dollars.
@@ -93,7 +94,7 @@ class Money
93
94
  # #=> #<Money @fractional=100 @currency="BHD">
94
95
  #
95
96
  # @see String#to_money
96
- # @see Money.parse
97
+ # @see #parse
97
98
  #
98
99
  def from_string(value, currency = Money.default_currency)
99
100
  from_bigdecimal(BigDecimal.new(value.to_s), currency)
@@ -120,7 +121,7 @@ class Money
120
121
  # #=> #<Money @fractional=100 @currency="BHD">
121
122
  #
122
123
  # @see Fixnum#to_money
123
- # @see Money.from_numeric
124
+ # @see #from_numeric
124
125
  #
125
126
  def from_fixnum(value, currency = Money.default_currency)
126
127
  currency = Money::Currency.wrap(currency)
@@ -152,7 +153,7 @@ class Money
152
153
  # #=> #<Money @fractional=100 @currency="BHD">
153
154
  #
154
155
  # @see Float#to_money
155
- # @see Money.from_numeric
156
+ # @see #from_numeric
156
157
  #
157
158
  def from_float(value, currency = Money.default_currency)
158
159
  from_bigdecimal(BigDecimal.new(value.to_s), currency)
@@ -179,7 +180,7 @@ class Money
179
180
  # #=> #<Money @fractional=100 @currency="BHD">
180
181
  #
181
182
  # @see BigDecimal#to_money
182
- # @see Money.from_numeric
183
+ # @see #from_numeric
183
184
  #
184
185
  def from_bigdecimal(value, currency = Money.default_currency)
185
186
  currency = Money::Currency.wrap(currency)
@@ -196,8 +197,8 @@ class Money
196
197
  # and tries to forwards the call to the most appropriate method
197
198
  # in order to reduce computation effort.
198
199
  # For instance, if +value+ is an Integer, this method calls
199
- # {Money.from_fixnum} instead of using the default
200
- # {Money.from_bigdecimal} which adds the overload to converts
200
+ # {#from_fixnum} instead of using the default
201
+ # {#from_bigdecimal} which adds the overload to converts
201
202
  # the value into a slower BigDecimal instance.
202
203
  #
203
204
  # @param [Numeric] value The money amount, in dollars.
@@ -216,9 +217,9 @@ class Money
216
217
  # #=> ArgumentError
217
218
  #
218
219
  # @see Numeric#to_money
219
- # @see Money.from_fixnum
220
- # @see Money.from_float
221
- # @see Money.from_bigdecimal
220
+ # @see #from_fixnum
221
+ # @see #from_float
222
+ # @see #from_bigdecimal
222
223
  #
223
224
  def from_numeric(value, currency = Money.default_currency)
224
225
  case value
@@ -260,89 +261,90 @@ class Money
260
261
  #save it from being mis-interpreted as a decimal.
261
262
  num.chop! if num.match(/[\.|,]$/)
262
263
 
263
- # gather all decimal_marks within the result number
264
- used_decimal_marks = num.scan(/[^\d]/)
264
+ # gather all decimal_marks within the result number
265
+ used_delimiters = num.scan(/[^\d]/)
265
266
 
266
- # determine the number of unique decimal_marks within the number
267
- #
268
- # e.g.
269
- # $1,234,567.89 would return 2 (, and .)
270
- # $125,00 would return 1
271
- # $199 would return 0
272
- # $1 234,567.89 would raise an error (decimal_marks are space, comma, and period)
273
- case used_decimal_marks.uniq.length
274
- # no decimal_mark or thousands_separator; major (dollars) is the number, and minor (cents) is 0
275
- when 0 then major, minor = num, 0
267
+ # determine the number of unique decimal_marks within the number
268
+ #
269
+ # e.g.
270
+ # $1,234,567.89 would return 2 (, and .)
271
+ # $125,00 would return 1
272
+ # $199 would return 0
273
+ # $1 234,567.89 would raise an error (decimal_marks are space, comma, and period)
274
+ case used_delimiters.uniq.length
275
+ # no decimal_mark or thousands_separator; major (dollars) is the number, and minor (cents) is 0
276
+ when 0 then major, minor = num, 0
277
+
278
+ # two decimal_marks, so we know the last item in this array is the
279
+ # major/minor thousands_separator and the rest are decimal_marks
280
+ when 2
281
+ thousands_separator, decimal_mark = used_delimiters.uniq
276
282
 
277
- # two decimal_marks, so we know the last item in this array is the
278
- # major/minor thousands_separator and the rest are decimal_marks
279
- when 2
280
- decimal_mark, thousands_separator = used_decimal_marks.uniq
281
- # remove all decimal_marks, split on the thousands_separator
282
- major, minor = num.gsub(decimal_mark, '').split(thousands_separator)
283
- min = 0 unless min
284
- when 1
285
- # we can't determine if the comma or period is supposed to be a decimal_mark or a thousands_separator
286
- # e.g.
287
- # 1,00 - comma is a thousands_separator
288
- # 1.000 - period is a thousands_separator
289
- # 1,000 - comma is a decimal_mark
290
- # 1,000,000 - comma is a decimal_mark
291
- # 10000,00 - comma is a thousands_separator
292
- # 1000,000 - comma is a thousands_separator
283
+ # remove all thousands_separator, split on the decimal_mark
284
+ major, minor = num.gsub(thousands_separator, '').split(decimal_mark)
285
+ min = 0 unless min
286
+ when 1
287
+ # we can't determine if the comma or period is supposed to be a decimal_mark or a thousands_separator
288
+ # e.g.
289
+ # 1,00 - comma is a thousands_separator
290
+ # 1.000 - period is a thousands_separator
291
+ # 1,000 - comma is a decimal_mark
292
+ # 1,000,000 - comma is a decimal_mark
293
+ # 10000,00 - comma is a thousands_separator
294
+ # 1000,000 - comma is a thousands_separator
293
295
 
294
- # assign first decimal_mark for reusability
295
- decimal_mark = used_decimal_marks.first
296
+ # assign first decimal_mark for reusability
297
+ decimal_mark = used_delimiters.first
296
298
 
297
- # When we have identified the decimal mark character
298
- if decimal_char == decimal_mark
299
- major, minor = num.split(decimal_char)
299
+ # When we have identified the decimal mark character
300
+ if decimal_char == decimal_mark
301
+ major, minor = num.split(decimal_char)
300
302
 
303
+ else
304
+ # decimal_mark is used as a decimal_mark when there are multiple instances, always
305
+ if num.scan(decimal_mark).length > 1 # multiple matches; treat as decimal_mark
306
+ major, minor = num.gsub(decimal_mark, ''), 0
301
307
  else
302
- # decimal_mark is used as a decimal_mark when there are multiple instances, always
303
- if num.scan(decimal_mark).length > 1 # multiple matches; treat as decimal_mark
304
- major, minor = num.gsub(decimal_mark, ''), 0
308
+ # ex: 1,000 - 1.0000 - 10001.000
309
+ # split number into possible major (dollars) and minor (cents) values
310
+ possible_major, possible_minor = num.split(decimal_mark)
311
+ possible_major ||= "0"
312
+ possible_minor ||= "00"
313
+
314
+ # if the minor (cents) length isn't 3, assign major/minor from the possibles
315
+ # e.g.
316
+ # 1,00 => 1.00
317
+ # 1.0000 => 1.00
318
+ # 1.2 => 1.20
319
+ if possible_minor.length != 3 # thousands_separator
320
+ major, minor = possible_major, possible_minor
305
321
  else
306
- # ex: 1,000 - 1.0000 - 10001.000
307
- # split number into possible major (dollars) and minor (cents) values
308
- possible_major, possible_minor = num.split(decimal_mark)
309
- possible_major ||= "0"
310
- possible_minor ||= "00"
322
+ # minor length is three
323
+ # let's try to figure out intent of the thousands_separator
311
324
 
312
- # if the minor (cents) length isn't 3, assign major/minor from the possibles
325
+ # the major length is greater than three, which means
326
+ # the comma or period is used as a thousands_separator
313
327
  # e.g.
314
- # 1,00 => 1.00
315
- # 1.0000 => 1.00
316
- # 1.2 => 1.20
317
- if possible_minor.length != 3 # thousands_separator
328
+ # 1000,000
329
+ # 100000,000
330
+ if possible_major.length > 3
318
331
  major, minor = possible_major, possible_minor
319
332
  else
320
- # minor length is three
321
- # let's try to figure out intent of the thousands_separator
322
-
323
- # the major length is greater than three, which means
324
- # the comma or period is used as a thousands_separator
325
- # e.g.
326
- # 1000,000
327
- # 100000,000
328
- if possible_major.length > 3
333
+ # number is in format ###{sep}### or ##{sep}### or #{sep}###
334
+ # handle as , is sep, . is thousands_separator
335
+ if decimal_mark == '.'
329
336
  major, minor = possible_major, possible_minor
330
337
  else
331
- # number is in format ###{sep}### or ##{sep}### or #{sep}###
332
- # handle as , is sep, . is thousands_separator
333
- if decimal_mark == '.'
334
- major, minor = possible_major, possible_minor
335
- else
336
- major, minor = "#{possible_major}#{possible_minor}", 0
337
- end
338
+ major, minor = "#{possible_major}#{possible_minor}", 0
338
339
  end
339
340
  end
340
341
  end
341
342
  end
342
- else
343
- # TODO: ParseError
344
- raise ArgumentError, "Invalid currency amount"
345
343
  end
344
+ else
345
+ # TODO: ParseError
346
+ raise ArgumentError, "Invalid currency amount"
347
+ end
346
348
 
347
349
  # build the string based on major/minor since decimal_mark/thousands_separator have been removed
348
350
  # avoiding floating point arithmetic here to ensure accuracy
data/money.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  Gem::Specification.new do |s|
3
3
  s.name = "money"
4
- s.version = "5.1.1"
4
+ s.version = "6.0.0.pre"
5
5
  s.platform = Gem::Platform::RUBY
6
6
  s.authors = ["Tobias Luetke", "Hongli Lai", "Jeremy McNevin",
7
7
  "Shane Emmons", "Simone Carletti"]
@@ -10,14 +10,15 @@ Gem::Specification.new do |s|
10
10
  s.summary = "Money and currency exchange support library."
11
11
  s.description = "This library aids one in handling money and different currencies."
12
12
 
13
- s.required_ruby_version = ">= 1.9.2"
14
- s.required_rubygems_version = ">= 1.3.6"
13
+ s.required_ruby_version = ">= 1.8.7"
15
14
 
16
- s.add_dependency "i18n", "~> 0.6.0"
15
+ s.add_dependency "i18n", "~> 0.6.4"
17
16
 
18
- s.add_development_dependency "rspec", "~> 2.11.0"
19
- s.add_development_dependency "yard", "~> 0.8.1"
20
- s.add_development_dependency "kramdown", "~> 0.14.0"
17
+ s.add_development_dependency "rspec", "~> 2.14"
18
+ s.add_development_dependency "yard", "~> 0.8"
19
+ s.add_development_dependency "kramdown", "~> 1.1"
20
+
21
+ s.license = "MIT"
21
22
 
22
23
  s.files = Dir.glob("{config,lib,spec}/**/*")
23
24
  s.files += %w(CHANGELOG.md LICENSE README.md)
@@ -145,7 +145,7 @@ describe Money::Bank::VariableExchange do
145
145
 
146
146
  context "with :file provided" do
147
147
  it "writes rates to file" do
148
- f = mock('IO')
148
+ f = double('IO')
149
149
  File.should_receive(:open).with('null', 'w').and_yield(f)
150
150
  f.should_receive(:write).with(JSON.dump(@rates))
151
151
 
@@ -7,8 +7,15 @@ describe Money::Currency do
7
7
  FOO = '{ "priority": 1, "iso_code": "FOO", "iso_numeric": "840", "name": "United States Dollar", "symbol": "$", "subunit": "Cent", "subunit_to_unit": 450, "symbol_first": true, "html_entity": "$", "decimal_mark": ".", "thousands_separator": "," }'
8
8
 
9
9
  describe ".find" do
10
- it "returns currency matching given id" do
10
+ before :each do
11
11
  Money::Currency.register(JSON.parse(FOO, :symbolize_names => true))
12
+ end
13
+
14
+ after :each do
15
+ Money::Currency.unregister(JSON.parse(FOO, :symbolize_names => true))
16
+ end
17
+
18
+ it "returns currency matching given id" do
12
19
 
13
20
  expected = Money::Currency.new(:foo)
14
21
  Money::Currency.find(:foo).should == expected
@@ -51,6 +58,19 @@ describe Money::Currency do
51
58
  end
52
59
  end
53
60
 
61
+ describe ".all" do
62
+ it "returns an array of currencies" do
63
+ Money::Currency.all.should include Money::Currency.new(:usd)
64
+ end
65
+ it "includes registered currencies" do
66
+ Money::Currency.register(JSON.parse(FOO, :symbolize_names => true))
67
+ Money::Currency.all.should include Money::Currency.new(:foo)
68
+ Money::Currency.unregister(JSON.parse(FOO, :symbolize_names => true))
69
+ end
70
+ it 'is sorted by priority' do
71
+ Money::Currency.all.first.priority.should == 1
72
+ end
73
+ end
54
74
 
55
75
  describe "#initialize" do
56
76
  it "lookups data from loaded config" do
@@ -84,10 +104,21 @@ describe Money::Currency do
84
104
  currency.should == currency
85
105
  end
86
106
 
87
- it "returns true if the id is equal" do
107
+ it "returns true if the id is equal ignorning case" do
88
108
  Money::Currency.new(:eur).should == Money::Currency.new(:eur)
109
+ Money::Currency.new(:eur).should == Money::Currency.new(:EUR)
89
110
  Money::Currency.new(:eur).should_not == Money::Currency.new(:usd)
90
111
  end
112
+
113
+ it "allows direct comparison of currencies and symbols/strings" do
114
+ Money::Currency.new(:eur).should == 'eur'
115
+ Money::Currency.new(:eur).should == :EUR
116
+ Money::Currency.new(:eur).should_not == 'usd'
117
+ end
118
+
119
+ it "allows comparison with nil and returns false" do
120
+ Money::Currency.new(:eur).should_not == nil
121
+ end
91
122
  end
92
123
 
93
124
  describe "#eql?" do
@@ -159,6 +190,7 @@ describe Money::Currency do
159
190
  it "proper places for custom currency" do
160
191
  Money::Currency.register(JSON.parse(FOO, :symbolize_names => true))
161
192
  Money::Currency.new(:foo).decimal_places == 3
193
+ Money::Currency.unregister(JSON.parse(FOO, :symbolize_names => true))
162
194
  end
163
195
  end
164
196
  end
@@ -126,18 +126,42 @@ describe Money do
126
126
  (Money.new(100_00, "USD") <=> target).should > 0
127
127
  end
128
128
 
129
- it "can be used to compare with a String money value" do
129
+ it "cannot compare objects with different currencies when no rate exists, unless one of the amounts is zero" do
130
+ expect { Money.new(100_00, "EUR") <=> Money.new(100_00, "USD") }.to raise_error(Money::Bank::UnknownRate)
131
+
132
+ (Money.new(100_00, "EUR") <=> Money.new(0, "USD")).should > 0
133
+ (Money.new(0, "EUR") <=> Money.new(100_00, "USD")).should < 0
134
+ (Money.new(0, "EUR") <=> Money.new(0, "USD")).should == 0
135
+ end
136
+
137
+ it "can be used to compare with a String money value when Money object is in default currency" do
130
138
  (Money.new(1_00) <=> "1.00").should == 0
131
139
  (Money.new(1_00) <=> ".99").should > 0
132
140
  (Money.new(1_00) <=> "2.00").should < 0
133
141
  end
134
142
 
135
- it "can be used to compare with a Numeric money value" do
143
+ it "can be used to compare with a String money value when Money object is not in default currency if String evaluates to zero" do
144
+ expect { Money.new(1_00, "EUR") <=> "1.00" }.to raise_error(Money::Bank::UnknownRate)
145
+
146
+ (Money.new(1_00, "EUR") <=> "0.00").should > 0
147
+ (Money.new(0_00, "EUR") <=> "0.00").should == 0
148
+ (Money.new(-1_00, "EUR") <=> "0.00").should < 0
149
+ end
150
+
151
+ it "can be used to compare with a Numeric money value when Money object is in default currency" do
136
152
  (Money.new(1_00) <=> 1).should == 0
137
153
  (Money.new(1_00) <=> 0.99).should > 0
138
154
  (Money.new(1_00) <=> 2.00).should < 0
139
155
  end
140
156
 
157
+ it "can be used to compare with a Numeric money value when Money object is not in default currency if String evaluates to zero" do
158
+ expect { Money.new(1_00, "EUR") <=> 1 }.to raise_error(Money::Bank::UnknownRate)
159
+
160
+ (Money.new(1_00, "EUR") <=> 0).should > 0
161
+ (Money.new(0_00, "EUR") <=> 0).should == 0
162
+ (Money.new(-1_00, "EUR") <=> 0).should < 0
163
+ end
164
+
141
165
  it "can be used to compare with an object that responds to #to_money" do
142
166
  klass = Class.new do
143
167
  def initialize(money)
@@ -167,9 +167,15 @@ describe Money, "formatting" do
167
167
  end
168
168
 
169
169
  it "inserts thousand separators if symbol contains decimal mark and no_cents is true" do
170
- Money.new(100000000, "AMD").format(no_cents: true).should == "1,000,000 դր."
171
- Money.new(100000000, "USD").format(no_cents: true).should == "$1,000,000"
172
- Money.new(100000000, "RUB").format(no_cents: true).should == "1.000.000 р."
170
+ Money.new(100000000, "AMD").format(:no_cents => true).should == "1,000,000 դր."
171
+ Money.new(100000000, "USD").format(:no_cents => true).should == "$1,000,000"
172
+ Money.new(100000000, "RUB").format(:no_cents => true).should == "1.000.000 р."
173
+ end
174
+
175
+ it "doesn't incorrectly format HTML" do
176
+ money = ::Money.new(1999, "RUB")
177
+ output = money.format(:html => true, :no_cents => true)
178
+ output.should == "19 &#x0440;&#x0443;&#x0431;"
173
179
  end
174
180
  end
175
181
 
@@ -294,6 +300,10 @@ describe Money, "formatting" do
294
300
  Money::Currency.register(JSON.parse(INDIAN_BAR, :symbolize_names => true))
295
301
  end
296
302
 
303
+ after(:each) do
304
+ Money::Currency.unregister(JSON.parse(INDIAN_BAR, :symbolize_names => true))
305
+ end
306
+
297
307
  specify "(:south_asian_number_formatting => true) works as documented" do
298
308
  Money.new(10000000, 'INR').format(:south_asian_number_formatting => true, :symbol => false).should == "1,00,000.00"
299
309
  Money.new(1000000000, 'INDIAN_BAR').format(:south_asian_number_formatting => true, :symbol => false).should == "1,00,000.0000"
@@ -339,6 +349,14 @@ describe Money, "formatting" do
339
349
  end
340
350
  end
341
351
 
352
+ describe ":html_wrap_symbol option" do
353
+ specify "(:html_wrap_symbol => true) works as documented" do
354
+ string = Money.ca_dollar(570).format(:html_wrap_symbol => true)
355
+ string.should == "<span class=\"currency_symbol\">$</span>5.70"
356
+ end
357
+ end
358
+
359
+
342
360
  describe ":symbol_position option" do
343
361
  it "inserts currency symbol before the amount when set to :before" do
344
362
  Money.euro(1_234_567_12).format(:symbol_position => :before).should == "€1.234.567,12"
@@ -418,6 +436,11 @@ describe Money, "formatting" do
418
436
  Money::Currency.register(JSON.parse(EU4, :symbolize_names => true))
419
437
  end
420
438
 
439
+ after :each do
440
+ Money::Currency.unregister(JSON.parse(BAR, :symbolize_names => true))
441
+ Money::Currency.unregister(JSON.parse(EU4, :symbolize_names => true))
442
+ end
443
+
421
444
  it "respects custom subunit to unit, decimal and thousands separator" do
422
445
  Money.new(4, "BAR").format.should == "$0.0004"
423
446
  Money.new(4, "EU4").format.should == "€0,0004"
@@ -8,6 +8,11 @@ describe Money, "parsing" do
8
8
  eu4 = '{ "priority": 1, "iso_code": "EU4", "iso_numeric": "841", "name": "Euro with 4 decimal places", "symbol": "€", "subunit": "Cent", "subunit_to_unit": 10000, "symbol_first": true, "html_entity": "€", "decimal_mark": ",", "thousands_separator": "." }'
9
9
 
10
10
  describe ".parse" do
11
+ it "is depreciated" do
12
+ Money.should_receive(:deprecate)
13
+ Money.parse("1.95")
14
+ end
15
+
11
16
  it "parses european-formatted inputs under 10EUR" do
12
17
  five_ninety_five = Money.new(595, 'EUR')
13
18
 
@@ -111,6 +116,11 @@ describe Money, "parsing" do
111
116
  Money::Currency.register(JSON.parse(eu4, :symbolize_names => true))
112
117
  end
113
118
 
119
+ after :each do
120
+ Money::Currency.unregister(JSON.parse(bar, :symbolize_names => true))
121
+ Money::Currency.unregister(JSON.parse(eu4, :symbolize_names => true))
122
+ end
123
+
114
124
  # String#to_money(Currency) is equivalent to Money.parse(String, Currency)
115
125
  it "parses strings respecting subunit to unit, decimal and thousands separator" do
116
126
  "$0.4".to_money("BAR").should == Money.new(4000, "BAR")
data/spec/money_spec.rb CHANGED
@@ -118,6 +118,15 @@ describe Money do
118
118
  end
119
119
 
120
120
  describe ".add_rate" do
121
+ before do
122
+ @default_bank = Money.default_bank
123
+ Money.default_bank = Money::Bank::VariableExchange.new
124
+ end
125
+
126
+ after do
127
+ Money.default_bank = @default_bank
128
+ end
129
+
121
130
  it "saves rate into current bank" do
122
131
  Money.add_rate("EUR", "USD", 10)
123
132
  Money.new(10_00, "EUR").exchange_to("USD").should == Money.new(100_00, "USD")
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: money
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.1.1
5
- prerelease:
4
+ version: 6.0.0.pre
6
5
  platform: ruby
7
6
  authors:
8
7
  - Tobias Luetke
@@ -13,72 +12,64 @@ authors:
13
12
  autorequire:
14
13
  bindir: bin
15
14
  cert_chain: []
16
- date: 2013-02-20 00:00:00.000000000 Z
15
+ date: 2013-07-24 00:00:00.000000000 Z
17
16
  dependencies:
18
17
  - !ruby/object:Gem::Dependency
19
18
  name: i18n
20
19
  requirement: !ruby/object:Gem::Requirement
21
- none: false
22
20
  requirements:
23
21
  - - ~>
24
22
  - !ruby/object:Gem::Version
25
- version: 0.6.0
23
+ version: 0.6.4
26
24
  type: :runtime
27
25
  prerelease: false
28
26
  version_requirements: !ruby/object:Gem::Requirement
29
- none: false
30
27
  requirements:
31
28
  - - ~>
32
29
  - !ruby/object:Gem::Version
33
- version: 0.6.0
30
+ version: 0.6.4
34
31
  - !ruby/object:Gem::Dependency
35
32
  name: rspec
36
33
  requirement: !ruby/object:Gem::Requirement
37
- none: false
38
34
  requirements:
39
35
  - - ~>
40
36
  - !ruby/object:Gem::Version
41
- version: 2.11.0
37
+ version: '2.14'
42
38
  type: :development
43
39
  prerelease: false
44
40
  version_requirements: !ruby/object:Gem::Requirement
45
- none: false
46
41
  requirements:
47
42
  - - ~>
48
43
  - !ruby/object:Gem::Version
49
- version: 2.11.0
44
+ version: '2.14'
50
45
  - !ruby/object:Gem::Dependency
51
46
  name: yard
52
47
  requirement: !ruby/object:Gem::Requirement
53
- none: false
54
48
  requirements:
55
49
  - - ~>
56
50
  - !ruby/object:Gem::Version
57
- version: 0.8.1
51
+ version: '0.8'
58
52
  type: :development
59
53
  prerelease: false
60
54
  version_requirements: !ruby/object:Gem::Requirement
61
- none: false
62
55
  requirements:
63
56
  - - ~>
64
57
  - !ruby/object:Gem::Version
65
- version: 0.8.1
58
+ version: '0.8'
66
59
  - !ruby/object:Gem::Dependency
67
60
  name: kramdown
68
61
  requirement: !ruby/object:Gem::Requirement
69
- none: false
70
62
  requirements:
71
63
  - - ~>
72
64
  - !ruby/object:Gem::Version
73
- version: 0.14.0
65
+ version: '1.1'
74
66
  type: :development
75
67
  prerelease: false
76
68
  version_requirements: !ruby/object:Gem::Requirement
77
- none: false
78
69
  requirements:
79
70
  - - ~>
80
71
  - !ruby/object:Gem::Version
81
- version: 0.14.0
72
+ version: '1.1'
82
73
  description: This library aids one in handling money and different currencies.
83
74
  email:
84
75
  - semmons99+RubyMoney@gmail.com
@@ -86,58 +77,59 @@ executables: []
86
77
  extensions: []
87
78
  extra_rdoc_files: []
88
79
  files:
89
- - config/currency_bc.json
90
- - config/currency.json
91
- - lib/money.rb
92
- - lib/money/money.rb
80
+ - config/currency_backwards_compatible.json
81
+ - config/currency_iso.json
82
+ - config/currency_non_iso.json
83
+ - lib/money/bank/base.rb
84
+ - lib/money/bank/variable_exchange.rb
93
85
  - lib/money/core_extensions.rb
94
- - lib/money/currency.rb
95
86
  - lib/money/currency/heuristics.rb
96
87
  - lib/money/currency/loader.rb
97
- - lib/money/money/formatting.rb
88
+ - lib/money/currency.rb
89
+ - lib/money/deprecations.rb
98
90
  - lib/money/money/arithmetic.rb
91
+ - lib/money/money/formatting.rb
99
92
  - lib/money/money/parsing.rb
100
- - lib/money/bank/variable_exchange.rb
101
- - lib/money/bank/base.rb
102
- - spec/money_spec.rb
103
- - spec/spec_helper.rb
93
+ - lib/money/money.rb
94
+ - lib/money.rb
95
+ - spec/bank/base_spec.rb
96
+ - spec/bank/variable_exchange_spec.rb
97
+ - spec/core_extensions_spec.rb
104
98
  - spec/currency/heuristics_spec.rb
105
99
  - spec/currency_spec.rb
106
100
  - spec/money/arithmetic_spec.rb
107
- - spec/money/parsing_spec.rb
108
101
  - spec/money/formatting_spec.rb
102
+ - spec/money/parsing_spec.rb
103
+ - spec/money_spec.rb
104
+ - spec/spec_helper.rb
109
105
  - spec/support/default_currency_helper.rb
110
- - spec/bank/base_spec.rb
111
- - spec/bank/variable_exchange_spec.rb
112
- - spec/core_extensions_spec.rb
113
106
  - CHANGELOG.md
114
107
  - LICENSE
115
108
  - README.md
116
109
  - Rakefile
117
110
  - money.gemspec
118
111
  homepage: http://rubymoney.github.com/money
119
- licenses: []
112
+ licenses:
113
+ - MIT
114
+ metadata: {}
120
115
  post_install_message:
121
116
  rdoc_options: []
122
117
  require_paths:
123
118
  - lib
124
119
  required_ruby_version: !ruby/object:Gem::Requirement
125
- none: false
126
120
  requirements:
127
- - - ! '>='
121
+ - - '>='
128
122
  - !ruby/object:Gem::Version
129
- version: 1.9.2
123
+ version: 1.8.7
130
124
  required_rubygems_version: !ruby/object:Gem::Requirement
131
- none: false
132
125
  requirements:
133
- - - ! '>='
126
+ - - '>'
134
127
  - !ruby/object:Gem::Version
135
- version: 1.3.6
128
+ version: 1.3.1
136
129
  requirements: []
137
130
  rubyforge_project:
138
- rubygems_version: 1.8.23
131
+ rubygems_version: 2.0.2
139
132
  signing_key:
140
- specification_version: 3
133
+ specification_version: 4
141
134
  summary: Money and currency exchange support library.
142
135
  test_files: []
143
- has_rdoc: