shopify-money 3.0.0 → 3.0.2

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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/tests.yml +3 -3
  3. data/.gitignore +2 -1
  4. data/.rubocop.yml +36 -0
  5. data/.ruby-version +1 -1
  6. data/Gemfile +4 -1
  7. data/Gemfile.lock +165 -124
  8. data/Rakefile +2 -2
  9. data/config/currency_historic.yml +44 -2
  10. data/config/currency_iso.yml +38 -64
  11. data/lib/money/allocator.rb +13 -9
  12. data/lib/money/config.rb +8 -0
  13. data/lib/money/core_extensions.rb +2 -1
  14. data/lib/money/currency/loader.rb +4 -3
  15. data/lib/money/currency.rb +12 -3
  16. data/lib/money/deprecations.rb +22 -4
  17. data/lib/money/errors.rb +1 -0
  18. data/lib/money/helpers.rb +2 -1
  19. data/lib/money/money.rb +55 -30
  20. data/lib/money/null_currency.rb +11 -3
  21. data/lib/money/parser/accounting.rb +1 -0
  22. data/lib/money/parser/fuzzy.rb +14 -13
  23. data/lib/money/parser/locale_aware.rb +3 -6
  24. data/lib/money/parser/simple.rb +2 -1
  25. data/lib/money/rails/job_argument_serializer.rb +0 -1
  26. data/lib/money/railtie.rb +5 -3
  27. data/lib/money/splitter.rb +20 -24
  28. data/lib/money/version.rb +2 -1
  29. data/lib/money.rb +1 -0
  30. data/lib/money_column/active_record_hooks.rb +9 -6
  31. data/lib/money_column/active_record_type.rb +7 -4
  32. data/lib/money_column/railtie.rb +2 -1
  33. data/lib/money_column.rb +1 -0
  34. data/lib/rubocop/cop/money/missing_currency.rb +16 -23
  35. data/lib/rubocop/cop/money/zero_money.rb +7 -13
  36. data/lib/shopify-money.rb +1 -0
  37. data/money.gemspec +6 -6
  38. data/spec/config_spec.rb +18 -0
  39. data/spec/money_spec.rb +38 -0
  40. data/spec/rubocop/cop/money/missing_currency_spec.rb +7 -7
  41. data/spec/rubocop/cop/money/zero_money_spec.rb +2 -2
  42. metadata +18 -42
@@ -105,7 +105,7 @@ ars:
105
105
  subunit: Centavo
106
106
  subunit_to_unit: 100
107
107
  symbol_first: true
108
- html_entity: "₱"
108
+ html_entity: "$"
109
109
  decimal_mark: ","
110
110
  thousands_separator: "."
111
111
  iso_numeric: '032'
@@ -225,7 +225,7 @@ bhd:
225
225
  priority: 100
226
226
  iso_code: BHD
227
227
  name: Bahraini Dinar
228
- symbol: ب.د
228
+ symbol: د.ب
229
229
  alternate_symbols:
230
230
  - BD
231
231
  subunit: Fils
@@ -458,7 +458,7 @@ chf:
458
458
  symbol_first: true
459
459
  html_entity: ''
460
460
  decimal_mark: "."
461
- thousands_separator: ","
461
+ thousands_separator: "'"
462
462
  iso_numeric: '756'
463
463
  smallest_denomination: 5
464
464
  clf:
@@ -715,7 +715,7 @@ eur:
715
715
  subunit: Cent
716
716
  subunit_to_unit: 100
717
717
  symbol_first: true
718
- html_entity: "€"
718
+ html_entity: ""
719
719
  decimal_mark: ","
720
720
  thousands_separator: "."
721
721
  iso_numeric: '978'
@@ -771,7 +771,7 @@ gel:
771
771
  priority: 100
772
772
  iso_code: GEL
773
773
  name: Georgian Lari
774
- symbol:
774
+ symbol: "₾"
775
775
  alternate_symbols:
776
776
  - lari
777
777
  subunit: Tetri
@@ -905,20 +905,6 @@ hnl:
905
905
  thousands_separator: ","
906
906
  iso_numeric: '340'
907
907
  smallest_denomination: 5
