monetize 1.4.0 → 1.9.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 7f96f9f99c2fc04ab625a2977f370eff77d33696
4
- data.tar.gz: 75817ce67a91ae35019f6ef3a3b290b937b64749
2
+ SHA256:
3
+ metadata.gz: 6268692fea7908fbc268790bf98cca9795df28eed380b07d2683eed6f5dad4d1
4
+ data.tar.gz: 8d795add425b915dc88ecf910505af69b7c1f340ae412083e4c230f0622c2e27
5
5
  SHA512:
6
- metadata.gz: 657c4f4be74370f9a8b2b1f4fcb91e60a013e9d2e01f39f95258a48c47710c5418767770af32ca61c19d52b0a94ccaa875fd3a4b7d8f21023ff7f4b036700c90
7
- data.tar.gz: 4cb6265937f209b0797cc4c0d2e78b4fa27a9f27f9f045cfac8d00812dcb2ccb86072672897b7fb36f7337dab52cbb62c3e58739b9cdcdc9ec32b73393bedd9a
6
+ metadata.gz: e4291ebf0a43a4bea5a2973186b1dca2d9d9fa08729acb956073efb2628d6898620f5eb1110ade3bba5dbac313894babd4ab59c0d1db92b8cb8e041974a0d402
7
+ data.tar.gz: 06d080183a460c5777b9f7443655bcb00d214ee18a6294f0838a3ac4bfec95715ab1ad5704001d286a6bc1ed0966a4a031942bd946ef9d249372ea527a120785
@@ -1,8 +1,20 @@
1
- language: ruby
1
+ sudo: false
2
+ language:
3
+ - ruby
4
+ - java
2
5
  rvm:
3
6
  - 1.9.3
4
7
  - 2.0.0
5
- - 2.1.2
8
+ - 2.1.10
9
+ - 2.2.10
10
+ - 2.3.8
11
+ - 2.4.6
12
+ - 2.5.5
13
+ - 2.6.3
14
+ - jruby-9.0.5.0
15
+ jdk: openjdk8
16
+ before_install:
17
+ - gem install bundler --version '~> 1.17'
6
18
  script: bundle exec rspec spec
7
19
  notifications:
8
20
  recipients:
@@ -1,21 +1,96 @@
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.4
4
+ - Fix symbol parsing that are surrounded by other characters
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.3
7
+ - Fix input parsing when currency symbol after the amount
12
8
 
13
- ## 1.3.1
14
- - Updated Money version dependency to 6.6
9
+ ## 1.9.2
10
+ - Respect Money.rounding_mode when parsing strings
11
+ - Deprecate Monetize.extract_cents
12
+
13
+ ## 1.9.1
14
+ - Ruby 2.6 support
15
+
16
+ ## 1.9.0
17
+ - Relax Money gem dependency to ~> 6.12
18
+ - Refactor `Monetize::Parser`
19
+ - Ruby 2.5 support
20
+
21
+ ## 1.8.0
22
+ - Money version updated to 6.11.2
23
+ - Fix rounding problem in `.from_bigdecimal`
15
24
 
16
- ## master
25
+ ## 1.7.0
26
+ - Add South Korean Won currency
27
+ - Money version updated to 6.9
28
+ - Coveralls version update to 0.8.20
29
+ - Add South Korean Won currency
30
+ - Improve conversion to Money from Hash
31
+
32
+ ## 1.6.0
33
+ - Ruby 2.4.0 support
34
+ - Money version updated to 6.8
35
+
36
+ ## 1.5.0
37
+ - Fix issue where parsing a Money object resulted in a Money object with its currency set to `Money.default_currency`,
38
+ rather than the currency that it was sent in as.
39
+ - Add extra currencies:
40
+ - Azerbaijani manat
41
+ - Chinese yuan
42
+ - Czech koruna
43
+ - Hungarian forint
44
+ - Indian rupee
45
+ - Russian ruble
46
+ - Turkish Lira
47
+ - Ukrainian Hryvnia
48
+ - Swiss Frank
49
+ - Polish Zloty
50
+ - Kazakhstani Tenge
51
+ - Fix issue with losing precision on BigDecimal input
52
+ - Add Swedish krona
53
+ - Exclude ambiguous kr symbol from parsing
54
+ - Fix JPY parsing
55
+ - Subclass all errors to Monetize::Error
56
+ - Fix ruby 1.9.3 compatibility
57
+ - Suppress errors when using parse. Use `parse!` instead
58
+ - Strip currency symbol prefix when parsing input
59
+
60
+ ## 1.4.0
17
61
  - Fixed support for <code>Money.infinite_precision = true</code> in .to_money
