monetize 1.4.0 → 1.9.1

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: 7f96f9f99c2fc04ab625a2977f370eff77d33696
4
- data.tar.gz: 75817ce67a91ae35019f6ef3a3b290b937b64749
3
+ metadata.gz: 7c921047a6f291ae61ceb19db130de7b0288d8e2
4
+ data.tar.gz: f48eb20c8582b1453ef6114df30793f9367d934e
5
5
  SHA512:
6
- metadata.gz: 657c4f4be74370f9a8b2b1f4fcb91e60a013e9d2e01f39f95258a48c47710c5418767770af32ca61c19d52b0a94ccaa875fd3a4b7d8f21023ff7f4b036700c90
7
- data.tar.gz: 4cb6265937f209b0797cc4c0d2e78b4fa27a9f27f9f045cfac8d00812dcb2ccb86072672897b7fb36f7337dab52cbb62c3e58739b9cdcdc9ec32b73393bedd9a
6
+ metadata.gz: 9b4a49126c30cfd92968d6fed6cd43a806e5cda807f8dfd0c8956d434e0e3a3331191d9e228e5648c4d11157f01d3c3fcdb72f72f21e52f96002ab803b70265a
7
+ data.tar.gz: 571ec0ec170014d408f4ba0208a1b40f04cdf3436b2939e7d43b922cfe2ce3e981fb5a51a6dc79eab8d07ccad4ecfbc270548e15b4293428df87dbc0c912d277
@@ -1,8 +1,17 @@
1
+ sudo: false
1
2
  language: ruby
2
3
  rvm:
3
4
  - 1.9.3
4
5
  - 2.0.0
5
- - 2.1.2
6
+ - 2.1.10
7
+ - 2.2.10
8
+ - 2.3.7
9
+ - 2.4.4
10
+ - 2.5.1
11
+ - 2.6.0
12
+ - jruby-9.0.5.0
13
+ before_install:
14
+ - gem install bundler --version '~> 1.17'
6
15
  script: bundle exec rspec spec
7
16
  notifications:
8
17
  recipients:
@@ -1,21 +1,86 @@
1
1
  # Changelog
2
2
 