908
- hrk:
909
- priority: 100
910
- iso_code: HRK
911
- name: Croatian Kuna
912
- symbol: kn
913
- alternate_symbols: []
914
- subunit: Lipa
915
- subunit_to_unit: 100
916
- symbol_first: false
917
- html_entity: ''
918
- decimal_mark: ","
919
- thousands_separator: "."
920
- iso_numeric: '191'
921
- smallest_denomination: 1
922
908
  htg:
923
909
  priority: 100
924
910
  iso_code: HTG
@@ -964,7 +950,7 @@ idr:
964
950
  ils:
965
951
  priority: 100
966
952
  iso_code: ILS
967
- name: Israeli New Sheqel
953
+ name: Israeli New Shekel
968
954
  symbol: "₪"
969
955
  alternate_symbols:
970
956
  - ש״ח
@@ -1034,7 +1020,7 @@ isk:
1034
1020
  - Íkr
1035
1021
  subunit:
1036
1022
  subunit_to_unit: 1
1037
- symbol_first: true
1023
+ symbol_first: false
1038
1024
  html_entity: ''
1039
1025
  decimal_mark: ","
1040
1026
  thousands_separator: "."
@@ -1210,7 +1196,7 @@ kzt:
1210
1196
  priority: 100
1211
1197
  iso_code: KZT
1212
1198
  name: Kazakhstani Tenge
1213
- symbol: ""
1199
+ symbol: ""
1214
1200
  alternate_symbols: []
1215
1201
  subunit: Tiyn
1216
1202
  subunit_to_unit: 100
@@ -1302,34 +1288,6 @@ lsl:
1302
1288
  thousands_separator: ","
1303
1289
  iso_numeric: '426'
1304
1290
  smallest_denomination: 1
1305
- ltl:
1306
- priority: 100
1307
- iso_code: LTL
1308
- name: Lithuanian Litas
1309
- symbol: Lt
1310
- alternate_symbols: []
1311
- subunit: Centas
1312
- subunit_to_unit: 100
1313
- symbol_first: false
1314
- html_entity: ''
1315
- decimal_mark: "."
1316
- thousands_separator: ","
1317
- iso_numeric: '440'
1318
- smallest_denomination: 1
1319
- lvl:
1320
- priority: 100
1321
- iso_code: LVL
1322
- name: Latvian Lats
1323
- symbol: Ls
1324
- alternate_symbols: []
1325
- subunit: Santīms
1326
- subunit_to_unit: 100
1327
- symbol_first: true
1328
- html_entity: ''
1329
- decimal_mark: "."
1330
- thousands_separator: ","
1331
- iso_numeric: '428'
1332
- smallest_denomination: 1
1333
1291
  lyd:
1334
1292
  priority: 100
1335
1293
  iso_code: LYD
@@ -1620,11 +1578,12 @@ npr:
1620
1578
  priority: 100
1621
1579
  iso_code: NPR
1622
1580
  name: Nepalese Rupee
1623
- symbol: "₨"
1581
+ symbol: Rs.
1624
1582
  disambiguate_symbol: NPR
1625
1583
  alternate_symbols:
1626
1584
  - Rs
1627
1585
  - रू
1586
+ - "₨"
1628
1587
  subunit: Paisa
1629
1588
  subunit_to_unit: 100
1630
1589
  symbol_first: true
@@ -1681,14 +1640,14 @@ pen:
1681
1640
  priority: 100
1682
1641
  iso_code: PEN
1683
1642
  name: Peruvian Sol
1684
- symbol: S/.
1643
+ symbol: S/
1685
1644
  alternate_symbols: []
1686
1645
  subunit: Céntimo
1687
1646
  subunit_to_unit: 100
1688
1647
  symbol_first: true
1689
- html_entity: S/.
1690
1648
  decimal_mark: "."
1691
1649
  thousands_separator: ","
1650
+ html_entity: S/
1692
1651
  iso_numeric: '604'
1693
1652
  smallest_denomination: 1
1694
1653
  pgk:
@@ -1970,6 +1929,20 @@ skk:
1970
1929
  thousands_separator: ","
1971
1930
  iso_numeric: '703'
1972
1931
  smallest_denomination: 50