18
62
  - Add Rubocop config to project
19
63
  - Reformat code to adapt to Rubocop guidelines
20
64
  - Add config setting to always enforce currency delimiters
21
65
  - Add rake console task
66
+ - Required Forwardable on Collection to resolve NameError [\#44](https://github.com/RubyMoney/monetize/issues/44)
67
+ - Add capability to parse currency amounts given with suffixes (K, M, B, and T)
68
+
69
+ ## 1.3.1
70
+ - Updated Money version dependency to 6.6
71
+
72
+ ## 1.3.0
73
+ - Add Lira Sign (₤) as a symbol for GBP
74
+
75
+ ## 1.2.0
76
+ - Add support for parsing Yen symbol
77
+ - Add `Monetize.parse_collection` and `Monetize::Collection` class for parsing multiple values
78
+ - Add parsing of C$ for Canadian Dollar
79
+ - Add NilClass extension
80
+ - Add Hash extension
81
+
82
+ ## 1.1.0
83
+ - Add :assume_from_symbol option to #parse
84
+ - Enable #parse to detect currency with signed amounts
85
+ - Updated Money version dependency to 6.5.0
86
+
87
+ ## 1.0.0
88
+ - Updated Money version dependency to 6.4.0
89
+
90
+ ## 0.4.1
91
+ - Updated Money version dependency to 6.2.1
92
+
93
+ ## 0.4.0
94
+ - Added correct parsing of Brazilian Real $R symbol
95
+ - Add testing task for Brazilian Real parsing
96
+ - 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,57 @@ 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
-
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
22
 
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
28
 
108
- cents = major.to_i * currency.subunit_to_unit
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)
109
32
 
110
- cents, minor = apply_multiplier(multiplier_exp, cents, minor)
33
+ parser = Monetize::Parser.new(input, currency, options)
34
+ amount, currency = parser.parse
111
35
 
112
- cents += set_minor_precision(minor, currency)
113
-
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.from_amount(amount, currency)
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
59
+ def from_bigdecimal(value, currency = Money.default_currency)
60
+ Money.from_amount(value, currency)
61
+ end
205
62
 
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
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)
219
66
  end
220
- end
221
67
 
222
- def self.split_major_minor(num, delimiter)
223
- major, minor = num.split(delimiter)
224
- minor = '00' unless minor
225
- [major, minor]
226
- end
68
+ def extract_cents(input, currency = Money.default_currency)
69
+ warn '[DEPRECATION] Monetize.extract_cents is deprecated. Use Monetize.parse().cents'
227
70
 
