money 6.16.0 → 6.19.0

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
2
  SHA256:
3
- metadata.gz: 3de47437ec002ed24a400508cac96b2ff6812f484c666fe3db3a82e921a805c0
4
- data.tar.gz: f96755602e56ea81d734b7505e7cfc88caaa948d7a8d285eeb470801028c15b9
3
+ metadata.gz: 331d852b12ab9a5e62108f3610d1ec5eed8f4fa9bb683be1aab2703cd2df26cd
4
+ data.tar.gz: 56e2bcad250542c80b800db800c2216dd2b3b10f1df5d8a77819d13153a77844
5
5
  SHA512:
6
- metadata.gz: 2f8cd71611e96a80cb733651675cb6fac59d358cb7c9576c8c264abbfec6eb1da11b8cbe2af12cdfb070e5dd01cd74f6fdc70772da16aa4c2abc5248b13fca3c
7
- data.tar.gz: '092ba5a188eb29d462431e94420e1c6d7a7f9a4a59c0895f66a4a1cf92cfaa37cbc1bc344a241f5f8cc9fc4e998189164bc2d0ab11480a589fe7bb0e341754ba'
6
+ metadata.gz: ae6d529a7382aaab721a4ae933658828f975eaa4c9a0ad9444b74b28d8ff1141d59f3e264d08b650367e327987266be03dcd480e0a850fe224feb6cdca4163d1
7
+ data.tar.gz: bbb76570efd7bf4be700cc3f46d01e26945e9790f5f9f3fee666d4ac3164d1422f5ca1614622a429c430804a9047bcc8f5178886905e5ad814ce21ab4117f94a
data/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # Changelog
2
2
 
3
+ ## Upcoming
4
+
5
+ -
6
+
7
+ ## 6.19.0
8
+
9
+ - Change Peruvian Sol (PEN) decimal mark and thousands separator.
10
+ - Improves Precision and Simplifies Allocation Logic
11
+ - explicit declaration of i18n locales
12
+ - Add space to CHF format
13
+ - Update deprecation message to suggest correct formatting.
14
+
15
+ ## 6.18.0
16
+
17
+ - Add second dobra (STN) from São Tomé and Príncipe
18
+ - Correct South African Rand (ZAR) to use comma decimal mark, and space thousands separator
19
+ - Use euro symbol as html_entity for euro currency
20
+ - Update Georgian Lari symbol
21
+ - Add Ruby 3.1 and 3.2 to the CI matrix
22
+ - Add `Money.from_dollars` alias as a more explicit initializer, it's the same as `Money.from_amount`
23
+ - Mark Croatian Kuna (HRK) as obsolete by moving its definition to the backwards compatibility data source
24
+
25
+ ## 6.17.0
26
+
27
+ - Allow true for `thousands_separator`
28
+
3
29
  ## 6.16.0
4
30
 
5
31
  - Add `Money.from_cents` alias as a more explicit initializer, it's the same as `Money.new`
data/LICENSE CHANGED
@@ -2,7 +2,7 @@ MIT License
2
2
 
3
3
  Copyright (c) 2005 Tobias Lutke
4
4
  Copyright (c) 2008 Phusion
5
- Copyright (c) 2021 Shane Emmons
5
+ Copyright (c) 2024 Shane Emmons
6
6
 
7
7
  Permission is hereby granted, free of charge, to any person obtaining a copy