1932
+ sle:
1933
+ priority: 100
1934
+ iso_code: SLE
1935
+ name: New Leone
1936
+ symbol: Le
1937
+ alternate_symbols: []
1938
+ subunit: Cent
1939
+ subunit_to_unit: 100
1940
+ symbol_first: false
1941
+ html_entity: ''
1942
+ decimal_mark: "."
1943
+ thousands_separator: ","
1944
+ iso_numeric: '925'
1945
+ smallest_denomination: 1000
1973
1946
  sll:
1974
1947
  priority: 100
1975
1948
  iso_code: SLL
@@ -2274,13 +2247,13 @@ uyu:
2274
2247
  priority: 100
2275
2248
  iso_code: UYU
2276
2249
  name: Uruguayan Peso
2277
- symbol: "$"
2250
+ symbol: "$U"
2278
2251
  alternate_symbols:
2279
2252
  - "$U"
2280
2253
  subunit: Centésimo
2281
2254
  subunit_to_unit: 100
2282
2255
  symbol_first: true
2283
- html_entity: "₱"
2256
+ html_entity: "$U"
2284
2257
  decimal_mark: ","
2285
2258
  thousands_separator: "."
2286
2259
  iso_numeric: '858'
@@ -2289,7 +2262,7 @@ uzs:
2289
2262
  priority: 100
2290
2263
  iso_code: UZS
2291
2264
  name: Uzbekistan Som
2292
- symbol: ''
2265
+ symbol: so'm
2293
2266
  alternate_symbols:
2294
2267
  - so‘m
2295
2268
  - сўм
@@ -2325,9 +2298,10 @@ ved:
2325
2298
  ves:
2326
2299
  priority: 100
2327
2300
  iso_code: VES
2328
- name: Venezuelan Bolívar soberano
2329
- symbol: Bs.S.
2330
- alternate_symbols: []
2301
+ name: Venezuelan Bolívar Soberano
2302
+ symbol: Bs
2303
+ alternate_symbols:
2304
+ - Bs.S
2331
2305
  subunit: Céntimo
2332
2306
  subunit_to_unit: 100
2333
2307
  symbol_first: true
@@ -2389,7 +2363,7 @@ xaf:
2389
2363
  priority: 100
2390
2364
  iso_code: XAF
2391
2365
  name: Central African Cfa Franc
2392
- symbol: Fr
2366
+ symbol: CFA
2393
2367
  disambiguate_symbol: FCFA
2394
2368
  alternate_symbols:
2395
2369
  - FCFA
@@ -2576,7 +2550,7 @@ xpt:
2576
2550
  smallest_denomination: ''
2577
2551
  xts:
2578
2552
  priority: 100
2579
- iso_code: xts
2553
+ iso_code: XTS
2580
2554
  name: Codes specifically reserved for testing purposes
2581
2555
  symbol: ''
2582
2556
  alternate_symbols: []
@@ -2612,8 +2586,8 @@ zar:
2612
2586
  subunit_to_unit: 100
2613
2587
  symbol_first: true
2614
2588
  html_entity: "R"
2615
- decimal_mark: "."
2616
- thousands_separator: ","
2589
+ decimal_mark: ","
2590
+ thousands_separator: " "
2617
2591
  iso_numeric: '710'
2618
2592
  smallest_denomination: 10
2619
2593
  zmk:
@@ -2635,7 +2609,7 @@ zmw:
2635
2609
  priority: 100
2636
2610
  iso_code: ZMW
2637
2611
  name: Zambian Kwacha
2638
- symbol: ZK
2612
+ symbol: K
2639
2613
  disambiguate_symbol: ZMW
2640
2614
  alternate_symbols: []
2641
2615
  subunit: Ngwee
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'delegate'
3
4
 
4
5
  class Money
@@ -107,7 +108,7 @@ class Money
107
108
  # Money.new(100).allocate_max_amounts([Money.new(5), Money.new(2)])
108
109
  # #=> [Money.new(5), Money.new(2)]
109
110
  def allocate_max_amounts(maximums)
110
- allocation_currency = extract_currency(maximums + [self.__getobj__])
111
+ allocation_currency = extract_currency(maximums + [__getobj__])
111
112
  maximums = maximums.map { |max| max.to_money(allocation_currency) }
112
113
  maximums_total = maximums.reduce(Money.new(0, allocation_currency), :+)