228
- def self.currency_symbol_regex
229
- /\A[\+|\-]?(?<symbol>#{regex_safe_symbols})/
71
+ money = parse(input, currency)
72
+ money.cents if money
73
+ end
230
74
  end
231
75
  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,159 @@
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
+ DEFAULT_DECIMAL_MARK = '.'.freeze
33
+
34
+ def initialize(input, fallback_currency = Money.default_currency, options = {})
35
+ @input = input.to_s.strip
36
+ @fallback_currency = fallback_currency
37
+ @options = options
38
+ end
39
+
40
+ def parse
41
+ currency = Money::Currency.wrap(parse_currency)
42
+
43
+ multiplier_exp, input = extract_multiplier
44
+
45
+ num = input.gsub(/(?:^#{currency.symbol}|[^\d.,'-]+)/, '')
46
+
47
+ negative, num = extract_sign(num)
48
+
49
+ num.chop! if num =~ /[\.|,]$/
50
+
51
+ major, minor = extract_major_minor(num, currency)
52
+
53
+ amount = BigDecimal([major, minor].join(DEFAULT_DECIMAL_MARK))
54
+ amount = apply_multiplier(multiplier_exp, amount)
55
+ amount = apply_sign(negative, amount)
56
+
57
+ [amount, currency]
58
+ end
59
+
60
+ private
61
+
62
+ attr_reader :input, :fallback_currency, :options
63
+
64
+ def parse_currency
65
+ computed_currency = nil
66
+ computed_currency = compute_currency if assume_from_symbol?
67
+ computed_currency ||= input[/[A-Z]{2,3}/]
68
+
69
+ computed_currency || fallback_currency || Money.default_currency
70
+ end
71
+
72
+ def assume_from_symbol?
73
+ options.fetch(:assume_from_symbol) { Monetize.assume_from_symbol }
74
+ end
75
+
76
+ def apply_multiplier(multiplier_exp, amount)
77
+ amount * 10**multiplier_exp
78
+ end
79
+
80
+ def apply_sign(negative, amount)
81
+ negative ? amount * -1 : amount
82
+ end
83
+
84
+ def compute_currency
85
+ match = input.match(currency_symbol_regex)
86
+ CURRENCY_SYMBOLS[match.to_s] if match
87
+ end
88
+
89
+ def extract_major_minor(num, currency)
90
+ used_delimiters = num.scan(/[^\d]/).uniq
91
+
92
+ case used_delimiters.length
93
+ when 0
94
+ [num, 0]
95
+ when 2
96
+ thousands_separator, decimal_mark = used_delimiters
97
+ split_major_minor(num.gsub(thousands_separator, ''), decimal_mark)
98
+ when 1
99
+ extract_major_minor_with_single_delimiter(num, currency, used_delimiters.first)
100
+ else
101
+ fail ParseError, 'Invalid amount'
102
+ end
103
+ end
104
+
105
+ def extract_major_minor_with_single_delimiter(num, currency, delimiter)
106
+ if delimiter == currency.decimal_mark
107
+ split_major_minor(num, delimiter)
108
+ elsif Monetize.enforce_currency_delimiters && delimiter == currency.thousands_separator
109
+ [num.gsub(delimiter, ''), 0]
110
+ else
111
+ extract_major_minor_with_tentative_delimiter(num, delimiter)
112
+ end
113
+ end
114
+
115
+ def extract_major_minor_with_tentative_delimiter(num, delimiter)
116
+ if num.scan(delimiter).length > 1
117
+ # Multiple matches; treat as thousands separator
118
+ [num.gsub(delimiter, ''), '00']
119
+ else
120
+ possible_major, possible_minor = split_major_minor(num, delimiter)
121
+
122
+ if possible_minor.length != 3 || possible_major.length > 3 || delimiter == '.'
123
+ # Doesn't look like thousands separator
124
+ [possible_major, possible_minor]
125
+ else
126
+ ["#{possible_major}#{possible_minor}", '00']
127
+ end
128
+ end
129
+ end
130
+
131
+ def extract_multiplier
132
+ if (matches = MULTIPLIER_REGEXP.match(input))
133
+ multiplier_suffix = matches[2].upcase
134
+ [MULTIPLIER_SUFFIXES[multiplier_suffix], "#{$1}#{$3}"]
135
+ else
136
+ [0, input]
137
+ end
138
+ end
139
+
140
+ def extract_sign(input)
141
+ result = (input =~ /^-+(.*)$/ || input =~ /^(.*)-+$/) ? [true, $1] : [false, input]
142
+ fail ParseError, 'Invalid amount (hyphen)' if result[1].include?('-')
143
+ result
144
+ end
145
+
146
+ def regex_safe_symbols
147
+ CURRENCY_SYMBOLS.keys.map { |key| Regexp.escape(key) }.join('|')
148
+ end
149
+
150
+ def split_major_minor(num, delimiter)
151
+ major, minor = num.split(delimiter)
152
+ [major, minor || '00']
153
+ end
154
+
155
+ def currency_symbol_regex
156
+ /(?<![A-Z])(#{regex_safe_symbols})(?![A-Z])/i
157
+ end
158
+ end
159
+ 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.4'
5
5
  end
@@ -7,8 +7,8 @@ require 'English'
7
7
  Gem::Specification.new do |spec|
8
8
  spec.name = 'monetize'
9
9
  spec.version = Monetize::VERSION
10
- spec.authors = ['Shane Emmons']
11
- spec.email = ['shane@emmons.io']
10
+ spec.authors = ['Shane Emmons', 'Anthony Dmitriyev']
11
+ spec.email = ['shane@emmons.io', 'anthony.dmitriyev@gmail.com']
12
12
  spec.description = 'A library for converting various objects into `Money` objects.'
13
13
  spec.summary = 'A library for converting various objects into `Money` objects.'
14
14
  spec.homepage = 'https://github.com/RubyMoney/monetize'
@@ -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
@@ -67,7 +67,8 @@ describe Monetize, 'core extensions' do
67
67
  '-1,000' => Money.new(-1_000_00),
68
68
  '1,000.5' => Money.new(1_000_50),
69
69
  '1,000.51' => Money.new(1_000_51),
70
- '1,000.505' => Money.new(1_000_51),
70
+ '1,000.505' => Money.new(1_000_50), # ROUND_HALF_EVEN default bankers rounding
71
+ '1,000.515' => Money.new(1_000_52), # ROUND_HALF_EVEN default bankers rounding
71
72
  '1,000.504' => Money.new(1_000_50),
72
73
  '1,000.0000' => Money.new(1_000_00),
73
74
  '1,000.5000' => Money.new(1_000_50),
@@ -149,6 +150,28 @@ describe Monetize, 'core extensions' do
149
150
  expect('1'.to_money('JPY')).to eq Money.new(1, 'JPY')
150
151
  expect('1.5'.to_money('KWD').cents).to eq 1_500
151
152
  end
153
+
154
+ it 'respects Money.rounding_mode' do
155
+ expect('1.009'.to_money).to eq(Money.new(1_01))
156
+
157
+ Money.rounding_mode(BigDecimal::ROUND_DOWN) do
158
+ expect('1.009'.to_money).to eq(Money.new(1_00))
159
+ end
160
+
161
+ expect('1.001'.to_money).to eq(Money.new(1_00))
162
+
163
+ Money.rounding_mode(BigDecimal::ROUND_UP) do
164
+ expect('1.001'.to_money).to eq(Money.new(1_01))
165
+ end
166
+ end
167
+
168
+ it 'produces results similar to Money.from_amount for all the rounding edge cases' do
169
+ (1_000..1_010).each do |amount|
170
+ amount = amount.to_f / 1000
171
+
172
+ expect(amount.to_s.to_money).to eq(Money.from_amount(amount))
173
+ end
174
+ end
152
175
  end
153
176
 
154
177
  describe '#to_currency' do
@@ -182,6 +205,14 @@ describe Monetize, 'core extensions' do
182
205
  end
183
206
  end
184
207
 
208
+ context 'when currency argument is a hash' do
209
+ subject(:hash) { {cents: 100, currency: {iso_code: 'EUR'}} }
210
+
211
+ it 'converts Hash to Money using iso_code from currency hash' do
212
+ expect(hash.to_money).to eq(Money.new(100, 'EUR'))
213
+ end
214
+ end
215
+
185
216
  context 'when no currency is passed' do
186
217
  subject(:hash) { {cents: 123} }
187
218
 
@@ -191,6 +222,14 @@ describe Monetize, 'core extensions' do
191
222
  expect(hash.to_money('USD')).to eq(Money.new(123, 'USD'))
192
223
  end
193
224
  end
225
+
226
+ context "when key name is 'fractional'" do
227
+ subject(:hash) { {fractional: 100} }
228
+
229
+ it 'converts Hash to Money, interpreting fractional as cents' do
230
+ expect(hash.to_money).to eq(Money.new(100, 'USD'))
231
+ end
232
+ end
194
233
  end
195
234
  end
196
235
 
@@ -56,76 +56,78 @@ 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
+ it "parses formatted inputs with #{iso_code} symbol is after the amount" do
74
+ expect(Monetize.parse("#{amount_in_units}#{symbol}")).to eq Money.new(amount, iso_code)
75
+ end
76
+
77
+ context 'prefix' do
78
+ it 'parses formatted inputs with plus 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
+
82
+ it 'parses formatted inputs with minus sign and currency as a symbol' do
83
+ expect(Monetize.parse("-#{symbol}#{amount_in_units}")).to eq Money.new(-amount, iso_code)
84
+ end
85
+ end
86
+
87
+ context 'postfix' do
88
+ it 'parses formatted inputs with currency symbol and postfix minus sign' do
89
+ expect(Monetize.parse("#{symbol}#{amount_in_units}-")).to eq Money.new(-amount, iso_code)
90
+ end
91
+
92
+ it 'parses formatted inputs with currency symbol and postfix plus sign' do
93
+ expect(Monetize.parse("#{symbol}#{amount_in_units}+")).to eq Money.new(amount, iso_code)
94
+ end
95
+ end
96
+
97
+ context 'amount suffixes' do
98
+ it 'parses formatted inputs with amounts given with suffixes' do
99
+ expect(Monetize.parse("#{symbol}1.26K")).to eq Money.new(1_260 * currency.subunit_to_unit, iso_code)
100
+ expect(Monetize.parse("#{symbol}126.36M")).to eq Money.new(126_360_000 * currency.subunit_to_unit, iso_code)
101
+ expect(Monetize.parse("#{symbol}.45B")).to eq Money.new(450_000_000 * currency.subunit_to_unit, iso_code)
102
+ expect(Monetize.parse("-#{symbol}2.45B")).to eq Money.new(-2_450_000_000 * currency.subunit_to_unit, iso_code)
103
+ expect(Monetize.parse("#{symbol}1.65T")).to eq Money.new(1_650_000_000_000 * currency.subunit_to_unit, iso_code)
104
+ end
105
+ end
106
+
107
+ it 'parses formatted inputs with symbol and surrounding spaces' do
108
+ expect(Monetize.parse(" #{symbol}#{amount_in_units} ")).to eq Money.new(amount, iso_code)
109
+ end
110
+
111
+ it 'parses formatted inputs without currency detection when overridden' do
112
+ expect(Monetize.parse("#{symbol}5.95", nil, assume_from_symbol: false)).to eq Money.new(amount, 'USD')
113
+ end
114
+ end
89
115
  end
90
116
 
91
117
  it 'should assume default currency if not a recognised symbol' do
92
118
  expect(Monetize.parse('L9.99')).to eq Money.new(999, 'USD')
93
119
  end
94
120
 
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
+ it 'ignores ZAR symbols that is part of a text' do
122
+ expect(Monetize.parse('EUR 9.99')).to eq Money.new(999, 'EUR')
123
+ expect(Monetize.parse('9.99 EUR')).to eq Money.new(999, 'EUR')
121
124
  end
122
125
 
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')
126
+ context 'negatives' do
127
+ it 'ignores the ambiguous kr symbol' do
128
+ # Could mean either of DKK, EEK, ISK, NOK, SEK
129
+ expect(Monetize.parse('kr9.99')).to eq Money.new(999, 'USD')
130
+ end
129
131
  end
130
132
  end
131
133
 
@@ -158,6 +160,18 @@ describe Monetize do
158
160
  it 'should opt out by default' do
159
161
  expect(Monetize.assume_from_symbol).to be_falsy
160
162
  end
163
+
164
+ context 'ISO code' do
165
+ it 'parses currency given as ISO code' do
166
+ expect('20.00 USD'.to_money).to eq Money.new(20_00, 'USD')
167
+ expect('20.00 EUR'.to_money).to eq Money.new(20_00, 'EUR')
168
+ expect('20.00 GBP'.to_money).to eq Money.new(20_00, 'GBP')
169
+ end
170
+
171
+ it 'raises an error if currency code is invalid' do
172
+ expect { '20.00 OMG'.to_money }.to raise_error Monetize::ParseError
173
+ end
174
+ end
161
175
  end
162
176
 
163
177
  it 'parses USD-formatted inputs under $10' do
@@ -177,10 +191,16 @@ describe Monetize do
177
191
  expect(Monetize.parse('1,111,234,567.89')).to eq Money.new(1_111_234_567_89, 'USD')
178
192
  end
179
193
 
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
194
+ it 'parses DKK-formatted inputs' do
195
+ expect(Monetize.parse('kr.123,45', 'DKK')).to eq Money.new(123_45, 'DKK')
196
+ expect(Monetize.parse('kr.123.45', 'DKK')).to eq Money.new(123_45, 'DKK')
197
+ expect(Monetize.parse('kr.45k', 'DKK')).to eq Money.new(45_000_00, 'DKK')
198
+ end
199
+
200
+ it 'returns nil if input is a price range' do
201
+ expect(Monetize.parse('$5.95-10.95')).to be_nil
202
+ expect(Monetize.parse('$5.95 - 10.95')).to be_nil
203
+ expect(Monetize.parse('$5.95 - $10.95')).to be_nil
184
204
  end
185
205
 
186
206
  it 'does not return a price for completely invalid input' do
@@ -197,8 +217,16 @@ describe Monetize do
197
217
  expect(Monetize.parse('$5.95-')).to eq five_ninety_five
198
218
  end
199
219
 
200
- it 'raises ArgumentError when unable to detect polarity' do
201
- expect { Monetize.parse('-$5.95-') }.to raise_error ArgumentError
220
+ it 'returns nil when unable to detect polarity' do
221
+ expect(Monetize.parse('-$5.95-')).to be_nil
222
+ end
223
+
224
+ it 'returns nil when more than 2 digit separators are used' do
225
+ expect(Monetize.parse("123.34,56'89 EUR")).to be_nil
226
+ end
227
+
228
+ it 'parses correctly strings with repeated digit separator' do
229
+ expect(Monetize.parse('19.12.89', 'EUR')).to eq Money.new(191_289_00, 'EUR')
202
230
  end
203
231
 
204
232
  it 'parses correctly strings with exactly 3 decimal digits' do
@@ -210,6 +238,32 @@ describe Monetize do
210
238
  Monetize.enforce_currency_delimiters = false
211
239
  end
212
240
 
241
+ context 'Money object attempting to be parsed' do
242
+ let(:money) { Money.new(595, 'GBP') }
243
+
244
+ it 'returns the original Money object' do
245
+ expect(Monetize.parse(money)).to eq money
246
+ expect(Monetize.parse(money).currency).to eq 'GBP'
247
+ expect(Monetize.parse(money).cents).to eq 595
248
+ end
249
+ end
250
+
251
+ context 'parsing an instance of Numeric class' do
252
+ let(:integer) { 10 }
253
+ let(:float) { 10.0 }
254
+ let(:big_decimal) { BigDecimal('10') }
255
+
256
+ [:integer, :float, :big_decimal].each do |type|
257
+ it "returns a new Money object based on the #{type} input" do
258
+ money = Monetize.parse(send(type), 'USD')
259
+
260
+ expect(money).to be_instance_of(Money)
261
+ expect(money.currency).to eq('USD')
262
+ expect(money.cents).to eq(10_00)
263
+ end
264
+ end
265
+ end
266
+
213
267
  context 'custom currencies with 4 decimal places' do
214
268
  before :each do
215
269
  Money::Currency.register(JSON.parse(bar, symbolize_names: true))
@@ -265,6 +319,18 @@ describe Monetize do
265
319
  end
266
320
  end
267
321
 
322
+ describe '.parse!' do
323
+ it 'does not return a price if there is a price range' do
324
+ expect { Monetize.parse!('$5.95-10.95') }.to raise_error Monetize::ParseError
325
+ expect { Monetize.parse!('$5.95 - 10.95') }.to raise_error Monetize::ParseError
326
+ expect { Monetize.parse!('$5.95 - $10.95') }.to raise_error Monetize::ParseError
327
+ end
328
+
329
+ it 'raises ArgumentError when unable to detect polarity' do
330
+ expect { Monetize.parse!('-$5.95-') }.to raise_error Monetize::ParseError
331
+ end
332
+ end
333
+
268
334
  describe '.parse_collection' do
269
335
  it 'parses into a Money::Collection' do
270
336
  expect(Monetize.parse_collection('$7')).to be_a Monetize::Collection
@@ -287,6 +353,10 @@ describe Monetize do
287
353
  expect(collection.first).to eq Monetize.parse('$4')
288
354
  expect(collection.last).to eq Monetize.parse('$10')
289
355
  end
356
+
357
+ it 'raises an error if argument is invalid' do
358
+ expect { Monetize.parse_collection(nil) }.to raise_error Monetize::ArgumentError
359
+ end
290
360
  end
291
361
 
292
362
  describe '.from_string' do
@@ -337,6 +407,10 @@ describe Monetize do
337
407
  m = Monetize.from_fixnum(1, 'EUR')
338
408
  expect(m.currency).to eq Money::Currency.wrap('EUR')
339
409
  end
410
+
411
+ it 'is aliased as from_integer' do
412
+ expect(Monetize.from_integer(1)).to eq(Monetize.from_fixnum(1))
413
+ end
340
414
  end
341
415
 
342
416
  describe '.from_float' do
@@ -366,25 +440,31 @@ describe Monetize do
366
440
 
367
441
  describe '.from_bigdecimal' do
368
442
  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')
443
+ expect(Monetize.from_bigdecimal(BigDecimal('1'))).to eq Money.new(1_00)
444
+ expect(Monetize.from_bigdecimal(BigDecimal('1'))).to eq Money.new(1_00, 'USD')
445
+ expect(Monetize.from_bigdecimal(BigDecimal('1'), 'EUR')).to eq Money.new(1_00, 'EUR')
372
446
  end
373
447
 
374
448
  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')
449
+ expect(Monetize.from_bigdecimal(BigDecimal('1'), 'USD')).to eq Money.new(1_00, 'USD')
450
+ expect(Monetize.from_bigdecimal(BigDecimal('1'), 'TND')).to eq Money.new(1_000, 'TND')
451
+ expect(Monetize.from_bigdecimal(BigDecimal('1'), 'JPY')).to eq Money.new(1, 'JPY')
452
+ end
453
+
454
+ it 'respects rounding mode when rounding amount to the nearest cent' do
455
+ amount = BigDecimal('1.005')
456
+
457
+ expect(Monetize.from_bigdecimal(amount, 'USD')).to eq Money.from_amount(amount, 'USD')
378
458
  end
379
459
 
380
460
  it 'accepts a currency options' do
381
- m = Monetize.from_bigdecimal(BigDecimal.new('1'))
461
+ m = Monetize.from_bigdecimal(BigDecimal('1'))
382
462
  expect(m.currency).to eq Money.default_currency
383
463
 
384
- m = Monetize.from_bigdecimal(BigDecimal.new('1'), Money::Currency.wrap('EUR'))
464
+ m = Monetize.from_bigdecimal(BigDecimal('1'), Money::Currency.wrap('EUR'))
385
465
  expect(m.currency).to eq Money::Currency.wrap('EUR')
386
466
 
387
- m = Monetize.from_bigdecimal(BigDecimal.new('1'), 'EUR')
467
+ m = Monetize.from_bigdecimal(BigDecimal('1'), 'EUR')
388
468
  expect(m.currency).to eq Money::Currency.wrap('EUR')
389
469
  end
390
470
 
@@ -398,11 +478,11 @@ describe Monetize do
398
478
  end
399
479
 
400
480
  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')
481
+ expect(Monetize.from_bigdecimal(BigDecimal('1'))).to eq Money.new(100)
482
+ expect(Monetize.from_bigdecimal(BigDecimal('1.23456'))).to eq Money.new(123.456)
483
+ expect(Monetize.from_bigdecimal(BigDecimal('-1.23456'))).to eq Money.new(-123.456)
484
+ expect(Monetize.from_bigdecimal(BigDecimal('1.23456'))).to eq Money.new(123.456, 'USD')
485
+ expect(Monetize.from_bigdecimal(BigDecimal('1.23456'), 'EUR')).to eq Money.new(123.456, 'EUR')
406
486
 
407
487
  expect('1'.to_money).to eq Money.new(100)
408
488
  expect('1.23456'.to_money).to eq Money.new(123.456)
@@ -417,19 +497,11 @@ describe Monetize do
417
497
  it 'converts given amount to cents' do
418
498
  expect(Monetize.from_numeric(1)).to eq Money.new(1_00)
419
499
  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)
500
+ expect(Monetize.from_numeric(BigDecimal('1'))).to eq Money.new(1_00)
421
501
  end
422
502
 
423
503
  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')
504
+ expect { Monetize.from_numeric('100') }.to raise_error(Monetize::ArgumentError)
433
505
  end
434
506
 
435
507
  it 'respects :subunit_to_unit currency property' do
@@ -457,6 +529,20 @@ describe Monetize do
457
529
  end
458
530
 
459
531
  describe '.extract_cents' do
532
+ it 'is deprecated' do
533
+ allow(Monetize).to receive(:warn)
534
+
535
+ Monetize.extract_cents('100')
536
+
537
+ expect(Monetize)
538
+ .to have_received(:warn)
539
+ .with('[DEPRECATION] Monetize.extract_cents is deprecated. Use Monetize.parse().cents')
540
+ end
541
+
542
+ it 'extracts cents from a given string' do
543
+ expect(Monetize.extract_cents('10.99')).to eq(1099)
544
+ end
545
+
460
546
  it "correctly treats pipe marks '|' in input (regression test)" do
461
547
  expect(Monetize.extract_cents('100|0')).to eq Monetize.extract_cents('100!0')
462
548
  end
metadata CHANGED
@@ -1,14 +1,15 @@
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.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shane Emmons
8
+ - Anthony Dmitriyev
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2016-01-15 00:00:00.000000000 Z
12
+ date: 2020-01-07 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: money
@@ -16,59 +17,60 @@ dependencies:
16
17
  requirements:
17
18
  - - "~>"
18
19
  - !ruby/object:Gem::Version
19
- version: '6.7'
20
+ version: '6.12'
20
21
  type: :runtime
21
22
  prerelease: false
22
23
  version_requirements: !ruby/object:Gem::Requirement
23
24
  requirements:
24
25
  - - "~>"
25
26
  - !ruby/object:Gem::Version
26
- version: '6.7'
27
+ version: '6.12'
27
28
  - !ruby/object:Gem::Dependency
28
29
  name: bundler
29
30
  requirement: !ruby/object:Gem::Requirement
30
31
  requirements:
31
- - - "~>"
32
+ - - ">="
32
33
  - !ruby/object:Gem::Version
33
- version: '1.3'
34
+ version: '0'
34
35
  type: :development
35
36
  prerelease: false
36
37
  version_requirements: !ruby/object:Gem::Requirement
37
38
  requirements:
38
- - - "~>"
39
+ - - ">="
39
40
  - !ruby/object:Gem::Version
40
- version: '1.3'
41
+ version: '0'
41
42
  - !ruby/object:Gem::Dependency
42
43
  name: rake
43
44
  requirement: !ruby/object:Gem::Requirement
44
45
  requirements:
45
- - - ">="
46
+ - - "~>"
46
47
  - !ruby/object:Gem::Version
47
- version: '0'
48
+ version: '10.2'
48
49
  type: :development
49
50
  prerelease: false
50
51
  version_requirements: !ruby/object:Gem::Requirement
51
52
  requirements:
52
- - - ">="
53
+ - - "~>"
53
54
  - !ruby/object:Gem::Version
54
- version: '0'
55
+ version: '10.2'
55
56
  - !ruby/object:Gem::Dependency
56
57
  name: rspec
57
58
  requirement: !ruby/object:Gem::Requirement
58
59
  requirements:
59
60
  - - "~>"
60
61
  - !ruby/object:Gem::Version
61
- version: 3.0.0.beta1
62
+ version: '3.0'
62
63
  type: :development
63
64
  prerelease: false
64
65
  version_requirements: !ruby/object:Gem::Requirement
65
66
  requirements:
66
67
  - - "~>"
67
68
  - !ruby/object:Gem::Version
68
- version: 3.0.0.beta1
69
+ version: '3.0'
69
70
  description: A library for converting various objects into `Money` objects.
70
71
  email:
71
72
  - shane@emmons.io
73
+ - anthony.dmitriyev@gmail.com
72
74
  executables: []
73
75
  extensions: []
74
76
  extra_rdoc_files: []
@@ -83,14 +85,16 @@ files:
83
85
  - LICENSE.txt
84
86
  - README.md
85
87
  - Rakefile
86
- - lib/collection.rb
87
88
  - lib/monetize.rb
89
+ - lib/monetize/collection.rb
88
90
  - lib/monetize/core_extensions.rb
89
91
  - lib/monetize/core_extensions/hash.rb
90
92
  - lib/monetize/core_extensions/nil_class.rb
91
93
  - lib/monetize/core_extensions/numeric.rb
92
94
  - lib/monetize/core_extensions/string.rb
93
95
  - lib/monetize/core_extensions/symbol.rb
96
+ - lib/monetize/errors.rb
97
+ - lib/monetize/parser.rb
94
98
  - lib/monetize/version.rb
95
99
  - monetize.gemspec
96
100
  - spec/core_extensions_spec.rb
@@ -99,7 +103,10 @@ files:
99
103
  homepage: https://github.com/RubyMoney/monetize
100
104
  licenses:
101
105
  - MIT
102
- metadata: {}
106
+ metadata:
107
+ changelog_uri: https://github.com/RubyMoney/monetize/blob/master/CHANGELOG.md
108
+ source_code_uri: https://github.com/RubyMoney/monetize/
109
+ bug_tracker_uri: https://github.com/RubyMoney/monetize/issues
103
110
  post_install_message:
104
111
  rdoc_options: []
105
112
  require_paths:
@@ -115,8 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
115
122
  - !ruby/object:Gem::Version
116
123
  version: '0'
117
124
  requirements: []
118
- rubyforge_project:
119
- rubygems_version: 2.4.5.1
125
+ rubygems_version: 3.0.3
120
126
  signing_key:
121
127
  specification_version: 4
122
128
  summary: A library for converting various objects into `Money` objects.
@@ -124,4 +130,3 @@ test_files:
124
130
  - spec/core_extensions_spec.rb
125
131
  - spec/monetize_spec.rb
126
132
  - spec/spec_helper.rb
127
- has_rdoc: