shopify-money 3.2.7 → 4.1.0
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 +4 -4
- data/.github/workflows/tests.yml +12 -12
- data/.gitignore +3 -0
- data/.rubocop.yml +1 -1
- data/.ruby-version +1 -1
- data/Gemfile +4 -1
- data/Gemfile.lock +72 -28
- data/README.md +39 -0
- data/Rakefile +28 -1
- data/Steepfile +20 -0
- data/config/currency_iso.yml +1 -4
- data/dev.yml +7 -1
- data/lib/money/allocator.rb +8 -2
- data/lib/money/config.rb +3 -10
- data/lib/money/core_extensions.rb +1 -22
- data/lib/money/currency/loader.rb +8 -1
- data/lib/money/currency.rb +13 -0
- data/lib/money/helpers.rb +1 -10
- data/lib/money/money.rb +8 -20
- data/lib/money/null_currency.rb +0 -1
- data/lib/money/version.rb +1 -1
- data/lib/money_column/active_record_hooks.rb +5 -13
- data/money.gemspec +3 -2
- data/rbs_collection.lock.yaml +440 -0
- data/rbs_collection.yaml +14 -0
- data/sig/core_extensions.rbs +9 -0
- data/sig/money/allocator.rbs +31 -0
- data/sig/money/config.rbs +33 -0
- data/sig/money/converters.rbs +32 -0
- data/sig/money/currency.rbs +49 -0
- data/sig/money/errors.rbs +9 -0
- data/sig/money/helpers.rbs +15 -0
- data/sig/money/null_currency.rbs +22 -0
- data/sig/money/parser.rbs +49 -0
- data/sig/money/splitter.rbs +28 -0
- data/sig/money/version.rbs +5 -0
- data/sig/money.rbs +103 -0
- data/sig/money_column.rbs +71 -0
- data/spec/allocator_spec.rb +24 -1
- data/spec/config_spec.rb +25 -39
- data/spec/core_extensions_spec.rb +5 -19
- data/spec/currency/loader_spec.rb +52 -0
- data/spec/currency_spec.rb +118 -1
- data/spec/deprecations_spec.rb +1 -1
- data/spec/helpers_spec.rb +2 -8
- data/spec/money_column_spec.rb +7 -37
- data/spec/money_spec.rb +7 -75
- data/spec/spec_helper.rb +14 -5
- metadata +35 -6
- data/UPGRADING.md +0 -59
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cadc7891cca0acc6f6128c570b259a5c1bead3a6a87175ebe3def93d9a618afb
|
|
4
|
+
data.tar.gz: 3fcc02abc7af2a86aba449ed135361a1024a18975430c8075f4b36d36d70c72a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 982ccb02e8ad20c3ad3ba9d217e0a53531d370cf32e7664947d859997ee2bc493614908f722fd1dc1ee0f234e114cb4c7e3552c85401d978afac4d462e35344c
|
|
7
|
+
data.tar.gz: 4a5e188fb292ad0ca2afdc2ba3dbcde89507a352d34ac7b7964870fc1584c0f9fd10d1036bd5b78a1971649d107b89f549f3b38a4f9bad823e829ac0c60d29ea
|
data/.github/workflows/tests.yml
CHANGED
|
@@ -9,26 +9,26 @@ jobs:
|
|
|
9
9
|
|
|
10
10
|
strategy:
|
|
11
11
|
matrix:
|
|
12
|
-
ruby: ['3.
|
|
12
|
+
ruby: ['3.2', '3.3', '3.4', '4.0']
|
|
13
13
|
|
|
14
14
|
name: Ruby ${{ matrix.ruby }}
|
|
15
15
|
steps:
|
|
16
16
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
17
17
|
- name: Set up Ruby ${{ matrix.ruby }}
|
|
18
|
-
uses: ruby/setup-ruby@
|
|
18
|
+
uses: ruby/setup-ruby@4fc31e1c823882afd7ef55985266a526c589de90 # v1.238.0
|
|
19
19
|
with:
|
|
20
20
|
ruby-version: ${{ matrix.ruby }}
|
|
21
|
-
|
|
21
|
+
bundler-cache: true
|
|
22
|
+
- name: Cache RBS collection
|
|
23
|
+
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
|
22
24
|
with:
|
|
23
|
-
path:
|
|
24
|
-
key: ${{ runner.os }}-
|
|
25
|
+
path: .gem_rbs_collection
|
|
26
|
+
key: ${{ runner.os }}-rbs-${{ hashFiles('rbs_collection.lock.yaml') }}
|
|
25
27
|
restore-keys: |
|
|
26
|
-
${{ runner.os }}-
|
|
27
|
-
- name: Install dependencies
|
|
28
|
-
run: |
|
|
29
|
-
gem install bundler
|
|
30
|
-
bundle config path vendor/bundle
|
|
31
|
-
bundle install --jobs 4 --retry 3
|
|
28
|
+
${{ runner.os }}-rbs-
|
|
32
29
|
- name: Run tests
|
|
33
30
|
run: |
|
|
34
|
-
bundle exec rake
|
|
31
|
+
bundle exec rake spec
|
|
32
|
+
- name: Run typecheck
|
|
33
|
+
run: |
|
|
34
|
+
bundle exec rake typecheck
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
4.0.1
|
data/Gemfile
CHANGED
|
@@ -3,8 +3,11 @@
|
|
|
3
3
|
source "https://rubygems.org"
|
|
4
4
|
|
|
5
5
|
gem "pry-byebug", require: false
|
|
6
|
+
gem "readline", require: false
|
|
6
7
|
gem "rubocop", require: false
|
|
7
|
-
gem "rubocop-shopify",
|
|
8
|
+
gem "rubocop-shopify", require: false
|
|
8
9
|
gem "rubocop-performance", require: false
|
|
9
10
|
|
|
10
11
|
gemspec
|
|
12
|
+
|
|
13
|
+
gem "steep", "~> 1.10"
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
shopify-money (
|
|
4
|
+
shopify-money (4.1.0)
|
|
5
5
|
bigdecimal (>= 3.0)
|
|
6
6
|
|
|
7
7
|
GEM
|
|
@@ -81,13 +81,14 @@ GEM
|
|
|
81
81
|
ast (2.4.3)
|
|
82
82
|
base64 (0.2.0)
|
|
83
83
|
benchmark (0.4.0)
|
|
84
|
-
bigdecimal (3.
|
|
84
|
+
bigdecimal (3.3.1)
|
|
85
85
|
builder (3.3.0)
|
|
86
86
|
byebug (12.0.0)
|
|
87
87
|
coderay (1.1.3)
|
|
88
88
|
concurrent-ruby (1.3.5)
|
|
89
89
|
connection_pool (2.5.0)
|
|
90
90
|
crass (1.0.6)
|
|
91
|
+
csv (3.3.5)
|
|
91
92
|
database_cleaner (2.0.2)
|
|
92
93
|
database_cleaner-active_record (>= 2, < 3)
|
|
93
94
|
database_cleaner-active_record (2.2.0)
|
|
@@ -99,6 +100,13 @@ GEM
|
|
|
99
100
|
docile (1.4.1)
|
|
100
101
|
drb (2.2.1)
|
|
101
102
|
erubi (1.13.1)
|
|
103
|
+
ffi (1.17.3-aarch64-linux-gnu)
|
|
104
|
+
ffi (1.17.3-arm-linux-gnu)
|
|
105
|
+
ffi (1.17.3-arm64-darwin)
|
|
106
|
+
ffi (1.17.3-x86-linux-gnu)
|
|
107
|
+
ffi (1.17.3-x86_64-darwin)
|
|
108
|
+
ffi (1.17.3-x86_64-linux-gnu)
|
|
109
|
+
fileutils (1.7.3)
|
|
102
110
|
globalid (1.2.1)
|
|
103
111
|
activesupport (>= 6.1)
|
|
104
112
|
i18n (1.14.7)
|
|
@@ -111,6 +119,9 @@ GEM
|
|
|
111
119
|
json (2.13.2)
|
|
112
120
|
language_server-protocol (3.17.0.5)
|
|
113
121
|
lint_roller (1.1.0)
|
|
122
|
+
listen (3.9.0)
|
|
123
|
+
rb-fsevent (~> 0.10, >= 0.10.3)
|
|
124
|
+
rb-inotify (~> 0.9, >= 0.9.10)
|
|
114
125
|
logger (1.7.0)
|
|
115
126
|
loofah (2.24.0)
|
|
116
127
|
crass (~> 1.0.2)
|
|
@@ -123,8 +134,10 @@ GEM
|
|
|
123
134
|
marcel (1.0.4)
|
|
124
135
|
method_source (1.1.0)
|
|
125
136
|
mini_mime (1.1.5)
|
|
126
|
-
mini_portile2 (2.8.
|
|
127
|
-
minitest (
|
|
137
|
+
mini_portile2 (2.8.9)
|
|
138
|
+
minitest (6.0.1)
|
|
139
|
+
prism (~> 1.5)
|
|
140
|
+
mutex_m (0.3.0)
|
|
128
141
|
net-imap (0.5.7)
|
|
129
142
|
date
|
|
130
143
|
net-protocol
|
|
@@ -135,18 +148,18 @@ GEM
|
|
|
135
148
|
net-smtp (0.5.1)
|
|
136
149
|
net-protocol
|
|
137
150
|
nio4r (2.7.4)
|
|
138
|
-
nokogiri (1.
|
|
151
|
+
nokogiri (1.19.0)
|
|
139
152
|
mini_portile2 (~> 2.8.2)
|
|
140
153
|
racc (~> 1.4)
|
|
141
|
-
nokogiri (1.
|
|
154
|
+
nokogiri (1.19.0-aarch64-linux-gnu)
|
|
142
155
|
racc (~> 1.4)
|
|
143
|
-
nokogiri (1.
|
|
156
|
+
nokogiri (1.19.0-arm-linux-gnu)
|
|
144
157
|
racc (~> 1.4)
|
|
145
|
-
nokogiri (1.
|
|
158
|
+
nokogiri (1.19.0-arm64-darwin)
|
|
146
159
|
racc (~> 1.4)
|
|
147
|
-
nokogiri (1.
|
|
160
|
+
nokogiri (1.19.0-x86_64-darwin)
|
|
148
161
|
racc (~> 1.4)
|
|
149
|
-
nokogiri (1.
|
|
162
|
+
nokogiri (1.19.0-x86_64-linux-gnu)
|
|
150
163
|
racc (~> 1.4)
|
|
151
164
|
ostruct (0.6.1)
|
|
152
165
|
parallel (1.27.0)
|
|
@@ -156,7 +169,7 @@ GEM
|
|
|
156
169
|
pp (0.6.2)
|
|
157
170
|
prettyprint
|
|
158
171
|
prettyprint (0.2.0)
|
|
159
|
-
prism (1.
|
|
172
|
+
prism (1.9.0)
|
|
160
173
|
pry (0.15.2)
|
|
161
174
|
coderay (~> 1.1)
|
|
162
175
|
method_source (~> 1.0)
|
|
@@ -206,8 +219,15 @@ GEM
|
|
|
206
219
|
zeitwerk (~> 2.6)
|
|
207
220
|
rainbow (3.1.1)
|
|
208
221
|
rake (13.2.1)
|
|
222
|
+
rb-fsevent (0.11.2)
|
|
223
|
+
rb-inotify (0.11.1)
|
|
224
|
+
ffi (~> 1.0)
|
|
225
|
+
rbs (3.9.5)
|
|
226
|
+
logger
|
|
209
227
|
rdoc (6.13.1)
|
|
210
228
|
psych (>= 4.0.0)
|
|
229
|
+
readline (0.0.4)
|
|
230
|
+
reline
|
|
211
231
|
regexp_parser (2.11.0)
|
|
212
232
|
reline (0.6.1)
|
|
213
233
|
io-console (~> 0.5)
|
|
@@ -224,7 +244,7 @@ GEM
|
|
|
224
244
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
225
245
|
rspec-support (~> 3.13.0)
|
|
226
246
|
rspec-support (3.13.1)
|
|
227
|
-
rubocop (1.
|
|
247
|
+
rubocop (1.84.2)
|
|
228
248
|
json (~> 2.3)
|
|
229
249
|
language_server-protocol (~> 3.17.0.2)
|
|
230
250
|
lint_roller (~> 1.1.0)
|
|
@@ -232,17 +252,17 @@ GEM
|
|
|
232
252
|
parser (>= 3.3.0.2)
|
|
233
253
|
rainbow (>= 2.2.2, < 4.0)
|
|
234
254
|
regexp_parser (>= 2.9.3, < 3.0)
|
|
235
|
-
rubocop-ast (>= 1.
|
|
255
|
+
rubocop-ast (>= 1.49.0, < 2.0)
|
|
236
256
|
ruby-progressbar (~> 1.7)
|
|
237
257
|
unicode-display_width (>= 2.4.0, < 4.0)
|
|
238
|
-
rubocop-ast (1.
|
|
258
|
+
rubocop-ast (1.49.0)
|
|
239
259
|
parser (>= 3.3.7.2)
|
|
240
|
-
prism (~> 1.
|
|
241
|
-
rubocop-performance (1.
|
|
260
|
+
prism (~> 1.7)
|
|
261
|
+
rubocop-performance (1.26.1)
|
|
242
262
|
lint_roller (~> 1.1)
|
|
243
263
|
rubocop (>= 1.75.0, < 2.0)
|
|
244
|
-
rubocop-ast (>= 1.
|
|
245
|
-
rubocop-shopify (2.
|
|
264
|
+
rubocop-ast (>= 1.47.1, < 2.0)
|
|
265
|
+
rubocop-shopify (2.18.0)
|
|
246
266
|
rubocop (~> 1.62)
|
|
247
267
|
ruby-progressbar (1.13.0)
|
|
248
268
|
securerandom (0.4.1)
|
|
@@ -252,20 +272,41 @@ GEM
|
|
|
252
272
|
simplecov_json_formatter (~> 0.1)
|
|
253
273
|
simplecov-html (0.13.1)
|
|
254
274
|
simplecov_json_formatter (0.1.4)
|
|
255
|
-
sqlite3 (2.
|
|
256
|
-
sqlite3 (2.
|
|
257
|
-
sqlite3 (2.
|
|
258
|
-
sqlite3 (2.
|
|
259
|
-
sqlite3 (2.
|
|
260
|
-
sqlite3 (2.
|
|
261
|
-
|
|
275
|
+
sqlite3 (2.9.0-aarch64-linux-gnu)
|
|
276
|
+
sqlite3 (2.9.0-arm-linux-gnu)
|
|
277
|
+
sqlite3 (2.9.0-arm64-darwin)
|
|
278
|
+
sqlite3 (2.9.0-x86-linux-gnu)
|
|
279
|
+
sqlite3 (2.9.0-x86_64-darwin)
|
|
280
|
+
sqlite3 (2.9.0-x86_64-linux-gnu)
|
|
281
|
+
steep (1.10.0)
|
|
282
|
+
activesupport (>= 5.1)
|
|
283
|
+
concurrent-ruby (>= 1.1.10)
|
|
284
|
+
csv (>= 3.0.9)
|
|
285
|
+
fileutils (>= 1.1.0)
|
|
286
|
+
json (>= 2.1.0)
|
|
287
|
+
language_server-protocol (>= 3.17.0.4, < 4.0)
|
|
288
|
+
listen (~> 3.0)
|
|
289
|
+
logger (>= 1.3.0)
|
|
290
|
+
mutex_m (>= 0.3.0)
|
|
291
|
+
parser (>= 3.1)
|
|
292
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
293
|
+
rbs (~> 3.9)
|
|
294
|
+
securerandom (>= 0.1)
|
|
295
|
+
strscan (>= 1.0.0)
|
|
296
|
+
terminal-table (>= 2, < 5)
|
|
297
|
+
uri (>= 0.12.0)
|
|
298
|
+
stringio (3.2.0)
|
|
299
|
+
strscan (3.1.5)
|
|
300
|
+
terminal-table (4.0.0)
|
|
301
|
+
unicode-display_width (>= 1.1.1, < 4)
|
|
262
302
|
thor (1.3.2)
|
|
263
303
|
timeout (0.4.3)
|
|
264
304
|
tzinfo (2.0.6)
|
|
265
305
|
concurrent-ruby (~> 1.0)
|
|
266
306
|
unicode-display_width (3.1.4)
|
|
267
307
|
unicode-emoji (~> 4.0, >= 4.0.4)
|
|
268
|
-
unicode-emoji (4.0
|
|
308
|
+
unicode-emoji (4.2.0)
|
|
309
|
+
uri (1.0.4)
|
|
269
310
|
useragent (0.16.11)
|
|
270
311
|
websocket-driver (0.7.7)
|
|
271
312
|
base64
|
|
@@ -287,13 +328,16 @@ DEPENDENCIES
|
|
|
287
328
|
ostruct
|
|
288
329
|
pry-byebug
|
|
289
330
|
rails (~> 7.2)
|
|
331
|
+
rbs (~> 3.0)
|
|
332
|
+
readline
|
|
290
333
|
rspec (~> 3.2)
|
|
291
334
|
rubocop
|
|
292
335
|
rubocop-performance
|
|
293
|
-
rubocop-shopify
|
|
336
|
+
rubocop-shopify
|
|
294
337
|
shopify-money!
|
|
295
338
|
simplecov
|
|
296
339
|
sqlite3
|
|
340
|
+
steep (~> 1.10)
|
|
297
341
|
|
|
298
342
|
BUNDLED WITH
|
|
299
|
-
|
|
343
|
+
4.0.6
|
data/README.md
CHANGED
|
@@ -157,6 +157,23 @@ Money.new(money.value * exchange_rate, "JPY")
|
|
|
157
157
|
money.convert_currency(exchange_rate, "JPY")
|
|
158
158
|
```
|
|
159
159
|
|
|
160
|
+
### Allocation Strategy
|
|
161
|
+
|
|
162
|
+
By default `allocate` distributes leftover subunits using the `:roundrobin` strategy.
|
|
163
|
+
You can change the default:
|
|
164
|
+
|
|
165
|
+
``` ruby
|
|
166
|
+
Money.configure do |config|
|
|
167
|
+
config.default_allocation_strategy = :nearest
|
|
168
|
+
end
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Or pass a strategy per call:
|
|
172
|
+
|
|
173
|
+
``` ruby
|
|
174
|
+
Money.new(10.55, "USD").allocate([0.25, 0.5, 0.25], :nearest)
|
|
175
|
+
```
|
|
176
|
+
|
|
160
177
|
### Crypto Currencies
|
|
161
178
|
To enable support for currencies listed in `crypto.yml` use
|
|
162
179
|
``` ruby
|
|
@@ -165,6 +182,28 @@ Money.configure do |config|
|
|
|
165
182
|
end
|
|
166
183
|
```
|
|
167
184
|
|
|
185
|
+
### Custom Currencies
|
|
186
|
+
To load custom currencies from a YAML file:
|
|
187
|
+
``` ruby
|
|
188
|
+
Money.configure do |config|
|
|
189
|
+
config.experimental_custom_currency_path = Rails.root.join("config/custom_currencies.yml")
|
|
190
|
+
end
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
``` yaml
|
|
194
|
+
# config/custom_currencies.yml
|
|
195
|
+
credits:
|
|
196
|
+
iso_code: "CREDITS"
|
|
197
|
+
name: "Loyalty Points"
|
|
198
|
+
symbol: "CR"
|
|
199
|
+
disambiguate_symbol: "CR"
|
|
200
|
+
subunit_to_unit: 1
|
|
201
|
+
smallest_denomination: 1
|
|
202
|
+
decimal_mark: "."
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Custom currencies are looked up after ISO and crypto currencies, so they cannot shadow built-in currencies.
|
|
206
|
+
|
|
168
207
|
### Converters
|
|
169
208
|
The Money gem provides a flexible converter system for handling different subunit formats. This is particularly useful when working with payment providers or APIs that have their own conventions for handling currency subunits.
|
|
170
209
|
|
data/Rakefile
CHANGED
|
@@ -30,7 +30,34 @@ RSpec::Core::RakeTask.new(:rcov) do |spec|
|
|
|
30
30
|
spec.rcov = true
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
namespace :rbs do
|
|
34
|
+
desc "Install RBS collection"
|
|
35
|
+
task :install do
|
|
36
|
+
sh "rbs collection install > /dev/null"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
desc "Validate RBS type signatures"
|
|
40
|
+
task validate: :install do
|
|
41
|
+
sh "rbs -I sig validate"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
desc "List RBS files"
|
|
45
|
+
task :list do
|
|
46
|
+
sh "find sig -name '*.rbs'"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
namespace :steep do
|
|
51
|
+
desc "Type check Ruby code against RBS signatures"
|
|
52
|
+
task check: "rbs:install" do
|
|
53
|
+
sh "steep check --jobs 2"
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
desc "Run all type checks (RBS validation + Steep type checking)"
|
|
58
|
+
task typecheck: ["rbs:validate", "steep:check"]
|
|
59
|
+
|
|
60
|
+
task default: [:spec, :typecheck]
|
|
34
61
|
|
|
35
62
|
require 'rake/task'
|
|
36
63
|
RDoc::Task.new do |rdoc|
|
data/Steepfile
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
target :lib do
|
|
4
|
+
signature "sig"
|
|
5
|
+
|
|
6
|
+
check "lib"
|
|
7
|
+
ignore "lib/rubocop/**/*.rb" # RuboCop cops use metaprogramming DSL
|
|
8
|
+
ignore "lib/money/railtie.rb" # Rails types
|
|
9
|
+
ignore "lib/money/deprecations.rb" # Uses class_eval
|
|
10
|
+
ignore "lib/money/rails/**/*.rb" # Rails-specific code
|
|
11
|
+
ignore "lib/money_column/railtie.rb" # Rails types
|
|
12
|
+
ignore "lib/money_column/active_record_hooks.rb" # Heavy metaprogramming with define_method
|
|
13
|
+
|
|
14
|
+
library "bigdecimal"
|
|
15
|
+
library "json"
|
|
16
|
+
library "forwardable"
|
|
17
|
+
library "yaml"
|
|
18
|
+
|
|
19
|
+
configure_code_diagnostics(Steep::Diagnostic::Ruby.lenient)
|
|
20
|
+
end
|
data/config/currency_iso.yml
CHANGED
|
@@ -420,7 +420,6 @@ cad:
|
|
|
420
420
|
alternate_symbols:
|
|
421
421
|
- C$
|
|
422
422
|
- CAD$
|
|
423
|
-
subunit_symbol: "¢"
|
|
424
423
|
subunit: Cent
|
|
425
424
|
subunit_to_unit: 100
|
|
426
425
|
symbol_first: true
|
|
@@ -758,7 +757,6 @@ gbp:
|
|
|
758
757
|
name: British Pound
|
|
759
758
|
symbol: "£"
|
|
760
759
|
alternate_symbols: []
|
|
761
|
-
subunit_symbol: p
|
|
762
760
|
subunit: Penny
|
|
763
761
|
subunit_to_unit: 100
|
|
764
762
|
symbol_first: true
|
|
@@ -1339,7 +1337,7 @@ mga:
|
|
|
1339
1337
|
symbol: Ar
|
|
1340
1338
|
alternate_symbols: []
|
|
1341
1339
|
subunit: Iraimbilanja
|
|
1342
|
-
subunit_to_unit:
|
|
1340
|
+
subunit_to_unit: 1
|
|
1343
1341
|
symbol_first: true
|
|
1344
1342
|
html_entity: ''
|
|
1345
1343
|
decimal_mark: "."
|
|
@@ -2235,7 +2233,6 @@ usd:
|
|
|
2235
2233
|
alternate_symbols:
|
|
2236
2234
|
- US$
|
|
2237
2235
|
subunit: Cent
|
|
2238
|
-
subunit_symbol: "¢"
|
|
2239
2236
|
subunit_to_unit: 100
|
|
2240
2237
|
symbol_first: true
|
|
2241
2238
|
html_entity: "$"
|
data/dev.yml
CHANGED
data/lib/money/allocator.rb
CHANGED
|
@@ -33,6 +33,8 @@ class Money
|
|
|
33
33
|
# - `:roundrobin_reverse`: leftover subunits will be accumulated starting from the last allocation right to left
|
|
34
34
|
# - `:nearest`: leftover subunits will by given first to the party closest to the next whole subunit
|
|
35
35
|
#
|
|
36
|
+
# The default strategy can be changed via `Money::Config.current.default_allocation_strategy`.
|
|
37
|
+
#
|
|
36
38
|
# @example
|
|
37
39
|
# Money.new(5, "USD").allocate([0.50, 0.25, 0.25])
|
|
38
40
|
# #=> [#<Money value:2.50 currency:USD>, #<Money value:1.25 currency:USD>, #<Money value:1.25 currency:USD>]
|
|
@@ -57,12 +59,16 @@ class Money
|
|
|
57
59
|
# Money.new(10.55, "USD").allocate([0.25, 0.5, 0.25], :nearest)
|
|
58
60
|
# #=> [#<Money value:2.64 currency:USD>, #<Money value:5.27 currency:USD>, #<Money value:2.64 currency:USD>]
|
|
59
61
|
|
|
60
|
-
def allocate(splits, strategy =
|
|
62
|
+
def allocate(splits, strategy = nil)
|
|
61
63
|
if splits.empty?
|
|
62
64
|
raise ArgumentError, 'at least one split must be provided'
|
|
63
65
|
end
|
|
64
66
|
|
|
65
|
-
|
|
67
|
+
strategy ||= Money::Config.current.default_allocation_strategy
|
|
68
|
+
|
|
69
|
+
# Float#to_r preserves float imprecision (0.98.to_r != 98/100).
|
|
70
|
+
# Rationalize gives the clean fraction (0.98.rationalize == 49/50).
|
|
71
|
+
splits.map!(&:rationalize)
|
|
66
72
|
allocations = splits.inject(0, :+)
|
|
67
73
|
|
|
68
74
|
if (allocations - ONE) > Float::EPSILON
|
data/lib/money/config.rb
CHANGED
|
@@ -41,7 +41,7 @@ class Money
|
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
attr_accessor :legacy_json_format, :
|
|
44
|
+
attr_accessor :legacy_json_format, :experimental_crypto_currencies, :default_subunit_format, :experimental_custom_currency_path, :default_allocation_strategy
|
|
45
45
|
|
|
46
46
|
attr_reader :default_currency
|
|
47
47
|
alias_method :currency, :default_currency
|
|
@@ -59,14 +59,6 @@ class Money
|
|
|
59
59
|
end
|
|
60
60
|
alias_method :currency=, :default_currency=
|
|
61
61
|
|
|
62
|
-
def legacy_default_currency!
|
|
63
|
-
@default_currency ||= Money::NULL_CURRENCY
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def legacy_deprecations!
|
|
67
|
-
@legacy_deprecations = true
|
|
68
|
-
end
|
|
69
|
-
|
|
70
62
|
def legacy_json_format!
|
|
71
63
|
@legacy_json_format = true
|
|
72
64
|
end
|
|
@@ -78,9 +70,10 @@ class Money
|
|
|
78
70
|
def initialize
|
|
79
71
|
@default_currency = nil
|
|
80
72
|
@legacy_json_format = false
|
|
81
|
-
@legacy_deprecations = false
|
|
82
73
|
@experimental_crypto_currencies = false
|
|
83
74
|
@default_subunit_format = :iso4217
|
|
75
|
+
@experimental_custom_currency_path = nil
|
|
76
|
+
@default_allocation_strategy = :roundrobin
|
|
84
77
|
end
|
|
85
78
|
end
|
|
86
79
|
end
|
|
@@ -16,27 +16,6 @@ end
|
|
|
16
16
|
class String
|
|
17
17
|
def to_money(currency = nil)
|
|
18
18
|
currency = Money::Helpers.value_to_currency(currency)
|
|
19
|
-
|
|
20
|
-
unless Money::Config.current.legacy_deprecations
|
|
21
|
-
return Money.new(self, currency)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
new_value = BigDecimal(self, exception: false)&.round(currency.minor_units)
|
|
25
|
-
unless new_value.nil?
|
|
26
|
-
return Money.new(self, currency)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
return Money.new(0, currency) if empty?
|
|
30
|
-
|
|
31
|
-
Money::Parser::Fuzzy.parse(self, currency).tap do |money|
|
|
32
|
-
old_value = money.value
|
|
33
|
-
|
|
34
|
-
if new_value != old_value
|
|
35
|
-
message = "`\"#{self}\".to_money` will soon behave like `Money.new(\"#{self}\")` and " \
|
|
36
|
-
"raise an ArgumentError exception. Use the browser's locale to parse money strings."
|
|
37
|
-
|
|
38
|
-
Money.deprecate(message)
|
|
39
|
-
end
|
|
40
|
-
end
|
|
19
|
+
Money.new(self, currency)
|
|
41
20
|
end
|
|
42
21
|
end
|
|
@@ -5,7 +5,7 @@ require 'yaml'
|
|
|
5
5
|
class Money
|
|
6
6
|
class Currency
|
|
7
7
|
module Loader
|
|
8
|
-
CURRENCY_DATA_PATH = File.expand_path("../../../config", __dir__)
|
|
8
|
+
CURRENCY_DATA_PATH = File.expand_path("../../../config", __dir__ || raise("__dir__ is nil"))
|
|
9
9
|
|
|
10
10
|
class << self
|
|
11
11
|
def load_currencies
|
|
@@ -22,6 +22,13 @@ class Money
|
|
|
22
22
|
deep_deduplicate!(currencies)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
def load_custom_currencies(path)
|
|
26
|
+
raise ArgumentError, "Custom currency file not found: #{path}" unless File.exist?(path)
|
|
27
|
+
data = YAML.safe_load_file(path, permitted_classes: [])
|
|
28
|
+
raise ArgumentError, "Custom currency file must contain a YAML hash" unless data.is_a?(Hash)
|
|
29
|
+
deep_deduplicate!(data)
|
|
30
|
+
end
|
|
31
|
+
|
|
25
32
|
private
|
|
26
33
|
|
|
27
34
|
def deep_deduplicate!(data)
|
data/lib/money/currency.rb
CHANGED
|
@@ -31,6 +31,15 @@ class Money
|
|
|
31
31
|
@@crypto_currencies ||= Loader.load_crypto_currencies
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
def custom_currencies(path)
|
|
35
|
+
@@custom_currencies_cache ||= {}
|
|
36
|
+
@@custom_currencies_cache[path] ||= Loader.load_custom_currencies(path)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def reset_custom_currencies
|
|
40
|
+
@@custom_currencies_cache = nil
|
|
41
|
+
end
|
|
42
|
+
|
|
34
43
|
def reset_loaded_currencies
|
|
35
44
|
@@loaded_currencies = {}
|
|
36
45
|
end
|
|
@@ -52,6 +61,10 @@ class Money
|
|
|
52
61
|
if data.nil? && Money::Config.current.experimental_crypto_currencies
|
|
53
62
|
data = self.class.crypto_currencies[currency_iso]
|
|
54
63
|
end
|
|
64
|
+
if data.nil?
|
|
65
|
+
custom_path = Money::Config.current.experimental_custom_currency_path
|
|
66
|
+
data = self.class.custom_currencies(custom_path)[currency_iso] if custom_path
|
|
67
|
+
end
|
|
55
68
|
|
|
56
69
|
raise UnknownCurrency, "Invalid iso4217 currency '#{currency_iso}'" unless data
|
|
57
70
|
@symbol = data['symbol']
|
data/lib/money/helpers.rb
CHANGED
|
@@ -44,16 +44,7 @@ class Money
|
|
|
44
44
|
when 'xxx', 'XXX'
|
|
45
45
|
Money::NULL_CURRENCY
|
|
46
46
|
when String
|
|
47
|
-
|
|
48
|
-
Currency.find!(currency)
|
|
49
|
-
rescue Money::Currency::UnknownCurrency => error
|
|
50
|
-
if Money::Config.current.legacy_deprecations
|
|
51
|
-
Money.deprecate(error.message)
|
|
52
|
-
Money::NULL_CURRENCY
|
|
53
|
-
else
|
|
54
|
-
raise error
|
|
55
|
-
end
|
|
56
|
-
end
|
|
47
|
+
Currency.find!(currency)
|
|
57
48
|
else
|
|
58
49
|
raise ArgumentError, "could not parse as currency #{currency.inspect}"
|
|
59
50
|
end
|
data/lib/money/money.rb
CHANGED
|
@@ -41,10 +41,6 @@ class Money
|
|
|
41
41
|
extend Forwardable
|
|
42
42
|
def_delegators :'Money::Config.global', :default_currency, :default_currency=
|
|
43
43
|
|
|
44
|
-
def without_legacy_deprecations(&block)
|
|
45
|
-
with_config(legacy_deprecations: false, &block)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
44
|
def with_config(**configs, &block)
|
|
49
45
|
Money::Config.configure_current(**configs, &block)
|
|
50
46
|
end
|
|
@@ -124,28 +120,24 @@ class Money
|
|
|
124
120
|
msg = "Money.new(Money.new(amount, #{amount.currency}), #{currency}) " \
|
|
125
121
|
"is changing the currency of an existing money object"
|
|
126
122
|
|
|
127
|
-
|
|
128
|
-
Money.deprecate("#{msg}. A Money::IncompatibleCurrencyError will raise in the next major release")
|
|
129
|
-
Money.new(amount.value, currency)
|
|
130
|
-
else
|
|
131
|
-
raise Money::IncompatibleCurrencyError, msg
|
|
132
|
-
end
|
|
123
|
+
raise Money::IncompatibleCurrencyError, msg
|
|
133
124
|
end
|
|
134
125
|
end
|
|
135
126
|
|
|
136
127
|
def initialize(value, currency)
|
|
137
128
|
raise ArgumentError if value.nan?
|
|
138
|
-
if value.infinite?
|
|
139
|
-
Money.deprecate("Initializing Money with infinity is deprecated and will raise an ArgumentError in v4")
|
|
140
|
-
end
|
|
129
|
+
raise ArgumentError if value.infinite?
|
|
141
130
|
|
|
142
|
-
@currency =
|
|
131
|
+
@currency = currency
|
|
143
132
|
@value = BigDecimal(value.round(@currency.minor_units))
|
|
144
133
|
freeze
|
|
145
134
|
end
|
|
146
135
|
|
|
147
136
|
def init_with(coder)
|
|
148
|
-
initialize(
|
|
137
|
+
initialize(
|
|
138
|
+
Helpers.value_to_decimal(coder['value']),
|
|
139
|
+
Helpers.value_to_currency(coder['currency']),
|
|
140
|
+
)
|
|
149
141
|
end
|
|
150
142
|
|
|
151
143
|
def encode_with(coder)
|
|
@@ -394,11 +386,7 @@ class Money
|
|
|
394
386
|
def ensure_compatible_currency(other_currency, msg)
|
|
395
387
|
return if currency.compatible?(other_currency)
|
|
396
388
|
|
|
397
|
-
|
|
398
|
-
Money.deprecate("#{msg}. A Money::IncompatibleCurrencyError will raise in the next major release")
|
|
399
|
-
else
|
|
400
|
-
raise Money::IncompatibleCurrencyError, msg
|
|
401
|
-
end
|
|
389
|
+
raise Money::IncompatibleCurrencyError, msg
|
|
402
390
|
end
|
|
403
391
|
|
|
404
392
|
def calculated_currency(other)
|