113
114
 
@@ -116,16 +117,16 @@ class Money
116
117
  Money.rational(max_amount, maximums_total)
117
118
  end
118
119
 
119
- total_allocatable = [maximums_total.subunits, self.subunits].min
120
+ total_allocatable = [maximums_total.subunits, subunits].min
120
121
 
121
122
  subunits_amounts, left_over = amounts_from_splits(1, splits, total_allocatable)
122
123
  subunits_amounts.map! { |amount| amount[:whole_subunits] }
123
124
 
124
125
  subunits_amounts.each_with_index do |amount, index|
125
- break unless left_over > 0
126
+ break if left_over <= 0
126
127
 
127
128
  max_amount = maximums[index].value * allocation_currency.subunit_to_unit
128
- next unless amount < max_amount
129
+ next if amount >= max_amount
129
130
 
130
131
  left_over -= 1
131
132
  subunits_amounts[index] += 1
@@ -137,9 +138,12 @@ class Money
137
138
  private
138
139
 
139
140
  def extract_currency(money_array)
140
- currencies = money_array.lazy.select { |money| money.is_a?(Money) }.reject(&:no_currency?).map(&:currency).to_a.uniq
141
+ currencies = money_array.lazy.select do |money|
142
+ money.is_a?(Money)
143
+ end.reject(&:no_currency?).map(&:currency).to_a.uniq
141
144
  if currencies.size > 1
142
- raise ArgumentError, "operation not permitted for Money objects with different currencies #{currencies.join(', ')}"
145
+ raise ArgumentError,
146
+ "operation not permitted for Money objects with different currencies #{currencies.join(", ")}"
143
147
  end
144
148
  currencies.first || NULL_CURRENCY
145
149
  end
@@ -154,8 +158,8 @@ class Money
154
158
  fractional_subunits = (subunits_to_split * ratio / allocations.to_r).to_f - whole_subunits
155
159
  left_over -= whole_subunits
156
160
  {
157
- :whole_subunits => whole_subunits,
158
- :fractional_subunits => fractional_subunits
161
+ whole_subunits: whole_subunits,
162
+ fractional_subunits: fractional_subunits,
159
163
  }
160
164
  end
161
165
 
@@ -172,7 +176,7 @@ class Money
172
176
  # the next whole number. Similarly, given the input [9.1, 5.5, 3.9] the correct ranking is *still* 2, 1, 0. This
173
177
  # is because 3.9 is nearer to 4 than 9.1 is to 10.
174
178
  def rank_by_nearest(amounts)
175
- amounts.each_with_index.sort_by{ |amount, i| 1 - amount[:fractional_subunits] }.map(&:last)
179
+ amounts.each_with_index.sort_by { |amount, _i| 1 - amount[:fractional_subunits] }.map(&:last)
176
180
  end
177
181
  end
178
182
  end
data/lib/money/config.rb CHANGED
@@ -21,5 +21,13 @@ class Money
21
21
  @legacy_json_format = false
22
22
  @legacy_deprecations = false
23
23
  end
24
+
25
+ def without_legacy_deprecations(&block)
26
+ old_legacy_deprecations = @legacy_deprecations
27
+ @legacy_deprecations = false
28
+ yield
29
+ ensure
30
+ @legacy_deprecations = old_legacy_deprecations
31
+ end
24
32
  end
25
33
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Allows Writing of 100.to_money for +Numeric+ types
3
4
  # 100.to_money => #<Money @cents=10000>
4
5
  # 100.37.to_money => #<Money @cents=10037>
@@ -25,7 +26,7 @@ class String
25
26
  return Money.new(self, currency)
26
27
  end
27
28
 
28
- return Money.new(0, currency) if self.empty?
29
+ return Money.new(0, currency) if empty?
29
30
 
30
31
  Money::Parser::Fuzzy.parse(self, currency).tap do |money|
31
32
  old_value = money.value
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'yaml'
3
4
 
4
5
  class Money
@@ -9,9 +10,9 @@ class Money
9
10
  currency_data_path = File.expand_path("../../../../config", __FILE__)
10
11
 
11
12
  currencies = {}
12
- currencies.merge! YAML.load_file("#{currency_data_path}/currency_historic.yml")
13
- currencies.merge! YAML.load_file("#{currency_data_path}/currency_non_iso.yml")
14
- currencies.merge! YAML.load_file("#{currency_data_path}/currency_iso.yml")
13
+ currencies.merge!(YAML.load_file("#{currency_data_path}/currency_historic.yml"))
14
+ currencies.merge!(YAML.load_file("#{currency_data_path}/currency_non_iso.yml"))
15
+ currencies.merge!(YAML.load_file("#{currency_data_path}/currency_iso.yml"))
15
16
  deep_deduplicate!(currencies)
16
17
  end
17
18
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "money/currency/loader"
3
4
 
4
5
  class Money
@@ -27,8 +28,16 @@ class Money
27
28
  end
28
29
  end
29
30
 
30
- attr_reader :iso_code, :iso_numeric, :name, :smallest_denomination, :subunit_symbol,
31
- :subunit_to_unit, :minor_units, :symbol, :disambiguate_symbol, :decimal_mark
31
+ attr_reader :iso_code,
32
+ :iso_numeric,
33
+ :name,
34
+ :smallest_denomination,
35
+ :subunit_symbol,
36
+ :subunit_to_unit,
37
+ :minor_units,
38
+ :symbol,
39
+ :disambiguate_symbol,
40
+ :decimal_mark
32
41
 
33
42
  def initialize(currency_iso)
34
43
  data = self.class.currencies[currency_iso]
@@ -51,7 +60,7 @@ class Money
51
60
  end
52
61
 
53
62
  def hash
54
- [ self.class, iso_code ].hash
63
+ [self.class, iso_code].hash
55
64
  end
56
65
 
57
66
  def compatible?(other)
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Money.class_eval do
3
4
  ACTIVE_SUPPORT_DEFINED = defined?(ActiveSupport)
5
+ DEPRECATION_STACKTRACE_LENGTH = 5
4
6
 
5
7
  def self.active_support_deprecator
6
8
  @active_support_deprecator ||= begin
@@ -11,12 +13,28 @@ Money.class_eval do
11
13
 
12
14
  def self.deprecate(message)
13
15
  if ACTIVE_SUPPORT_DEFINED
14
- external_callstack = caller_locations.reject do |location|
15
- location.to_s.include?('gems/shopify-money')
16
- end
17
- active_support_deprecator.warn("[Shopify/Money] #{message}\n", external_callstack)
16
+ active_support_deprecator.warn("[Shopify/Money] #{message}\n", caller_stack)
18
17
  else
19
18
  Kernel.warn("DEPRECATION WARNING: [Shopify/Money] #{message}\n")
20
19
  end
21
20
  end
21
+
22
+ # :nocov:
23
+ if Thread.respond_to?(:each_caller_location)
24
+ def self.caller_stack
25
+ stack = []
26
+ Thread.each_caller_location do |location|
27
+ stack << location unless location.path.include?('gems/shopify-money')
28
+ break if stack.length == DEPRECATION_STACKTRACE_LENGTH
29
+ end
30
+ stack
31
+ end
32
+ else
33
+ def self.caller_stack
34
+ caller_locations(2, DEPRECATION_STACKTRACE_LENGTH * 2).reject do |location|
35
+ location.path.include?('gems/shopify-money')
36
+ end
37
+ end
38
+ end
39
+ # :nocov:
22
40
  end
data/lib/money/errors.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  class Money
3
4
  class Error < StandardError
4
5
  end
data/lib/money/helpers.rb CHANGED
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'bigdecimal'
3
4
 
4
5
  class Money
5
6
  module Helpers
6
- module_function
7
+ extend self
7
8
 
8
9
  DECIMAL_ZERO = BigDecimal(0).freeze
9
10
  MAX_DECIMAL = 21
data/lib/money/money.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'forwardable'
4
+ require 'json'
3
5
 
4
6
  class Money
5
7
  include Comparable
@@ -8,6 +10,7 @@ class Money
8
10
  NULL_CURRENCY = NullCurrency.new.freeze
9
11
 
10
12
  attr_reader :value, :currency
13
+
11
14
  def_delegators :@value, :zero?, :nonzero?, :positive?, :negative?, :to_i, :to_f, :hash
12
15
 