8
8
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # RubyMoney - Money
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/money.svg)](https://rubygems.org/gems/money)
4
- [![Build Status](https://travis-ci.org/RubyMoney/money.svg?branch=master)](https://travis-ci.org/RubyMoney/money)
4
+ [![Ruby](https://github.com/RubyMoney/money/actions/workflows/ruby.yml/badge.svg)](https://github.com/RubyMoney/money/actions/workflows/ruby.yml)
5
5
  [![Code Climate](https://codeclimate.com/github/RubyMoney/money.svg)](https://codeclimate.com/github/RubyMoney/money)
6
6
  [![Inline docs](https://inch-ci.org/github/RubyMoney/money.svg)](https://inch-ci.org/github/RubyMoney/money)
7
7
  [![License](https://img.shields.io/github/license/RubyMoney/money.svg)](https://opensource.org/licenses/MIT)
@@ -60,6 +60,10 @@ The development version (hosted on Github) can be installed with:
60
60
  ``` ruby
61
61
  require 'money'
62
62
 
63
+ # explicitly define locales
64
+ I18n.config.available_locales = :en
65
+ Money.locale_backend = :i18n
66
+
63
67
  # 10.00 USD
64
68
  money = Money.from_cents(1000, "USD")
65
69
  money.cents #=> 1000
@@ -334,6 +338,59 @@ class ExchangeRate < ApplicationRecord
334
338
  yield rate.from, rate.to, rate.rate
335
339
  end
336
340
  end
341
+
342
+ def self.marshal_dump
343
+ [self]
344
+ end
345
+ end
346
+ ```
347
+
348
+ The following example implements a `Redis` store to save exchange rates to a redis database.
349
+
350
+ ```ruby
351
+
352
+ class RedisRateStore
353
+ INDEX_KEY_SEPARATOR = '_TO_'.freeze
354
+
355
+ # Using second db of the redis instance
356
+ # because sidekiq uses the first db
357
+ REDIS_DATABASE = 1
358
+
359
+ # Using Hash to store rates data
360
+ REDIS_STORE_KEY = 'rates'
361
+
362
+ def initialize
363
+ conn_url = "#{Rails.application.credentials.redis_server}/#{REDIS_DATABASE}"
364
+ @connection = Redis.new(url: conn_url)
365
+ end
366
+
367
+ def add_rate(iso_from, iso_to, rate)
368
+ @connection.hset(REDIS_STORE_KEY, rate_key_for(iso_from, iso_to), rate)
369
+ end
370
+
371
+ def get_rate(iso_from, iso_to)
372
+ @connection.hget(REDIS_STORE_KEY, rate_key_for(iso_from, iso_to))
373
+ end
374
+
375
+ def each_rate
376
+ rates = @connection.hgetall(REDIS_STORE_KEY)
377
+ return to_enum(:each_rate) unless block_given?
378
+
379
+ rates.each do |key, rate|
380
+ iso_from, iso_to = key.split(INDEX_KEY_SEPARATOR)
381
+ yield iso_from, iso_to, rate
382
+ end
383
+ end
384
+
385
+ def transaction
386
+ yield
387
+ end
388
+
389
+ private
390
+
391
+ def rate_key_for(iso_from, iso_to)
392
+ [iso_from, iso_to].join(INDEX_KEY_SEPARATOR).upcase
393
+ end
337
394
  end
338
395
  ```
339
396
 
@@ -31,6 +31,22 @@
31
31
  "iso_numeric": "288",
32
32
  "smallest_denomination": 1
33
33
  },
34
+ "hrk": {
35
+ "priority": 100,
36
+ "iso_code": "HRK",
37
+ "name": "Croatian Kuna",
38
+ "symbol": "kn",
39
+ "alternate_symbols": [],
40
+ "subunit": "Lipa",
41
+ "subunit_to_unit": 100,
42
+ "symbol_first": false,
43
+ "format": "%n %u",
44
+ "html_entity": "",
45
+ "decimal_mark": ",",
46
+ "thousands_separator": ".",
47
+ "iso_numeric": "191",
48
+ "smallest_denomination": 1
49
+ },
34
50
  "ltl": {
35
51
  "priority": 100,
36
52
  "iso_code": "LTL",
@@ -452,7 +452,7 @@
452
452
  "subunit": "Rappen",
453
453
  "subunit_to_unit": 100,
454
454
  "symbol_first": true,
455
- "format": "%u%n",
455
+ "format": "%u %n",
456
456
  "html_entity": "",
457
457
  "decimal_mark": ".",
458
458
  "thousands_separator": ",",
@@ -723,7 +723,7 @@
723
723
  "subunit": "Cent",
724
724
  "subunit_to_unit": 100,
725
725
  "symbol_first": true,
726
- "html_entity": "&#x20AC;",
726
+ "html_entity": "",
727
727
  "decimal_mark": ",",
728
728
  "thousands_separator": ".",
729
729
  "iso_numeric": "978",
@@ -782,7 +782,7 @@
782
782
  "priority": 100,
783
783
  "iso_code": "GEL",
784
784
  "name": "Georgian Lari",
785
- "symbol": "",
785
+ "symbol": "",
786
786
  "alternate_symbols": ["lari"],
787
787
  "subunit": "Tetri",
788
788
  "subunit_to_unit": 100,
@@ -922,22 +922,6 @@
922
922
  "iso_numeric": "340",
923
923
  "smallest_denomination": 5
924
924
  },
925
- "hrk": {
926
- "priority": 100,
927
- "iso_code": "HRK",
928
- "name": "Croatian Kuna",
929
- "symbol": "kn",
930
- "alternate_symbols": [],
931
- "subunit": "Lipa",
932
- "subunit_to_unit": 100,
933
- "symbol_first": false,
934
- "format": "%n %u",
935
- "html_entity": "",
936
- "decimal_mark": ",",
937
- "thousands_separator": ".",
938
- "iso_numeric": "191",
939
- "smallest_denomination": 1
940
- },
941
925
  "htg": {
942
926
  "priority": 100,
943
927
  "iso_code": "HTG",
@@ -1706,8 +1690,8 @@
1706
1690
  "subunit_to_unit": 100,
1707
1691
  "symbol_first": true,
1708
1692
  "html_entity": "S/",
1709
- "decimal_mark": ".",
1710
- "thousands_separator": ",",
1693
+ "decimal_mark": ",",
1694
+ "thousands_separator": ".",
1711
1695
  "iso_numeric": "604",
1712
1696
  "smallest_denomination": 1
1713
1697
  },
@@ -1999,11 +1983,28 @@
1999
1983
  "iso_numeric": "703",
2000
1984
  "smallest_denomination": 50
2001
1985
  },
1986
+ "sle": {
1987
+ "priority": 100,
1988
+ "iso_code": "SLE",
1989
+ "name": "New Leone",
1990
+ "symbol": "Le",
1991
+ "alternate_symbols": [],
1992
+ "subunit": "Cent",
1993
+ "subunit_to_unit": 100,
1994
+ "symbol_first": false,
1995
+ "format": "%n %u",
1996
+ "html_entity": "",
1997
+ "decimal_mark": ".",
1998
+ "thousands_separator": ",",
1999
+ "iso_numeric": "925",
2000
+ "smallest_denomination": 1000
2001
+ },
2002
2002
  "sll": {
2003
2003
  "priority": 100,
2004
2004
  "iso_code": "SLL",
2005
2005
  "name": "Sierra Leonean Leone",
2006
2006
  "symbol": "Le",
2007
+ "disambiguate_symbol": "SLL",
2007
2008
  "alternate_symbols": [],
2008
2009
  "subunit": "Cent",
2009
2010
  "subunit_to_unit": 100,
@@ -2081,6 +2082,23 @@
2081
2082
  "iso_numeric": "678",
2082
2083
  "smallest_denomination": 10000
2083
2084
  },
2085
+ "stn": {
2086
+ "priority": 100,
2087
+ "iso_code": "STN",
2088
+ "name": "São Tomé and Príncipe Second Dobra",
2089
+ "symbol": "Db",
2090
+ "disambiguate_symbol": "STN",
2091
+ "alternate_symbols": [],
2092
+ "subunit": "Cêntimo",
2093
+ "subunit_to_unit": 100,
2094
+ "symbol_first": false,
2095
+ "format": "%n %u",
2096
+ "html_entity": "",
2097
+ "decimal_mark": ".",
2098
+ "thousands_separator": ",",
2099
+ "iso_numeric": "930",
2100
+ "smallest_denomination": 10
2101
+ },
2084
2102
  "svc": {
2085
2103
  "priority": 100,
2086
2104
  "iso_code": "SVC",
@@ -2661,8 +2679,8 @@
2661
2679
  "subunit_to_unit": 100,
2662
2680
  "symbol_first": true,
2663
2681
  "html_entity": "&#x0052;",
2664
- "decimal_mark": ".",
2665
- "thousands_separator": ",",
2682
+ "decimal_mark": ",",
2683
+ "thousands_separator": " ",
2666
2684
  "iso_numeric": "710",
2667
2685
  "smallest_denomination": 10
2668
2686
  },
@@ -126,5 +126,21 @@
126
126
  "thousands_separator": ",",
127
127
  "iso_numeric": "",
128
128
  "smallest_denomination": 1
129
+ },
130
+ "usdc": {
131
+ "priority": 100,
132
+ "iso_code": "USDC",
133
+ "name": "USD Coin",
134
+ "symbol": "USDC",
135
+ "disambiguate_symbol": "USDC",
136
+ "alternate_symbols": [],
137
+ "subunit": "Cent",
138
+ "subunit_to_unit": 100,
139
+ "symbol_first": false,
140
+ "html_entity": "$",
141
+ "decimal_mark": ".",
142
+ "thousands_separator": ",",
143
+ "iso_numeric": "",
144
+ "smallest_denomination": 1
129
145
  }
130
146
  }
@@ -2,16 +2,17 @@
2
2
 
3
3
  class Money
4
4
  class Allocation
5
- # Splits a given amount in parts without losing pennies.
6
- # The left-over pennies will be distributed round-robin amongst the parts. This means that
7
- # parts listed first will likely receive more pennies than the ones listed later.
5
+ # Splits a given amount in parts. The allocation is based on the parts' proportions
6
+ # or evenly if parts are numerically specified.
8
7
  #
9
8
  # The results should always add up to the original amount.
10
9
  #
11
- # The parts can be specified as:
12
- # Numeric performs the split between a given number of parties evenely
13
- # Array<Numeric> allocates the amounts proportionally to the given array
10
+ # @param amount [Numeric] The total amount to be allocated.
11
+ # @param parts [Numeric, Array<Numeric>] Number of parts to split into or an array (proportions for allocation)
12
+ # @param whole_amounts [Boolean] Specifies whether to allocate whole amounts only. Defaults to true.
14
13
  #
14
+ # @return [Array<Numeric>] An array containing the allocated amounts.
15
+ # @raise [ArgumentError] If parts is empty or not provided.
15
16
  def self.generate(amount, parts, whole_amounts = true)
16
17
  parts = if parts.is_a?(Numeric)
17
18
  Array.new(parts, 1)
@@ -21,7 +22,12 @@ class Money
21
22
  parts.dup
22
23
  end
23
24
 
24
- raise ArgumentError, 'need at least one party' if parts.empty?
25
+ raise ArgumentError, 'need at least one part' if parts.empty?
26
+
27
+ if [amount, *parts].any? { |i| i.is_a?(BigDecimal) || i.is_a?(Float) || i.is_a?(Rational) }
28
+ amount = convert_to_big_decimal(amount)
29
+ parts.map! { |p| convert_to_big_decimal(p) }
30
+ end
25
31
 
26
32
  result = []
27
33
  remaining_amount = amount
@@ -42,5 +48,21 @@ class Money
42
48
 
43
49
  result
44
50
  end
51
+
52
+ # Converts a given number to BigDecimal.
53
+ # This method supports inputs of BigDecimal, Rational, and other numeric types by ensuring they are all returned
54
+ # as BigDecimal instances for consistent handling.
55
+ #
56
+ # @param number [Numeric, BigDecimal, Rational] The number to convert.
57
+ # @return [BigDecimal] The converted number as a BigDecimal.
58
+ def self.convert_to_big_decimal(number)
59
+ if number.is_a? BigDecimal
60
+ number
61
+ elsif number.is_a? Rational
62
+ BigDecimal(number.to_f.to_s)
63
+ else
64
+ BigDecimal(number.to_s)
65
+ end
66
+ end
45
67
  end
46
68
  end
@@ -124,11 +124,14 @@ class Money
124
124
  # the currency should be delimited by the specified character or ','
125
125
  #
126
126
  # @example
127
- # # If false is specified, no thousands_separator is used.
127
+ # # If a falsey value is specified, no thousands_separator is used.
128
128
  # Money.new(100000, "USD").format(thousands_separator: false) #=> "1000.00"
129
129
  # Money.new(100000, "USD").format(thousands_separator: nil) #=> "1000.00"
130
130
  # Money.new(100000, "USD").format(thousands_separator: "") #=> "1000.00"
131
131
  #
132
+ # # If true is specified, the locale or default thousands_separator is used.
133
+ # Money.new(100000, "USD").format(thousands_separator: true) #=> "1,000.00"
134
+ #
132
135
  # # If a string is specified, it's value is used.
133
136
  # Money.new(100000, "USD").format(thousands_separator: ".") #=> "$1.000.00"
134
137
  #
@@ -241,7 +244,11 @@ class Money
241
244
  end
242
245
 
243
246
  def thousands_separator
244
- lookup :thousands_separator
247
+ val = lookup :thousands_separator
248
+
249
+ return val unless val == true
250
+
251
+ lookup_default :thousands_separator
245
252
  end
246
253
 
247
254
  def decimal_mark
@@ -371,6 +378,10 @@ class Money
371
378
  def lookup(key)
372
379
  return rules[key] || DEFAULTS[key] if rules.has_key?(key)
373
380
 
381
+ lookup_default key
382
+ end
383
+
384
+ def lookup_default(key)
374
385
  (Money.locale_backend && Money.locale_backend.lookup(key, currency)) || DEFAULTS[key]
375
386
  end
376
387
 
@@ -117,7 +117,7 @@ class Money
117
117
  def warn_about_deprecated_rules(rules)
118
118
  if rules.has_key?(:symbol_position)
119
119
  position = rules[:symbol_position]
120
- template = position == :before ? '%u %n' : '%n %u'
120
+ template = position == :before ? '%u%n' : '%n%u'
121
121
 
122
122
  warn "[DEPRECATION] `symbol_position: :#{position}` is deprecated - you can replace it with `format: #{template}`"
123
123
  end
data/lib/money/money.rb CHANGED
@@ -314,6 +314,7 @@ class Money
314
314
 
315
315
  class << self
316
316
  alias_method :from_cents, :new
317
+ alias_method :from_dollars, :from_amount
317
318
  end
318
319
 
319
320
  # Creates a new Money object of value given in the
data/lib/money/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class Money
2
- VERSION = '6.16.0'
2
+ VERSION = '6.19.0'
3
3
  end
data/money.gemspec CHANGED
@@ -23,8 +23,6 @@ Gem::Specification.new do |s|
23
23
  s.add_development_dependency "kramdown", "~> 2.3"
24
24
 
25
25
  s.files = `git ls-files -z -- config/* lib/* CHANGELOG.md LICENSE money.gemspec README.md`.split("\x0")
26
- s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
27
- s.test_files = s.files.grep(%r{^(test|spec|features)/})
28
26
  s.require_paths = ["lib"]
29
27
 
30
28
  if s.respond_to?(:metadata)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: money
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.16.0
4
+ version: 6.19.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shane Emmons
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-05-09 00:00:00.000000000 Z
12
+ date: 2024-03-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: i18n
@@ -159,7 +159,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
159
159
  - !ruby/object:Gem::Version
160
160
  version: '0'
161
161
  requirements: []
162
- rubygems_version: 3.2.3
162
+ rubygems_version: 3.5.3
163
163
  signing_key:
164
164
  specification_version: 4
165
165
  summary: A Ruby Library for dealing with money and currency conversion.