monetize 2.0.0 → 2.0.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
  SHA256:
3
- metadata.gz: 77ba1cf94643805ce15012361fda9aaadf3d029483b7c5e557dae4a0cd220c2f
4
- data.tar.gz: 8b9d5c77362a24cb9483d2cd02a0f35e5382a289c0eaacc8e44716408ef2a228
3
+ metadata.gz: 027fe3fe8fd8bf031ee1eeca954ccd33d64b09f7c1d611beef48758640f79ece
4
+ data.tar.gz: 252c3d7a5f4f922d0385ca6b7b10dffdbcf358a896afc5ba4a621298c966ae39
5
5
  SHA512:
6
- metadata.gz: 528b67577977e7fb1300cac86a086cc16d9a1941bb93270ed913b83c898b35b3c853583113ece518aeee68f099c0d5ee03bf559a68dffbabc4ed52aa3aaefdce
7
- data.tar.gz: d64891590b9c964dc7324f57e45262471922be81248914f8c4430649a9ee17a23e019ae99171762d27b07c1888db51d23f0be580cc0977fd0fa069e3aa7a6563
6
+ metadata.gz: 29bc1cef3e339731a0aa98f8d5198c81207f063c925650c5f42b8e23830f22dd1c35268b53d6f5296bfb0a15d59bbb08bc1b914967abc0eeda3282f7e0dcd8d4
7
+ data.tar.gz: af197d3990bc1a5488140912c7e5b39a9140a0bdf0247540ea3c9ef697044f20b8b9eab8691469bacf313a36e5ee3793c6c332e9353bf3cb676f98ba88bc1d8d
data/CHANGELOG.md CHANGED
@@ -2,6 +2,9 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 2.0.1
6
+ - Fix parsing of ISO codes not in `Monetize::Parser::CURRENCY_SYMBOLS`. `Monetize.parse('20.00 DKK')` returned 20.00 in the default currency instead of 20.00 DKK.
7
+
5
8
  ## 2.0.0
6
9
  - **Breaking change**: Remove deprecated `Monetize.extract_cents`.
7
10
  - **Breaking change**: Update Money gem dependency to ~> 7.0. See the [Money 7.0 upgrading guide](https://github.com/RubyMoney/money/blob/main/UPGRADING-7.0.md)
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Monetize
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/monetize.svg)](http://badge.fury.io/rb/monetize)
3
+ [![Gem Version](https://badge.fury.io/rb/monetize.svg)](https://rubygems.org/gems/monetize)
4
4
  [![Ruby](https://github.com/RubyMoney/monetize/actions/workflows/ruby.yml/badge.svg)](https://github.com/RubyMoney/monetize/actions/workflows/ruby.yml)
5
- [![License](https://img.shields.io/badge/license-MIT-green.svg)](http://opensource.org/licenses/MIT)
5
+ [![License](https://img.shields.io/badge/license-MIT-green.svg)](https://opensource.org/license/MIT)
6
6
 
7
7
  A library for converting various objects into `Money` objects.
8
8
 
@@ -53,7 +53,7 @@ this is not the case - a European site will show $10.000 because that's the loca
53
53
  As a human, if this was a stock ticker we might expect fractional cents. If it's a retail price we know it's actually an incorrect thousands separator.
54
54
 
55
55
 
56
- Monetize can also parse a list of values, returning an array-like object ([Monetize::Collection](lib/collection.rb)):
56
+ Monetize can also parse a list of values, returning an array-like object ([Monetize::Collection](lib/monetize/collection.rb)):
57
57
 
58
58
  ```ruby
59
59
  Monetize.parse_collection("€80/$100") == [Money.new(80_00, "EUR"), Money.new(100_00, "USD")]
@@ -35,6 +35,8 @@ module Monetize
35
35
  MULTIPLIER_REGEXP = Regexp.new(format('^(.*?\d)(%s)\b([^\d]*)$', MULTIPLIER_SUFFIXES.keys.join('|')), 'i')
36
36
 
37
37
  DEFAULT_DECIMAL_MARK = '.'.freeze
38
+ DEFAULT_MINOR = "00".freeze
39
+ private_constant :DEFAULT_MINOR
38
40
 
39
41
  def initialize(input, fallback_currency = Money.default_currency, options = {})
40
42
  @input = input.to_s.strip
@@ -43,19 +45,13 @@ module Monetize
43
45
  end
44
46
 
45
47
  def parse
46
- currency = Money::Currency.wrap(parse_currency)
47
-
48
48
  multiplier_exp, input = extract_multiplier
49
49
 
50
50
  num = input.gsub(/(?:^#{currency.symbol}|[^\d.,'-]+)/, '')
51
51
 
52
52
  negative, num = extract_sign(num)
53
53
 
54
- num.chop! if num =~ /[\.|,]$/
55
-
56
- major, minor = extract_major_minor(num, currency)
57
-
58
- amount = to_big_decimal([major, minor].join(DEFAULT_DECIMAL_MARK))
54
+ amount = to_big_decimal(normalize_number(num))
59
55
  amount = apply_multiplier(multiplier_exp, amount)
60
56
  amount = apply_sign(negative, amount)
61
57
 
@@ -64,6 +60,12 @@ module Monetize
64
60
 
65
61
  private
66
62
 
63
+ def normalize_number(num)
64
+ clean_num = num.sub(/[\.|,]$/, "")
65
+
66
+ extract_major_minor(clean_num).join(DEFAULT_DECIMAL_MARK)
67
+ end
68
+
67
69
  def to_big_decimal(value)
68
70
  BigDecimal(value)
69
71
  rescue ::ArgumentError => err
@@ -72,10 +74,14 @@ module Monetize
72
74
 
73
75
  attr_reader :input, :fallback_currency, :options
74
76
 
77
+ def currency
78
+ @currency ||= Money::Currency.wrap(parse_currency)
79
+ end
80
+
75
81
  def parse_currency
76
82
  computed_currency = nil
77
83
  computed_currency = input[/[A-Z]{2,3}/]
78
- computed_currency = nil unless Monetize::Parser::CURRENCY_SYMBOLS.value?(computed_currency)
84
+ computed_currency = nil unless Money::Currency.find(computed_currency)
79
85
  computed_currency ||= compute_currency if assume_from_symbol?
80
86
 
81
87
  found = computed_currency || fallback_currency || Money.default_currency
@@ -104,64 +110,65 @@ module Monetize
104
110
  CURRENCY_SYMBOLS[match.to_s] if match
105
111
  end
106
112
 
107
- def extract_major_minor(num, currency)
113
+ def remove_separator(num, separator)
114
+ num.gsub(separator, "")
115
+ end
116
+
117
+ def extract_major_minor(num)
108
118
  used_delimiters = num.scan(/[^\d]/).uniq
109
119
 
110
120
  case used_delimiters.length
111
121
  when 0
112
- [num, 0]
122
+ [num, DEFAULT_MINOR]
123
+ when 1
124
+ extract_major_minor_with_single_delimiter(num, used_delimiters.first)
113
125
  when 2
114
126
  thousands_separator, decimal_mark = used_delimiters
115
- split_major_minor(num.gsub(thousands_separator, ''), decimal_mark)
116
- when 1
117
- extract_major_minor_with_single_delimiter(num, currency, used_delimiters.first)
127
+ num = remove_separator(num, thousands_separator)
128
+
129
+ split_major_minor(num, decimal_mark)
118
130
  else
119
131
  fail ParseError, 'Invalid amount'
120
132
  end
121
133
  end
122
134
 
123
- def minor_has_correct_dp_for_currency_subunit?(minor, currency)
124
- minor.length == currency.subunit_to_unit.to_s.length - 1
135
+ def minor_has_correct_decimal_places_for_currency?(minor)
136
+ minor.length == currency.decimal_places
125
137
  end
126
138
 
127
- def extract_major_minor_with_single_delimiter(num, currency, delimiter)
139
+ def extract_major_minor_with_single_delimiter(num, delimiter)
128
140
  if expect_whole_subunits?
129
- _possible_major, possible_minor = split_major_minor(num, delimiter)
130
- if minor_has_correct_dp_for_currency_subunit?(possible_minor, currency)
131
- split_major_minor(num, delimiter)
132
- else
133
- extract_major_minor_with_tentative_delimiter(num, delimiter)
134
- end
135
- else
136
- if delimiter == currency.decimal_mark
137
- split_major_minor(num, delimiter)
138
- elsif Monetize.enforce_currency_delimiters && delimiter == currency.thousands_separator
139
- [num.gsub(delimiter, ''), 0]
140
- else
141
- extract_major_minor_with_tentative_delimiter(num, delimiter)
141
+ possible_major, possible_minor = split_major_minor(num, delimiter)
142
+
143
+ if minor_has_correct_decimal_places_for_currency?(possible_minor)
144
+ return [possible_major, possible_minor]
142
145
  end
146
+ elsif delimiter == currency.decimal_mark
147
+ return split_major_minor(num, delimiter)
148
+ elsif Monetize.enforce_currency_delimiters && delimiter == currency.thousands_separator
149
+ return [remove_separator(num, delimiter), DEFAULT_MINOR]
143
150
  end
151
+
152
+ extract_major_minor_with_tentative_delimiter(num, delimiter)
144
153
  end
145
154
 
146
155
  def extract_major_minor_with_tentative_delimiter(num, delimiter)
147
156
  if num.scan(delimiter).length > 1
148
157
  # Multiple matches; treat as thousands separator
149
- [num.gsub(delimiter, ''), '00']
150
- else
151
- possible_major, possible_minor = split_major_minor(num, delimiter)
158
+ return [remove_separator(num, delimiter), DEFAULT_MINOR]
159
+ end
152
160
 
153
- # Doesn't look like thousands separator
154
- is_decimal_mark = possible_minor.length != 3 ||
155
- possible_major.length > 3 ||
156
- possible_major.to_i == 0 ||
157
- (!expect_whole_subunits? && delimiter == '.')
161
+ possible_major, possible_minor = split_major_minor(num, delimiter)
158
162
 
159
- if is_decimal_mark
160
- [possible_major, possible_minor]
161
- else
162
- ["#{possible_major}#{possible_minor}", '00']
163
- end
164
- end
163
+ # Doesn't look like thousands separator
164
+ is_decimal_mark = possible_minor.length != 3 ||
165
+ possible_major.length > 3 ||
166
+ possible_major.to_i == 0 ||
167
+ (!expect_whole_subunits? && delimiter == ".")
168
+
169
+ return [possible_major, possible_minor] if is_decimal_mark
170
+
171
+ ["#{possible_major}#{possible_minor}", DEFAULT_MINOR]
165
172
  end
166
173
 
167
174
  def extract_multiplier
@@ -183,7 +190,9 @@ module Monetize
183
190
  splits = num.split(delimiter)
184
191
  fail ParseError, 'Invalid amount (multiple delimiters)' if splits.length > 2
185
192
 
186
- [splits[0], splits[1] || '00']
193
+ splits[1] ||= DEFAULT_MINOR
194
+
195
+ splits
187
196
  end
188
197
  end
189
198
  end
@@ -1,3 +1,3 @@
1
1
  module Monetize
2
- VERSION = '2.0.0'
2
+ VERSION = '2.0.1'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: monetize
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shane Emmons
@@ -69,7 +69,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
69
69
  - !ruby/object:Gem::Version
70
70
  version: '0'
71
71
  requirements: []
72
- rubygems_version: 4.0.0
72
+ rubygems_version: 4.0.17
73
73
  specification_version: 4
74
74
  summary: A library for converting various objects into `Money` objects.
75
75
  test_files: []