Skip to content

Commit 20d54f8

Browse files
authored
Merge branch 'main' into rbs
2 parents 84a3a4b + 3a45a68 commit 20d54f8

File tree

15 files changed

+94
-68
lines changed

15 files changed

+94
-68
lines changed

.github/workflows/ruby.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ jobs:
1212
runs-on: ubuntu-latest
1313
strategy:
1414
matrix:
15-
ruby-version: ['2.6', '2.7', '3.0', '3.1', '3.2']
15+
ruby-version: ['3.1', '3.2', '3.3']
1616

1717
steps:
18-
- uses: actions/checkout@v3
18+
- uses: actions/checkout@v4
1919
- name: Set up Ruby
2020
uses: ruby/setup-ruby@v1
2121
with:

AUTHORS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ Thomas E Enebo
123123
Thomas Weymuth
124124
Ticean Bennett
125125
Tien Nguyen
126+
Till Grosch
126127
Tim Hart
127128
Tim Krins
128129
Tobias Luetke
@@ -139,3 +140,4 @@ Yuusuke Takizawa
139140
Zubin Henner
140141
Бродяной Александр
141142
Nicolay Hvidsten
143+
Simon Neutert

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,21 @@
22

33
## Upcoming
44

5+
-
6+
7+
## 6.19.0
8+
59
- Change Peruvian Sol (PEN) decimal mark and thousands separator.
10+
- Fix deprecation warning for BigDecimal being moved out from stdlib.
11+
- Improves Precision and Simplifies Allocation Logic
12+
- explicit declaration of i18n locales
13+
- Add space to CHF format
14+
- Update deprecation message to suggest correct formatting.
615

716
## 6.18.0
817

918
- Add second dobra (STN) from São Tomé and Príncipe
19+
- Add Sierra Leonean (new) leone (SLE) from Sierra Leone
1020
- Correct South African Rand (ZAR) to use comma decimal mark, and space thousands separator
1121
- Use euro symbol as html_entity for euro currency
1222
- Update Georgian Lari symbol

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ MIT License
22

33
Copyright (c) 2005 Tobias Lutke
44
Copyright (c) 2008 Phusion
5-
Copyright (c) 2023 Shane Emmons
5+
Copyright (c) 2024 Shane Emmons
66

77
Permission is hereby granted, free of charge, to any person obtaining a copy
88
of this software and associated documentation files (the "Software"), to deal

config/currency_iso.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@
455455
"format": "%u %n",
456456
"html_entity": "",
457457
"decimal_mark": ".",
458-
"thousands_separator": ",",
458+
"thousands_separator": "'",
459459
"iso_numeric": "756",
460460
"smallest_denomination": 5
461461
},

lib/money/money/allocation.rb

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,21 @@
22

33
class Money
44
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.
87
#
98
# The results should always add up to the original amount.
109
#
1110
# The parts can be specified as:
1211
# Numeric — performs the split between a given number of parties evenly
1312
# Array<Numeric> — allocates the amounts proportionally to the given array
1413
#
14+
# @param amount [Numeric] The total amount to be allocated.
15+
# @param parts [Numeric, Array<Numeric>] Number of parts to split into or an array (proportions for allocation)
16+
# @param whole_amounts [Boolean] Specifies whether to allocate whole amounts only. Defaults to true.
17+
#
18+
# @return [Array<Numeric>] An array containing the allocated amounts.
19+
# @raise [ArgumentError] If parts is empty or not provided.
1520
def self.generate(amount, parts, whole_amounts = true)
1621
parts = if parts.is_a?(Numeric)
1722
Array.new(parts, 1)
@@ -21,7 +26,12 @@ def self.generate(amount, parts, whole_amounts = true)
2126
parts.dup
2227
end
2328

24-
raise ArgumentError, 'need at least one party' if parts.empty?
29+
raise ArgumentError, 'need at least one part' if parts.empty?
30+
31+
if [amount, *parts].any? { |i| i.is_a?(BigDecimal) || i.is_a?(Float) || i.is_a?(Rational) }
32+
amount = convert_to_big_decimal(amount)
33+
parts.map! { |p| convert_to_big_decimal(p) }
34+
end
2535

2636
result = []
2737
remaining_amount = amount
@@ -40,29 +50,23 @@ def self.generate(amount, parts, whole_amounts = true)
4050
remaining_amount -= current_split
4151
end
4252

43-
## round-robin allocation of any remaining pennies
44-
if result.size > 0
45-
while remaining_amount != 0
46-
index = 0
47-
48-
amount_to_distribute = [1, remaining_amount.abs].min
49-
50-
if remaining_amount > 0
51-
result[index] += amount_to_distribute
52-
remaining_amount -= amount_to_distribute
53-
else
54-
result[index] -= amount_to_distribute
55-
remaining_amount += amount_to_distribute
56-
end
53+
result
54+
end
5755

58-
index += 1
59-
if index > result.size
60-
index = 0
61-
end
62-
end
56+
# Converts a given number to BigDecimal.
57+
# This method supports inputs of BigDecimal, Rational, and other numeric types by ensuring they are all returned
58+
# as BigDecimal instances for consistent handling.
59+
#
60+
# @param number [Numeric, BigDecimal, Rational] The number to convert.
61+
# @return [BigDecimal] The converted number as a BigDecimal.
62+
def self.convert_to_big_decimal(number)
63+
if number.is_a? BigDecimal
64+
number
65+
elsif number.is_a? Rational
66+
BigDecimal(number.to_f.to_s)
67+
else
68+
BigDecimal(number.to_s)
6369
end
64-
65-
result
6670
end
6771
end
6872
end

lib/money/money/formatting_rules.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def translate_formatting_rules(rules)
7272
end
7373

7474
def localize_formatting_rules(rules)
75-
if currency.iso_code == "JPY" && I18n.locale == :ja
75+
if currency.iso_code == "JPY" && I18n.locale == :ja && rules[:format] == nil
7676
rules[:symbol] = "円" unless rules[:symbol] == false
7777
rules[:format] = '%n%u'
7878
end

money.gemspec

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Gem::Specification.new do |s|
1414
s.description = "A Ruby Library for dealing with money and currency conversion."
1515
s.license = "MIT"
1616

17+
s.add_dependency "bigdecimal"
1718
s.add_dependency 'i18n', [">= 0.6.4", '<= 2']
1819

1920
s.add_development_dependency "bundler"
@@ -24,12 +25,15 @@ Gem::Specification.new do |s|
2425
s.add_development_dependency "rbs" if RUBY_VERSION >= "2.7.0"
2526
s.add_development_dependency "typeprof" if RUBY_VERSION >= "2.7.0"
2627

28+
s.required_ruby_version = '>= 3.1'
29+
2730
s.files = `git ls-files -z -- config/* lib/* CHANGELOG.md LICENSE money.gemspec README.md`.split("\x0")
2831
s.require_paths = ["lib"]
2932

3033
if s.respond_to?(:metadata)
3134
s.metadata['changelog_uri'] = 'https://github.com/RubyMoney/money/blob/master/CHANGELOG.md'
3235
s.metadata['source_code_uri'] = 'https://github.com/RubyMoney/money/'
3336
s.metadata['bug_tracker_uri'] = 'https://github.com/RubyMoney/money/issues'
37+
s.metadata['rubygems_mfa_required'] = 'true'
3438
end
3539
end

spec/bank/base_spec.rb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,25 +32,25 @@ def setup
3232

3333
describe "#exchange_with" do
3434
it "is not implemented" do
35-
expect { subject.exchange_with(Money.new(100, 'USD'), 'EUR') }.to raise_exception(NotImplementedError)
35+
expect { subject.exchange_with(Money.new(100, 'USD'), 'EUR') }.to raise_error(NotImplementedError)
3636
end
3737
end
3838

3939
describe "#same_currency?" do
4040
it "accepts str/str" do
41-
expect { subject.send(:same_currency?, 'USD', 'EUR') }.to_not raise_exception
41+
expect { subject.send(:same_currency?, 'USD', 'EUR') }.to_not raise_error
4242
end
4343

4444
it "accepts currency/str" do
45-
expect { subject.send(:same_currency?, Money::Currency.wrap('USD'), 'EUR') }.to_not raise_exception
45+
expect { subject.send(:same_currency?, Money::Currency.wrap('USD'), 'EUR') }.to_not raise_error
4646
end
4747

4848
it "accepts str/currency" do
49-
expect { subject.send(:same_currency?, 'USD', Money::Currency.wrap('EUR')) }.to_not raise_exception
49+
expect { subject.send(:same_currency?, 'USD', Money::Currency.wrap('EUR')) }.to_not raise_error
5050
end
5151

5252
it "accepts currency/currency" do
53-
expect { subject.send(:same_currency?, Money::Currency.wrap('USD'), Money::Currency.wrap('EUR')) }.to_not raise_exception
53+
expect { subject.send(:same_currency?, Money::Currency.wrap('USD'), Money::Currency.wrap('EUR')) }.to_not raise_error
5454
end
5555

5656
it "returns true when currencies match" do
@@ -67,8 +67,8 @@ def setup
6767
expect(subject.send(:same_currency?, Money::Currency.wrap('USD'), Money::Currency.wrap('EUR'))).to be false
6868
end
6969

70-
it "raises an UnknownCurrency exception when an unknown currency is passed" do
71-
expect { subject.send(:same_currency?, 'AAA', 'BBB') }.to raise_exception(Money::Currency::UnknownCurrency)
70+
it "raises an UnknownCurrency error when an unknown currency is passed" do
71+
expect { subject.send(:same_currency?, 'AAA', 'BBB') }.to raise_error(Money::Currency::UnknownCurrency)
7272
end
7373
end
7474
end

spec/bank/single_currency_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
it "raises when called" do
44
expect {
55
subject.exchange_with(Money.new(100, 'USD'), 'EUR')
6-
}.to raise_exception(Money::Bank::DifferentCurrencyError, "No exchanging of currencies allowed: 1.00 USD to EUR")
6+
}.to raise_error(Money::Bank::DifferentCurrencyError, "No exchanging of currencies allowed: 1.00 USD to EUR")
77
end
88
end
99
end

0 commit comments

Comments
 (0)