13
16
  class ReverseOperationProxy
@@ -36,12 +39,19 @@ class Money
36
39
 
37
40
  class << self
38
41
  extend Forwardable
39
- attr_accessor :config
40
- def_delegators :@config, :default_currency, :default_currency=
42
+ def_delegators :config, :default_currency, :default_currency=, :without_legacy_deprecations
43
+
44
+ def config
45
+ Thread.current[:shopify_money__config] ||= @config.dup
46
+ end
47
+
48
+ def config=(config)
49
+ Thread.current[:shopify_money__config] = config
50
+ end
41
51
 
42
52
  def configure
43
- self.config ||= Config.new
44
- yield(config) if block_given?
53
+ @config ||= Config.new
54
+ yield(@config) if block_given?
45
55
  end
46
56
 
47
57
  def new(value = 0, currency = nil)
@@ -74,6 +84,16 @@ class Money
74
84
  new(value, currency)
75
85
  end
76
86
 
87
+ def from_json(string)
88
+ hash = JSON.parse(string, symbolize_names: true)
89
+ Money.new(hash.fetch(:value), hash.fetch(:currency))
90
+ end
91
+
92
+ def from_hash(hash)
93
+ hash = hash.transform_keys(&:to_sym)
94
+ Money.new(hash.fetch(:value), hash.fetch(:currency))
95
+ end
96
+
77
97
  def rational(money1, money2)
78
98
  money1.send(:arithmetic, money2) do
79
99
  factor = money1.currency.subunit_to_unit * money2.currency.subunit_to_unit
@@ -94,13 +114,11 @@ class Money
94
114
  # I18n.with_locale and ActiveSupport's Time.use_zone. This won't affect
95
115
  # instances being created with explicitly set currency.
96
116
  def with_currency(new_currency)
97
- begin
98
- old_currency = Money.current_currency
99
- Money.current_currency = new_currency
100
- yield
101
- ensure
102
- Money.current_currency = old_currency
103
- end
117
+ old_currency = Money.current_currency
118
+ Money.current_currency = new_currency
119
+ yield
120
+ ensure
121
+ Money.current_currency = old_currency
104
122
  end
105
123
 
106
124
  private
@@ -116,10 +134,12 @@ class Money
116
134
  return amount
117
135
  end
118
136
 
119
- msg = "Money.new(Money.new(amount, #{amount.currency}), #{currency}) is changing the currency of an existing money object"
137
+ msg = "Money.new(Money.new(amount, #{amount.currency}), #{currency}) " \
138
+ "is changing the currency of an existing money object"
139
+
120
140
  if Money.config.legacy_deprecations
121
141
  Money.deprecate("#{msg}. A Money::IncompatibleCurrencyError will raise in the next major release")
122
- return Money.new(amount.value, currency)
142
+ Money.new(amount.value, currency)
123
143
  else
124
144
  raise Money::IncompatibleCurrencyError, msg
125
145
  end
@@ -184,19 +204,19 @@ class Money
184
204
  end
185
205
  end
186
206
 
187
- def *(numeric)
188
- raise ArgumentError, "Money objects can only be multiplied by a Numeric" unless numeric.is_a?(Numeric)
207
+ def *(other)
208
+ raise ArgumentError, "Money objects can only be multiplied by a Numeric" unless other.is_a?(Numeric)
189
209
 
190
- return self if numeric == 1
191
- Money.new(value.to_r * numeric, currency)
210
+ return self if other == 1
211
+ Money.new(value.to_r * other, currency)
192
212
  end
193
213
 
194
- def /(numeric)
214
+ def /(other)
195
215
  raise "[Money] Dividing money objects can lose pennies. Use #split instead"
196
216
  end
197
217
 
198
218
  def inspect
199
- "#<#{self.class} value:#{self} currency:#{self.currency}>"
219
+ "#<#{self.class} value:#{self} currency:#{currency}>"
200
220
  end
201
221
 
202
222
  def ==(other)
@@ -228,8 +248,10 @@ class Money
228
248
  return Money.new(value, new_currency)
229
249
  end
230
250
 
231
- ensure_compatible_currency(Helpers.value_to_currency(new_currency),
232
- "to_money is attempting to change currency of an existing money object from #{currency} to #{new_currency}")
251
+ ensure_compatible_currency(
252
+ Helpers.value_to_currency(new_currency),
253
+ "to_money is attempting to change currency of an existing money object from #{currency} to #{new_currency}",
254
+ )
233
255
 
234
256
  self
235
257
  end
@@ -250,7 +272,7 @@ class Money
250
272
 
251
273
  rounded_value = value.round(units)
252
274
  if units == 0
253
- sprintf("%d", rounded_value)
275
+ format("%d", rounded_value)
254
276
  else
255
277
  formatted = rounded_value.to_s("F")
256
278
  decimal_digits = formatted.size - formatted.index(".") - 1
@@ -264,7 +286,7 @@ class Money
264
286
  alias_method :to_formatted_s, :to_fs
265
287
 
266
288
  def to_json(options = nil)
267
- if (options.is_a?(Hash) && options.delete(:legacy_format)) || Money.config.legacy_json_format
289
+ if (options.is_a?(Hash) && options[:legacy_format]) || Money.config.legacy_json_format
268
290
  to_s
269
291
  else
270
292
  as_json(options).to_json
@@ -272,12 +294,13 @@ class Money
272
294
  end
273
295
 
274
296
  def as_json(options = nil)
275
- if (options.is_a?(Hash) && options.delete(:legacy_format)) || Money.config.legacy_json_format
297
+ if (options.is_a?(Hash) && options[:legacy_format]) || Money.config.legacy_json_format
276
298
  to_s
277
299
  else
278
300
  { value: to_s(:amount), currency: currency.to_s }
279
301
  end
280
302
  end
303
+ alias_method :to_h, :as_json
281
304
 
282
305
  def abs
283
306
  abs = value.abs
@@ -291,7 +314,7 @@ class Money
291
314
  Money.new(floor, currency)
292
315
  end
293
316
 
294
- def round(ndigits=0)
317
+ def round(ndigits = 0)
295
318
  round = value.round(ndigits)
296
319
  return self if round == value
297
320
  Money.new(round, currency)
@@ -352,13 +375,13 @@ class Money
352
375
  def clamp(min, max)
353
376
  raise ArgumentError, 'min cannot be greater than max' if min > max
354
377
 
355
- clamped_value = min if self.value < min
356
- clamped_value = max if self.value > max
378
+ clamped_value = min if value < min
379
+ clamped_value = max if value > max
357
380
 
358
381
  if clamped_value.nil?
359
382
  self
360
383
  else
361
- Money.new(clamped_value, self.currency)
384
+ Money.new(clamped_value, currency)
362
385
  end
363
386
  end
364
387
 
@@ -367,8 +390,10 @@ class Money
367
390
  def arithmetic(other)
368
391
  case other
369
392
  when Money
370
- ensure_compatible_currency(other.currency,
371
- "mathematical operation not permitted for Money objects with different currencies #{other.currency} and #{currency}.")
393
+ desc = "mathematical operation not permitted for Money objects with different currencies " \
394
+ "#{other.currency} and #{currency}."
395
+
396
+ ensure_compatible_currency(other.currency, desc)
372
397
  yield(other)
373
398
 
374
399
  when Numeric, String
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  class Money
3
4
  # A placeholder currency for instances where no actual currency is available,
4
5
  # as defined by ISO4217. You should rarely, if ever, need to use this
@@ -32,9 +33,16 @@ class Money
32
33
  # #=> #<Money value:5.00 currency:CAD>
33
34
  #
34
35
  class NullCurrency
35
-
36
- attr_reader :iso_code, :iso_numeric, :name, :smallest_denomination, :subunit_symbol,
37
- :subunit_to_unit, :minor_units, :symbol, :disambiguate_symbol, :decimal_mark
36
+ attr_reader :iso_code,
37
+ :iso_numeric,
38
+ :name,
39
+ :smallest_denomination,
40
+ :subunit_symbol,
41
+ :subunit_to_unit,
42
+ :minor_units,
43
+ :symbol,
44
+ :disambiguate_symbol,
45
+ :decimal_mark
38
46
 
39
47
  def initialize
40
48
  @symbol = '$'
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  class Money
3
4
  module Parser
4
5
  class Accounting < Fuzzy