3
- ## 1.4.0
4
- - Required Forwardable on Collection to resolve NameError [\#44](https://github.com/RubyMoney/monetize/issues/44)
5
- - Add capability to parse currency amounts given with suffixes (K, M, B, and T)
3
+ ## 1.9.1
4
+ - Ruby 2.6 support
6
5
 
7
- ## 1.3.0
8
- - Add NilClass extension
9
- - Added correct parsing of Brazilian Real $R symbol
10
- - Add testing task for Brazilian Real parsing
11
- - Add Lira Sign (₤) as a symbol for GBP
6
+ ## 1.9.0
7
+ - Relax Money gem dependency to ~> 6.12
8
+ - Refactor `Monetize::Parser`
9
+ - Ruby 2.5 support
12
10
 
13
- ## 1.3.1
14
- - Updated Money version dependency to 6.6
11
+ ## 1.8.0
12
+ - Money version updated to 6.11.2
13
+ - Fix rounding problem in `.from_bigdecimal`
14
+
15
+ ## 1.7.0
16
+ - Add South Korean Won currency
17
+ - Money version updated to 6.9
18
+ - Coveralls version update to 0.8.20
19
+ - Add South Korean Won currency
20
+ - Improve conversion to Money from Hash
21
+
22
+ ## 1.6.0
23
+ - Ruby 2.4.0 support
24
+ - Money version updated to 6.8
15
25
 
16
- ## master
26
+ ## 1.5.0
27
+ - Fix issue where parsing a Money object resulted in a Money object with its currency set to `Money.default_currency`,
28
+ rather than the currency that it was sent in as.
29
+ - Add extra currencies:
30
+ - Azerbaijani manat
31
+ - Chinese yuan
32
+ - Czech koruna
33
+ - Hungarian forint
34
+ - Indian rupee
35
+ - Russian ruble
36
+ - Turkish Lira
37
+ - Ukrainian Hryvnia
38
+ - Swiss Frank
39
+ - Polish Zloty
40
+ - Kazakhstani Tenge
41
+ - Fix issue with losing precision on BigDecimal input
42
+ - Add Swedish krona
43
+ - Exclude ambiguous kr symbol from parsing
44
+ - Fix JPY parsing
45
+ - Subclass all errors to Monetize::Error
46
+ - Fix ruby 1.9.3 compatibility
47
+ - Suppress errors when using parse. Use `parse!` instead
48
+ - Strip currency symbol prefix when parsing input
49
+
50
+ ## 1.4.0
17
51
  - Fixed support for <code>Money.infinite_precision = true</code> in .to_money
18
52
  - Add Rubocop config to project
19
53
  - Reformat code to adapt to Rubocop guidelines
20
54
  - Add config setting to always enforce currency delimiters
21
55
  - Add rake console task
56
+ - Required Forwardable on Collection to resolve NameError [\#44](https://github.com/RubyMoney/monetize/issues/44)
57
+ - Add capability to parse currency amounts given with suffixes (K, M, B, and T)
58
+
59
+ ## 1.3.1
60
+ - Updated Money version dependency to 6.6
61
+
62
+ ## 1.3.0
63
+ - Add Lira Sign (₤) as a symbol for GBP
64
+
65
+ ## 1.2.0
66
+ - Add support for parsing Yen symbol
67
+ - Add `Monetize.parse_collection` and `Monetize::Collection` class for parsing multiple values
68
+ - Add parsing of C$ for Canadian Dollar
69
+ - Add NilClass extension
70
+ - Add Hash extension
71
+
72
+ ## 1.1.0
73
+ - Add :assume_from_symbol option to #parse
74
+ - Enable #parse to detect currency with signed amounts
75
+ - Updated Money version dependency to 6.5.0
76
+
77
+ ## 1.0.0
78
+ - Updated Money version dependency to 6.4.0
79
+
80
+ ## 0.4.1
81
+ - Updated Money version dependency to 6.2.1
82
+
83
+ ## 0.4.0
84
+ - Added correct parsing of Brazilian Real $R symbol
85
+ - Add testing task for Brazilian Real parsing
86
+ - Updated Money version dependency to 6.2.0
data/Gemfile CHANGED
@@ -1,5 +1,15 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'coveralls', require: false
3
+ gem 'coveralls', '>= 0.8.20', require: false
4
+
5
+ # JSON and I18n gem no longer supports ruby < 2.0.0
6
+ if defined?(JRUBY_VERSION)
7
+ gem 'json'
8
+ elsif RUBY_VERSION =~ /^1/
9
+ gem 'json', '~> 1.8.3'
10
+ gem 'tins', '~> 1.6.0'
11
+ gem 'term-ansicolor', '~> 1.3.0'
12
+ gem 'i18n', '~> 0.9'
13
+ end
4
14
 
5
15
  gemspec
data/README.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # Monetize
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/monetize.png)](http://badge.fury.io/rb/monetize)
4
- [![Build Status](https://travis-ci.org/RubyMoney/monetize.png?branch=master)](https://travis-ci.org/RubyMoney/monetize)
5
- [![Code Climate](https://codeclimate.com/github/RubyMoney/monetize.png)](https://codeclimate.com/github/RubyMoney/monetize)
6
- [![Coverage Status](https://coveralls.io/repos/RubyMoney/monetize/badge.png)](https://coveralls.io/r/RubyMoney/monetize)
7
- [![Dependency Status](https://gemnasium.com/RubyMoney/monetize.png)](https://gemnasium.com/RubyMoney/monetize)
8
- [![License](http://img.shields.io/license/MIT.png?color=green)](http://opensource.org/licenses/MIT)
3
+ [![Gem Version](https://badge.fury.io/rb/monetize.svg)](http://badge.fury.io/rb/monetize)
4
+ [![Build Status](https://travis-ci.org/RubyMoney/monetize.svg?branch=master)](https://travis-ci.org/RubyMoney/monetize)
5
+ [![Code Climate](https://codeclimate.com/github/RubyMoney/monetize.svg)](https://codeclimate.com/github/RubyMoney/monetize)
6
+ [![Coverage Status](https://coveralls.io/repos/RubyMoney/monetize/badge.svg)](https://coveralls.io/r/RubyMoney/monetize)
7
+ [![Dependency Status](https://gemnasium.com/RubyMoney/monetize.svg)](https://gemnasium.com/RubyMoney/monetize)
8
+ [![License](https://img.shields.io/badge/license-MIT-green.svg)](http://opensource.org/licenses/MIT)
9
9
 
10
10
  A library for converting various objects into `Money` objects.
11
11
 
@@ -33,6 +33,16 @@ Monetize.parse("GBP 100") == Money.new(100_00, "GBP")
33
33
  "100".to_money == Money.new(100_00, "USD")
34
34
  ```
35
35
 
36
+ `parse` will return `nil` if it is unable to parse the input. Use `parse!` instead if you want a `Monetize::Error` (or one of the subclasses) to be raised instead:
37
+
38
+ ```ruby
39
+ >> Monetize.parse('OMG 100')
40
+ => nil
41
+
42
+ >> Monetize.parse!('OMG 100')
43
+ Monetize::ParseError: Unknown currency 'omg'
44
+ ```
45
+
36
46
  Optionally, enable the ability to assume the currency from a passed symbol. Otherwise, currency symbols will be ignored, and USD used as the default currency:
37
47
 
38
48
  ```ruby
@@ -2,30 +2,12 @@
2
2
 
3
3
  require 'money'
4
4
  require 'monetize/core_extensions'
5
+ require 'monetize/errors'
5
6
  require 'monetize/version'
6
- require 'collection'
7
+ require 'monetize/parser'
8
+ require 'monetize/collection'
7
9
 
8
10
  module Monetize
9
- CURRENCY_SYMBOLS = {
10
- '$' => 'USD',
11
- '€' => 'EUR',
12
- '£' => 'GBP',
13
- '₤' => 'GBP',
14
- 'R$' => 'BRL',
15
- 'R' => 'ZAR',
16
- '¥' => 'JPY',
17
- 'C$' => 'CAD'
18
- }
19
-
20
- MULTIPLIER_SUFFIXES = {
21
- 'K' => 3,
22
- 'M' => 6,
23
- 'B' => 9,
24
- 'T' => 12
25
- }
26
- MULTIPLIER_SUFFIXES.default = 0
27
- MULTIPLIER_REGEXP = Regexp.new(format('^(.*?\d)(%s)\b([^\d]*)$', MULTIPLIER_SUFFIXES.keys.join('|')), 'i')
28
-
29
11
  # Class methods
30
12
  class << self
31
13
  # @attr_accessor [true, false] assume_from_symbol Use this to enable the
@@ -37,195 +19,54 @@ module Monetize
37
19
  # though, it will try to determine the correct separator by itself. Set this
38
20
  # to true to enforce the delimiters set in the currency all the time.
39
21
  attr_accessor :enforce_currency_delimiters
40
- end
41
-
42
- def self.parse(input, currency = Money.default_currency, options = {})
43
- input = input.to_s.strip
44
22
 
45
- computed_currency = if options.fetch(:assume_from_symbol) { assume_from_symbol }
46
- compute_currency(input)
47
- else
48
- input[/[A-Z]{2,3}/]
49
- end
50
-
51
- currency = computed_currency || currency || Money.default_currency
52
- currency = Money::Currency.wrap(currency)
53
-
54
- fractional = extract_cents(input, currency)
55
- Money.new(fractional, currency)
56
- end
57
-
58
- def self.parse_collection(input, currency = Money.default_currency, options = {})
59
- Collection.parse(input, currency, options)
60
- end
61
-
62
- def self.from_string(value, currency = Money.default_currency)
63
- value = BigDecimal.new(value.to_s)
64
- from_bigdecimal(value, currency)
65
- end
66
-
67
- def self.from_fixnum(value, currency = Money.default_currency)
68
- currency = Money::Currency.wrap(currency)
69
- value *= currency.subunit_to_unit
70
- Money.new(value, currency)
71
- end
72
-
73
- def self.from_float(value, currency = Money.default_currency)
74
- value = BigDecimal.new(value.to_s)
75
- from_bigdecimal(value, currency)
76
- end
77
-
78
- def self.from_bigdecimal(value, currency = Money.default_currency)
79
- currency = Money::Currency.wrap(currency)
80
- value *= currency.subunit_to_unit
81
- value = value.round unless Money.infinite_precision
82
- Money.new(value, currency)
83
- end
84
-
85
- def self.from_numeric(value, currency = Money.default_currency)
86
- case value
87
- when Fixnum
88
- from_fixnum(value, currency)
89
- when Numeric
90
- value = BigDecimal.new(value.to_s)
91
- from_bigdecimal(value, currency)
92
- else
93
- fail ArgumentError, "'value' should be a type of Numeric"
23
+ def parse(input, currency = Money.default_currency, options = {})
24
+ parse! input, currency, options
25
+ rescue Error
26
+ nil
94
27
  end
95
- end
96
-
97
- def self.extract_cents(input, currency = Money.default_currency)
98
- multiplier_exp, input = extract_multiplier(input)
99
-
100
- num = input.gsub(/[^\d.,'-]/, '')
101
-
102
- negative, num = extract_sign(num)
103
-
104
- num.chop! if num.match(/[\.|,]$/)
105
-
106
- major, minor = extract_major_minor(num, currency)
107
-
108
- cents = major.to_i * currency.subunit_to_unit
109
28
 
110
- cents, minor = apply_multiplier(multiplier_exp, cents, minor)
29
+ def parse!(input, currency = Money.default_currency, options = {})
30
+ return input if input.is_a?(Money)
31
+ return from_numeric(input, currency) if input.is_a?(Numeric)
111
32
 
112
- cents += set_minor_precision(minor, currency)
33
+ parser = Monetize::Parser.new(input, currency, options)
34
+ currency_from_input = Money::Currency.wrap(parser.parse_currency)
113
35
 
114
- apply_sign(negative, cents)
115
- end
116
-
117
- private
118
-
119
- def self.apply_multiplier(multiplier_exp, cents, minor)
120
- cents *= (10**multiplier_exp)
121
- minor = minor.to_s + ('0' * multiplier_exp)
122
- shift = minor[0...multiplier_exp].to_i * 100
123
- cents += shift
124
- minor = (minor[multiplier_exp..-1] || '')
125
- [cents, minor]
126
- end
127
-
128
- def self.apply_sign(negative, cents)
129
- negative ? cents * -1 : cents
130
- end
131
-
132
- def self.contains_currency_symbol?(amount)
133
- amount =~ currency_symbol_regex
134
- end
135
-
136
- def self.compute_currency(amount)
137
- if contains_currency_symbol?(amount)
138
- matches = amount.match(currency_symbol_regex)
139
- CURRENCY_SYMBOLS[matches[:symbol]]
140
- else
141
- amount[/[A-Z]{2,3}/]
36
+ Money.new(parser.parse_cents(currency_from_input), currency_from_input)
37
+ rescue Money::Currency::UnknownCurrency => e
38
+ fail ParseError, e.message
142
39
  end
143
- end
144
-
145
- def self.extract_major_minor(num, currency)
146
- used_delimiters = num.scan(/[^\d]/).uniq
147
40
 
148
- case used_delimiters.length
149
- when 0
150
- [num, 0]
151
- when 2
152
- thousands_separator, decimal_mark = used_delimiters
153
- split_major_minor(num.gsub(thousands_separator, ''), decimal_mark)
154
- when 1
155
- extract_major_minor_with_single_delimiter(num, currency, used_delimiters.first)
156
- else
157
- fail ArgumentError, 'Invalid currency amount'
41
+ def parse_collection(input, currency = Money.default_currency, options = {})
42
+ Collection.parse(input, currency, options)
158
43
  end
159
- end
160
44
 
161
- def self.extract_major_minor_with_single_delimiter(num, currency, delimiter)
162
- if delimiter == currency.decimal_mark
163
- split_major_minor(num, delimiter)
164
- elsif enforce_currency_delimiters and delimiter == currency.thousands_separator
165
- [num.gsub(delimiter, ''), 0]
166
- else
167
- extract_major_minor_with_tentative_delimiter(num, delimiter)
45
+ def from_string(value, currency = Money.default_currency)
46
+ value = BigDecimal(value.to_s)
47
+ Money.from_amount(value, currency)
168
48
  end
169
- end
170
-
171
- def self.extract_major_minor_with_tentative_delimiter(num, delimiter)
172
- if num.scan(delimiter).length > 1
173
- # Multiple matches; treat as thousands separator
174
- [num.gsub(delimiter, ''), '00']
175
- else
176
- possible_major, possible_minor = split_major_minor(num, delimiter)
177
49
 
178
- if possible_minor.length != 3 or possible_major.length > 3 or delimiter == '.'
179
- # Doesn't look like thousands separator
180
- [possible_major, possible_minor]
181
- else
182
- ["#{possible_major}#{possible_minor}", '00']
183
- end
50
+ def from_fixnum(value, currency = Money.default_currency)
51
+ Money.from_amount(value, currency)
184
52
  end
185
- end
53
+ alias_method :from_integer, :from_fixnum
186
54
 
187
- def self.extract_multiplier(input)
188
- if (matches = MULTIPLIER_REGEXP.match(input))
189
- multiplier_suffix = matches[2].upcase
190
- [MULTIPLIER_SUFFIXES[multiplier_suffix], "#{$1}#{$3}"]
191
- else
192
- [0, input]
55
+ def from_float(value, currency = Money.default_currency)
56
+ Money.from_amount(value, currency)
193
57
  end
194
- end
195
-
196
- def self.extract_sign(input)
197
- result = (input =~ /^-+(.*)$/ or input =~ /^(.*)-+$/) ? [true, $1] : [false, input]
198
- fail ArgumentError, 'Invalid currency amount (hyphen)' if result[1].include?('-')
199
- result
200
- end
201
58
 
202
- def self.regex_safe_symbols
203
- CURRENCY_SYMBOLS.keys.map { |key| Regexp.escape(key) }.join('|')
204
- end
205
-
206
- def self.set_minor_precision(minor, currency)
207
- if Money.infinite_precision
208
- (BigDecimal.new(minor) / (10**minor.size)) * currency.subunit_to_unit
209
- elsif minor.size < currency.decimal_places
210
- (minor + ('0' * currency.decimal_places))[0, currency.decimal_places].to_i
211
- elsif minor.size > currency.decimal_places
212
- if minor[currency.decimal_places, 1].to_i >= 5
213
- minor[0, currency.decimal_places].to_i + 1
214
- else
215
- minor[0, currency.decimal_places].to_i
216
- end
217
- else
218
- minor.to_i
59
+ def from_bigdecimal(value, currency = Money.default_currency)
60
+ Money.from_amount(value, currency)
219
61
  end
220
- end
221
62
 
222
- def self.split_major_minor(num, delimiter)
223
- major, minor = num.split(delimiter)
224
- minor = '00' unless minor
225
- [major, minor]
226
- end
63
+ def from_numeric(value, currency = Money.default_currency)
64
+ fail ArgumentError, "'value' should be a type of Numeric" unless value.is_a?(Numeric)
65
+ Money.from_amount(value, currency)
66
+ end
227
67
 
228
- def self.currency_symbol_regex
229
- /\A[\+|\-]?(?<symbol>#{regex_safe_symbols})/
68
+ def extract_cents(input, currency = Money.default_currency)
69
+ Monetize::Parser.new(input).parse_cents(currency)
70
+ end
230
71
  end
231
72
  end
@@ -1,6 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'monetize'
4
3
  require 'forwardable'
5
4
 
6
5
  module Monetize
@@ -2,6 +2,7 @@
2
2
 
3
3
  class Hash
4
4
  def to_money(currency = nil)
5
- Money.new(self[:cents], self[:currency] || currency || Money.default_currency)
5
+ hash_currency = self[:currency].is_a?(Hash) ? self[:currency][:iso_code] : self[:currency]
6
+ Money.new(self[:cents] || self[:fractional], hash_currency || currency || Money.default_currency)
6
7
  end
7
8
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  class String
4
4
  def to_money(currency = nil)
5
- Monetize.parse(self, currency)
5
+ Monetize.parse!(self, currency)
6
6
  end
7
7
 
8
8
  def to_currency
@@ -0,0 +1,6 @@
1
+ module Monetize
2
+ class Error < StandardError; end
3
+
4
+ class ParseError < Error; end
5
+ class ArgumentError < Error; end
6
+ end
@@ -0,0 +1,178 @@
1
+ # encoding: utf-8
2
+
3
+ module Monetize
4
+ class Parser
5
+ CURRENCY_SYMBOLS = {
6
+ '$' => 'USD',
7
+ '€' => 'EUR',
8
+ '£' => 'GBP',
9
+ '₤' => 'GBP',
10
+ 'R$' => 'BRL',
11
+ 'R' => 'ZAR',
12
+ '¥' => 'JPY',
13
+ 'C$' => 'CAD',
14
+ '₼' => 'AZN',
15
+ '元' => 'CNY',
16
+ 'Kč' => 'CZK',
17
+ 'Ft' => 'HUF',
18
+ '₹' => 'INR',
19
+ '₽' => 'RUB',
20
+ '₺' => 'TRY',
21
+ '₴' => 'UAH',
22
+ 'Fr' => 'CHF',
23
+ 'zł' => 'PLN',
24
+ '₸' => 'KZT',
25
+ "₩" => 'KRW',
26
+ }
27
+
28
+ MULTIPLIER_SUFFIXES = { 'K' => 3, 'M' => 6, 'B' => 9, 'T' => 12 }
29
+ MULTIPLIER_SUFFIXES.default = 0
30
+ MULTIPLIER_REGEXP = Regexp.new(format('^(.*?\d)(%s)\b([^\d]*)$', MULTIPLIER_SUFFIXES.keys.join('|')), 'i')
31
+
32
+ def initialize(input, fallback_currency = Money.default_currency, options = {})
33
+ @input = input.to_s.strip
34
+ @fallback_currency = fallback_currency
35
+ @options = options
36
+ end
37
+
38
+ def parse_cents(currency)
39
+ multiplier_exp, input = extract_multiplier
40
+
41
+ num = input.gsub(/(?:^#{currency.symbol}|[^\d.,'-]+)/, '')
42
+
43
+ negative, num = extract_sign(num)
44
+
45
+ num.chop! if num =~ /[\.|,]$/
46
+
47
+ major, minor = extract_major_minor(num, currency)
48
+
49
+ major, minor = apply_multiplier(multiplier_exp, major.to_i, minor)
50
+
51
+ cents = major.to_i * currency.subunit_to_unit
52
+
53
+ cents += set_minor_precision(minor, currency)
54
+
55
+ apply_sign(negative, cents)
56
+ end
57
+
58
+ def parse_currency
59
+ computed_currency = nil
60
+ computed_currency = compute_currency if assume_from_symbol?
61
+ computed_currency ||= input[/[A-Z]{2,3}/]
62
+
63
+ computed_currency || fallback_currency || Money.default_currency
64
+ end
65
+
66
+ private
67
+
68
+ attr_reader :input, :fallback_currency, :options
69
+
70
+ def assume_from_symbol?
71
+ options.fetch(:assume_from_symbol) { Monetize.assume_from_symbol }
72
+ end
73
+
74
+ def apply_multiplier(multiplier_exp, major, minor)
75
+ major *= 10**multiplier_exp
76
+ minor = minor.to_s + ('0' * multiplier_exp)
77
+ shift = minor[0...multiplier_exp].to_i
78
+ major += shift
79
+ minor = (minor[multiplier_exp..-1] || '')
80
+ [major, minor]
81
+ end
82
+
83
+ def apply_sign(negative, cents)
84
+ negative ? cents * -1 : cents
85
+ end
86
+
87
+ def compute_currency
88
+ matches = input.match(currency_symbol_regex)
89
+ CURRENCY_SYMBOLS[matches[:symbol]] if matches
90
+ end
91
+
92
+ def extract_major_minor(num, currency)
93
+ used_delimiters = num.scan(/[^\d]/).uniq
94
+
95
+ case used_delimiters.length
96
+ when 0
97
+ [num, 0]
98
+ when 2
99
+ thousands_separator, decimal_mark = used_delimiters
100
+ split_major_minor(num.gsub(thousands_separator, ''), decimal_mark)
101
+ when 1
102
+ extract_major_minor_with_single_delimiter(num, currency, used_delimiters.first)
103
+ else
104
+ fail ParseError, 'Invalid amount'
105
+ end
106
+ end
107
+
108
+ def extract_major_minor_with_single_delimiter(num, currency, delimiter)
109
+ if delimiter == currency.decimal_mark
110
+ split_major_minor(num, delimiter)
111
+ elsif Monetize.enforce_currency_delimiters && delimiter == currency.thousands_separator
112
+ [num.gsub(delimiter, ''), 0]
113
+ else
114
+ extract_major_minor_with_tentative_delimiter(num, delimiter)
115
+ end
116
+ end
117
+
118
+ def extract_major_minor_with_tentative_delimiter(num, delimiter)
119
+ if num.scan(delimiter).length > 1
120
+ # Multiple matches; treat as thousands separator
121
+ [num.gsub(delimiter, ''), '00']
122
+ else
123
+ possible_major, possible_minor = split_major_minor(num, delimiter)
124
+
125
+ if possible_minor.length != 3 || possible_major.length > 3 || delimiter == '.'
126
+ # Doesn't look like thousands separator
127
+ [possible_major, possible_minor]
128
+ else
129
+ ["#{possible_major}#{possible_minor}", '00']
130
+ end
131
+ end
132
+ end
133
+
134
+ def extract_multiplier
135
+ if (matches = MULTIPLIER_REGEXP.match(input))
136
+ multiplier_suffix = matches[2].upcase
137
+ [MULTIPLIER_SUFFIXES[multiplier_suffix], "#{$1}#{$3}"]
138
+ else
139
+ [0, input]
140
+ end
141
+ end
142
+
143
+ def extract_sign(input)
144
+ result = (input =~ /^-+(.*)$/ || input =~ /^(.*)-+$/) ? [true, $1] : [false, input]
145
+ fail ParseError, 'Invalid amount (hyphen)' if result[1].include?('-')
146
+ result
147
+ end
148
+
149
+ def regex_safe_symbols
150
+ CURRENCY_SYMBOLS.keys.map { |key| Regexp.escape(key) }.join('|')
151
+ end
152
+
153
+ def set_minor_precision(minor, currency)
154
+ if Money.infinite_precision
155
+ (BigDecimal(minor) / (10**minor.size)) * currency.subunit_to_unit
156
+ elsif minor.size < currency.decimal_places
157
+ (minor + ('0' * currency.decimal_places))[0, currency.decimal_places].to_i
158
+ elsif minor.size > currency.decimal_places
159
+ if minor[currency.decimal_places, 1].to_i >= 5
160
+ minor[0, currency.decimal_places].to_i + 1
161
+ else
162
+ minor[0, currency.decimal_places].to_i
163
+ end
164
+ else
165
+ minor.to_i
166
+ end
167
+ end
168
+
169
+ def split_major_minor(num, delimiter)
170
+ major, minor = num.split(delimiter)
171
+ [major, minor || '00']
172
+ end
173
+
174
+ def currency_symbol_regex
175
+ /\A[\+|\-]?(?<symbol>#{regex_safe_symbols})/
176
+ end
177
+ end
178
+ end
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Monetize
4
- VERSION = '1.4.0'
4
+ VERSION = '1.9.1'
5
5
  end
@@ -19,9 +19,15 @@ Gem::Specification.new do |spec|
19
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
20
  spec.require_paths = ['lib']
21
21
 
22
- spec.add_dependency 'money', '~> 6.7'
22
+ spec.add_dependency 'money', '~> 6.12'
23
23
 
24
- spec.add_development_dependency 'bundler', '~> 1.3'
25
- spec.add_development_dependency 'rake'
26
- spec.add_development_dependency 'rspec', '~> 3.0.0.beta1'
24
+ spec.add_development_dependency 'bundler'
25
+ spec.add_development_dependency 'rake', '~> 10.2'
26
+ spec.add_development_dependency 'rspec', '~> 3.0'
27
+
28
+ if spec.respond_to?(:metadata)
29
+ spec.metadata['changelog_uri'] = 'https://github.com/RubyMoney/monetize/blob/master/CHANGELOG.md'
30
+ spec.metadata['source_code_uri'] = 'https://github.com/RubyMoney/monetize/'
31
+ spec.metadata['bug_tracker_uri'] = 'https://github.com/RubyMoney/monetize/issues'
32
+ end
27
33
  end
@@ -31,7 +31,7 @@ describe Monetize, 'core extensions' do
31
31
  expect(money.cents).to eq 100_37
32
32
  expect(money.currency).to eq Money.default_currency
33
33
 
34
- money = BigDecimal.new('1234').to_money
34
+ money = BigDecimal('1234').to_money
35
35
  expect(money.cents).to eq 1_234_00
36
36
  expect(money.currency).to eq Money.default_currency
37
37
  end
@@ -182,6 +182,14 @@ describe Monetize, 'core extensions' do
182
182
  end
183
183
  end
184
184
 
185
+ context 'when currency argument is a hash' do
186
+ subject(:hash) { {cents: 100, currency: {iso_code: 'EUR'}} }
187
+
188
+ it 'converts Hash to Money using iso_code from currency hash' do
189
+ expect(hash.to_money).to eq(Money.new(100, 'EUR'))
190
+ end
191
+ end
192
+
185
193
  context 'when no currency is passed' do
186
194
  subject(:hash) { {cents: 123} }
187
195
 
@@ -191,6 +199,14 @@ describe Monetize, 'core extensions' do
191
199
  expect(hash.to_money('USD')).to eq(Money.new(123, 'USD'))
192
200
  end
193
201
  end
202
+
203
+ context "when key name is 'fractional'" do
204
+ subject(:hash) { {fractional: 100} }
205
+
206
+ it 'converts Hash to Money, interpreting fractional as cents' do
207
+ expect(hash.to_money).to eq(Money.new(100, 'USD'))
208
+ end
209
+ end
194
210
  end
195
211
  end
196
212
 
@@ -56,76 +56,69 @@ describe Monetize do
56
56
  Monetize.assume_from_symbol = false
57
57
  end
58
58
 
59
- it 'parses formatted inputs with Euros passed as a symbol' do
60
- expect(Monetize.parse('€5.95')).to eq Money.new(595, 'EUR')
61
- end
62
-
63
- it 'parses formatted inputs with Euros passed as a symbol with surrounding space' do
64
- expect(Monetize.parse(' €5.95 ')).to eq Money.new(595, 'EUR')
65
- end
66
-
67
- it 'parses formatted inputs with British Pounds Sterling passed as a symbol' do
68
- expect(Monetize.parse('£9.99')).to eq Money.new(999, 'GBP')
69
- end
70
-
71
- it 'parses formatted inputs with British Pounds Sterling passed as a lira sign symbol' do
72
- expect(Monetize.parse('₤9.99')).to eq Money.new(999, 'GBP')
73
- end
74
-
75
- it 'parses formatted inputs with South African Rand passed as a symbol' do
76
- expect(Monetize.parse('R9.99')).to eq Money.new(999, 'ZAR')
77
- end
78
-
79
- it 'parses formatted inputs with Brazilian real passed as a symbol' do
80
- expect(Monetize.parse('R$R9.99')).to eq Money.new(999, 'BRL')
81
- end
82
-
83
- it 'parses formatted inputs with Japanese Yen passed as a symbol' do
84
- expect(Monetize.parse('¥999')).to eq Money.new(999, 'JPY')
85
- end
86
-
87
- it 'parses formatted inputs with Canadian Dollar passed as a symbol' do
88
- expect(Monetize.parse('C$9.99')).to eq Money.new(999, 'CAD')
59
+ Monetize::Parser::CURRENCY_SYMBOLS.each_pair do |symbol, iso_code|
60
+ context iso_code do
61
+ let(:currency) { Money::Currency.find(iso_code) }
62
+ let(:amount) { 5_95 }
63
+ let(:amount_in_units) { amount.to_f / currency.subunit_to_unit }
64
+
65
+ it 'ensures correct amount calculations for test' do
66
+ expect(amount_in_units * currency.subunit_to_unit).to eq(amount)
67
+ end
68
+
69
+ it "parses formatted inputs with #{iso_code} passed as a symbol" do
70
+ expect(Monetize.parse("#{symbol}#{amount_in_units}")).to eq Money.new(amount, iso_code)
71
+ end
72
+
73
+ context 'prefix' do
74
+ it 'parses formatted inputs with plus sign and currency as a symbol' do
75
+ expect(Monetize.parse("+#{symbol}#{amount_in_units}")).to eq Money.new(amount, iso_code)
76
+ end
77
+
78
+ it 'parses formatted inputs with minus sign and currency as a symbol' do
79
+ expect(Monetize.parse("-#{symbol}#{amount_in_units}")).to eq Money.new(-amount, iso_code)
80
+ end
81
+ end
82
+
83
+ context 'postfix' do
84
+ it 'parses formatted inputs with currency symbol and postfix minus sign' do
85
+ expect(Monetize.parse("#{symbol}#{amount_in_units}-")).to eq Money.new(-amount, iso_code)
86
+ end
87
+
88
+ it 'parses formatted inputs with currency symbol and postfix plus sign' do
89
+ expect(Monetize.parse("#{symbol}#{amount_in_units}+")).to eq Money.new(amount, iso_code)
90
+ end
91
+ end
92
+
93
+ context 'amount suffixes' do
94
+ it 'parses formatted inputs with amounts given with suffixes' do
95
+ expect(Monetize.parse("#{symbol}1.26K")).to eq Money.new(1_260 * currency.subunit_to_unit, iso_code)
96
+ expect(Monetize.parse("#{symbol}126.36M")).to eq Money.new(126_360_000 * currency.subunit_to_unit, iso_code)
97
+ expect(Monetize.parse("#{symbol}.45B")).to eq Money.new(450_000_000 * currency.subunit_to_unit, iso_code)
98
+ expect(Monetize.parse("-#{symbol}2.45B")).to eq Money.new(-2_450_000_000 * currency.subunit_to_unit, iso_code)
99
+ expect(Monetize.parse("#{symbol}1.65T")).to eq Money.new(1_650_000_000_000 * currency.subunit_to_unit, iso_code)
100
+ end
101
+ end
102
+
103
+ it 'parses formatted inputs with symbol and surrounding spaces' do
104
+ expect(Monetize.parse(" #{symbol}#{amount_in_units} ")).to eq Money.new(amount, iso_code)
105
+ end
106
+
107
+ it 'parses formatted inputs without currency detection when overridden' do
108
+ expect(Monetize.parse("#{symbol}5.95", nil, assume_from_symbol: false)).to eq Money.new(amount, 'USD')
109
+ end
110
+ end
89
111
  end
90
112
 
91
113
  it 'should assume default currency if not a recognised symbol' do
92
114
  expect(Monetize.parse('L9.99')).to eq Money.new(999, 'USD')
93
115
  end
94
116
 
95
- it 'parses formatted inputs without currency detection when overridden' do
96
- expect(Monetize.parse('£9.99', nil, assume_from_symbol: false)).to eq Money.new(999, 'USD')
97
- end
98
-
99
- it 'parses formatted inputs with minus sign and currency symbol' do
100
- expect(Monetize.parse('-€9.99')).to eq Money.new(-999, 'EUR')
101
- expect(Monetize.parse('-£9.99')).to eq Money.new(-999, 'GBP')
102
- expect(Monetize.parse('-R$R9.99')).to eq Money.new(-999, 'BRL')
103
- expect(Monetize.parse('-¥999')).to eq Money.new(-999, 'JPY')
104
- expect(Monetize.parse('-C$9.99')).to eq Money.new(-999, 'CAD')
105
- end
106
-
107
- it 'parses formatted inputs with plus and GBP passed as symbol' do
108
- expect(Monetize.parse('+€9.99')).to eq Money.new(999, 'EUR')
109
- expect(Monetize.parse('+£9.99')).to eq Money.new(999, 'GBP')
110
- expect(Monetize.parse('+R$R9.99')).to eq Money.new(999, 'BRL')
111
- expect(Monetize.parse('+¥999')).to eq Money.new(999, 'JPY')
112
- expect(Monetize.parse('+C$9.99')).to eq Money.new(999, 'CAD')
113
- end
114
-
115
- it 'parses formatted inputs with currency symbol and postfix minus sign' do
116
- expect(Monetize.parse('€9.99-')).to eq Money.new(-999, 'EUR')
117
- end
118
-
119
- it 'parses formatted inputs with currency symbol and postfix plus sign' do
120
- expect(Monetize.parse('€9.99+')).to eq Money.new(999, 'EUR')
121
- end
122
-
123
- it 'parses formatted inputs with amounts given with suffixes' do
124
- expect(Monetize.parse('$1.26K')).to eq Money.new(1_260_00, 'USD')
125
- expect(Monetize.parse('$126.36M')).to eq Money.new(126_360_000_00, 'USD')
126
- expect(Monetize.parse('€.45B')).to eq Money.new(450_000_000_00, 'EUR')
127
- expect(Monetize.parse('-$2.45B')).to eq Money.new(-2_450_000_000_00, 'USD')
128
- expect(Monetize.parse('€1.65T')).to eq Money.new(1_650_000_000_000_00, 'EUR')
117
+ context 'negatives' do
118
+ it 'ignores the ambiguous kr symbol' do
119
+ # Could mean either of DKK, EEK, ISK, NOK, SEK
120
+ expect(Monetize.parse('kr9.99')).to eq Money.new(999, 'USD')
121
+ end
129
122
  end
130
123
  end
131
124
 
@@ -158,6 +151,18 @@ describe Monetize do
158
151
  it 'should opt out by default' do
159
152
  expect(Monetize.assume_from_symbol).to be_falsy
160
153
  end
154
+
155
+ context 'ISO code' do
156
+ it 'parses currency given as ISO code' do
157
+ expect('20.00 USD'.to_money).to eq Money.new(20_00, 'USD')
158
+ expect('20.00 EUR'.to_money).to eq Money.new(20_00, 'EUR')
159
+ expect('20.00 GBP'.to_money).to eq Money.new(20_00, 'GBP')
160
+ end
161
+
162
+ it 'raises an error if currency code is invalid' do
163
+ expect { '20.00 OMG'.to_money }.to raise_error Monetize::ParseError
164
+ end
165
+ end
161
166
  end
162
167
 
163
168
  it 'parses USD-formatted inputs under $10' do
@@ -177,10 +182,16 @@ describe Monetize do
177
182
  expect(Monetize.parse('1,111,234,567.89')).to eq Money.new(1_111_234_567_89, 'USD')
178
183
  end
179
184
 
180
- it 'does not return a price if there is a price range' do
181
- expect { Monetize.parse('$5.95-10.95') }.to raise_error ArgumentError
182
- expect { Monetize.parse('$5.95 - 10.95') }.to raise_error ArgumentError
183
- expect { Monetize.parse('$5.95 - $10.95') }.to raise_error ArgumentError
185
+ it 'parses DKK-formatted inputs' do
186
+ expect(Monetize.parse('kr.123,45', 'DKK')).to eq Money.new(123_45, 'DKK')
187
+ expect(Monetize.parse('kr.123.45', 'DKK')).to eq Money.new(123_45, 'DKK')
188
+ expect(Monetize.parse('kr.45k', 'DKK')).to eq Money.new(45_000_00, 'DKK')
189
+ end
190
+
191
+ it 'returns nil if input is a price range' do
192
+ expect(Monetize.parse('$5.95-10.95')).to be_nil
193
+ expect(Monetize.parse('$5.95 - 10.95')).to be_nil
194
+ expect(Monetize.parse('$5.95 - $10.95')).to be_nil
184
195
  end
185
196
 
186
197
  it 'does not return a price for completely invalid input' do
@@ -197,8 +208,16 @@ describe Monetize do
197
208
  expect(Monetize.parse('$5.95-')).to eq five_ninety_five
198
209
  end
199
210
 
200
- it 'raises ArgumentError when unable to detect polarity' do
201
- expect { Monetize.parse('-$5.95-') }.to raise_error ArgumentError
211
+ it 'returns nil when unable to detect polarity' do
212
+ expect(Monetize.parse('-$5.95-')).to be_nil
213
+ end
214
+
215
+ it 'returns nil when more than 2 digit separators are used' do
216
+ expect(Monetize.parse("123.34,56'89 EUR")).to be_nil
217
+ end
218
+
219
+ it 'parses correctly strings with repeated digit separator' do
220
+ expect(Monetize.parse('19.12.89', 'EUR')).to eq Money.new(191_289_00, 'EUR')
202
221
  end
203
222
 
204
223
  it 'parses correctly strings with exactly 3 decimal digits' do
@@ -210,6 +229,32 @@ describe Monetize do
210
229
  Monetize.enforce_currency_delimiters = false
211
230
  end
212
231
 
232
+ context 'Money object attempting to be parsed' do
233
+ let(:money) { Money.new(595, 'GBP') }
234
+
235
+ it 'returns the original Money object' do
236
+ expect(Monetize.parse(money)).to eq money
237
+ expect(Monetize.parse(money).currency).to eq 'GBP'
238
+ expect(Monetize.parse(money).cents).to eq 595
239
+ end
240
+ end
241
+
242
+ context 'parsing an instance of Numeric class' do
243
+ let(:integer) { 10 }
244
+ let(:float) { 10.0 }
245
+ let(:big_decimal) { BigDecimal('10') }
246
+
247
+ [:integer, :float, :big_decimal].each do |type|
248
+ it "returns a new Money object based on the #{type} input" do
249
+ money = Monetize.parse(send(type), 'USD')
250
+
251
+ expect(money).to be_instance_of(Money)
252
+ expect(money.currency).to eq('USD')
253
+ expect(money.cents).to eq(10_00)
254
+ end
255
+ end
256
+ end
257
+
213
258
  context 'custom currencies with 4 decimal places' do
214
259
  before :each do
215
260
  Money::Currency.register(JSON.parse(bar, symbolize_names: true))
@@ -265,6 +310,18 @@ describe Monetize do
265
310
  end
266
311
  end
267
312
 
313
+ describe '.parse!' do
314
+ it 'does not return a price if there is a price range' do
315
+ expect { Monetize.parse!('$5.95-10.95') }.to raise_error Monetize::ParseError
316
+ expect { Monetize.parse!('$5.95 - 10.95') }.to raise_error Monetize::ParseError
317
+ expect { Monetize.parse!('$5.95 - $10.95') }.to raise_error Monetize::ParseError
318
+ end
319
+
320
+ it 'raises ArgumentError when unable to detect polarity' do
321
+ expect { Monetize.parse!('-$5.95-') }.to raise_error Monetize::ParseError
322
+ end
323
+ end
324
+
268
325
  describe '.parse_collection' do
269
326
  it 'parses into a Money::Collection' do
270
327
  expect(Monetize.parse_collection('$7')).to be_a Monetize::Collection
@@ -287,6 +344,10 @@ describe Monetize do
287
344
  expect(collection.first).to eq Monetize.parse('$4')
288
345
  expect(collection.last).to eq Monetize.parse('$10')
289
346
  end
347
+
348
+ it 'raises an error if argument is invalid' do
349
+ expect { Monetize.parse_collection(nil) }.to raise_error Monetize::ArgumentError
350
+ end
290
351
  end
291
352
 
292
353
  describe '.from_string' do
@@ -337,6 +398,10 @@ describe Monetize do
337
398
  m = Monetize.from_fixnum(1, 'EUR')
338
399
  expect(m.currency).to eq Money::Currency.wrap('EUR')
339
400
  end
401
+
402
+ it 'is aliased as from_integer' do
403
+ expect(Monetize.from_integer(1)).to eq(Monetize.from_fixnum(1))
404
+ end
340
405
  end
341
406
 
342
407
  describe '.from_float' do
@@ -366,25 +431,31 @@ describe Monetize do
366
431
 
367
432
  describe '.from_bigdecimal' do
368
433
  it 'converts given amount to cents' do
369
- expect(Monetize.from_bigdecimal(BigDecimal.new('1'))).to eq Money.new(1_00)
370
- expect(Monetize.from_bigdecimal(BigDecimal.new('1'))).to eq Money.new(1_00, 'USD')
371
- expect(Monetize.from_bigdecimal(BigDecimal.new('1'), 'EUR')).to eq Money.new(1_00, 'EUR')
434
+ expect(Monetize.from_bigdecimal(BigDecimal('1'))).to eq Money.new(1_00)
435
+ expect(Monetize.from_bigdecimal(BigDecimal('1'))).to eq Money.new(1_00, 'USD')
436
+ expect(Monetize.from_bigdecimal(BigDecimal('1'), 'EUR')).to eq Money.new(1_00, 'EUR')
372
437
  end
373
438
 
374
439
  it 'respects :subunit_to_unit currency property' do
375
- expect(Monetize.from_bigdecimal(BigDecimal.new('1'), 'USD')).to eq Money.new(1_00, 'USD')
376
- expect(Monetize.from_bigdecimal(BigDecimal.new('1'), 'TND')).to eq Money.new(1_000, 'TND')
377
- expect(Monetize.from_bigdecimal(BigDecimal.new('1'), 'JPY')).to eq Money.new(1, 'JPY')
440
+ expect(Monetize.from_bigdecimal(BigDecimal('1'), 'USD')).to eq Money.new(1_00, 'USD')
441
+ expect(Monetize.from_bigdecimal(BigDecimal('1'), 'TND')).to eq Money.new(1_000, 'TND')
442
+ expect(Monetize.from_bigdecimal(BigDecimal('1'), 'JPY')).to eq Money.new(1, 'JPY')
443
+ end
444
+
445
+ it 'respects rounding mode when rounding amount to the nearest cent' do
446
+ amount = BigDecimal('1.005')
447
+
448
+ expect(Monetize.from_bigdecimal(amount, 'USD')).to eq Money.from_amount(amount, 'USD')
378
449
  end
379
450
 
380
451
  it 'accepts a currency options' do
381
- m = Monetize.from_bigdecimal(BigDecimal.new('1'))
452
+ m = Monetize.from_bigdecimal(BigDecimal('1'))
382
453
  expect(m.currency).to eq Money.default_currency
383
454
 
384
- m = Monetize.from_bigdecimal(BigDecimal.new('1'), Money::Currency.wrap('EUR'))
455
+ m = Monetize.from_bigdecimal(BigDecimal('1'), Money::Currency.wrap('EUR'))
385
456
  expect(m.currency).to eq Money::Currency.wrap('EUR')
386
457
 
387
- m = Monetize.from_bigdecimal(BigDecimal.new('1'), 'EUR')
458
+ m = Monetize.from_bigdecimal(BigDecimal('1'), 'EUR')
388
459
  expect(m.currency).to eq Money::Currency.wrap('EUR')
389
460
  end
390
461
 
@@ -398,11 +469,11 @@ describe Monetize do
398
469
  end
399
470
 
400
471
  it 'keeps precision' do
401
- expect(Monetize.from_bigdecimal(BigDecimal.new('1'))).to eq Money.new(100)
402
- expect(Monetize.from_bigdecimal(BigDecimal.new('1.23456'))).to eq Money.new(123.456)
403
- expect(Monetize.from_bigdecimal(BigDecimal.new('-1.23456'))).to eq Money.new(-123.456)
404
- expect(Monetize.from_bigdecimal(BigDecimal.new('1.23456'))).to eq Money.new(123.456, 'USD')
405
- expect(Monetize.from_bigdecimal(BigDecimal.new('1.23456'), 'EUR')).to eq Money.new(123.456, 'EUR')
472
+ expect(Monetize.from_bigdecimal(BigDecimal('1'))).to eq Money.new(100)
473
+ expect(Monetize.from_bigdecimal(BigDecimal('1.23456'))).to eq Money.new(123.456)
474
+ expect(Monetize.from_bigdecimal(BigDecimal('-1.23456'))).to eq Money.new(-123.456)
475
+ expect(Monetize.from_bigdecimal(BigDecimal('1.23456'))).to eq Money.new(123.456, 'USD')
476
+ expect(Monetize.from_bigdecimal(BigDecimal('1.23456'), 'EUR')).to eq Money.new(123.456, 'EUR')
406
477
 
407
478
  expect('1'.to_money).to eq Money.new(100)
408
479
  expect('1.23456'.to_money).to eq Money.new(123.456)
@@ -417,19 +488,11 @@ describe Monetize do
417
488
  it 'converts given amount to cents' do
418
489
  expect(Monetize.from_numeric(1)).to eq Money.new(1_00)
419
490
  expect(Monetize.from_numeric(1.0)).to eq Money.new(1_00)
420
- expect(Monetize.from_numeric(BigDecimal.new('1'))).to eq Money.new(1_00)
491
+ expect(Monetize.from_numeric(BigDecimal('1'))).to eq Money.new(1_00)
421
492
  end
422
493
 
423
494
  it 'raises ArgumentError with unsupported argument' do
424
- expect { Monetize.from_numeric('100') }.to raise_error(ArgumentError)
425
- end
426
-
427
- it 'optimizes workload' do
428
- expect(Monetize).to receive(:from_fixnum).with(1, 'USD').and_return(Money.new(1_00, 'USD'))
429
- expect(Monetize.from_numeric(1, 'USD')).to eq Money.new(1_00, 'USD')
430
- expect(Monetize).to receive(:from_bigdecimal).with(BigDecimal.new('1.0'), 'USD').
431
- and_return(Money.new(1_00, 'USD'))
432
- expect(Monetize.from_numeric(1.0, 'USD')).to eq Money.new(1_00, 'USD')
495
+ expect { Monetize.from_numeric('100') }.to raise_error(Monetize::ArgumentError)
433
496
  end
434
497
 
435
498
  it 'respects :subunit_to_unit currency property' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: monetize
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shane Emmons
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-15 00:00:00.000000000 Z
11
+ date: 2019-02-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: money
@@ -16,56 +16,56 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '6.7'
19
+ version: '6.12'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '6.7'
26
+ version: '6.12'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '1.3'
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '1.3'
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: '10.2'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: '10.2'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 3.0.0.beta1
61
+ version: '3.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 3.0.0.beta1
68
+ version: '3.0'
69
69
  description: A library for converting various objects into `Money` objects.
70
70
  email:
71
71
  - shane@emmons.io
@@ -83,14 +83,16 @@ files:
83
83
  - LICENSE.txt
84
84
  - README.md
85
85
  - Rakefile
86
- - lib/collection.rb
87
86
  - lib/monetize.rb
87
+ - lib/monetize/collection.rb
88
88
  - lib/monetize/core_extensions.rb
89
89
  - lib/monetize/core_extensions/hash.rb
90
90
  - lib/monetize/core_extensions/nil_class.rb
91
91
  - lib/monetize/core_extensions/numeric.rb
92
92
  - lib/monetize/core_extensions/string.rb
93
93
  - lib/monetize/core_extensions/symbol.rb
94
+ - lib/monetize/errors.rb
95
+ - lib/monetize/parser.rb
94
96
  - lib/monetize/version.rb
95
97
  - monetize.gemspec
96
98
  - spec/core_extensions_spec.rb
@@ -99,7 +101,10 @@ files:
99
101
  homepage: https://github.com/RubyMoney/monetize
100
102
  licenses:
101
103
  - MIT
102
- metadata: {}
104
+ metadata:
105
+ changelog_uri: https://github.com/RubyMoney/monetize/blob/master/CHANGELOG.md
106
+ source_code_uri: https://github.com/RubyMoney/monetize/
107
+ bug_tracker_uri: https://github.com/RubyMoney/monetize/issues
103
108
  post_install_message:
104
109
  rdoc_options: []
105
110
  require_paths:
@@ -116,7 +121,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
121
  version: '0'
117
122
  requirements: []
118
123
  rubyforge_project:
119
- rubygems_version: 2.4.5.1
124
+ rubygems_version: 2.6.8
120
125
  signing_key:
121
126
  specification_version: 4
122
127
  summary: A library for converting various objects into `Money` objects.
@@ -124,4 +129,3 @@ test_files:
124
129
  - spec/core_extensions_spec.rb
125
130
  - spec/monetize_spec.rb
126
131
  - spec/spec_helper.rb
127
- has_rdoc: