minting 1.9.6 → 1.9.7

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: 51f0a76084db98e53f29af4f82f1284f749c9691727a7a84a7f8cc758d1a9f67
4
- data.tar.gz: f24a130df454ee80f923aa42fd995e4b3eaf2f4f16d1a6f3a9e84548c08a4988
3
+ metadata.gz: 88ad41982102280b92486a6c6b1e05ae274afca3ccaf9daed2b778bc88f89764
4
+ data.tar.gz: 40c71dfc229055ddeb61c59c6a05977d8cce464c9ea869d07556be3efa529920
5
5
  SHA512:
6
- metadata.gz: 42ed5e90ba4a936426344cfd1f8aad69755038704c53b67d8f714ced040661e2f37829aa44d2d67f12575596656b7d9bd5b80058995b57875aaa46b2cf6dd291
7
- data.tar.gz: a6490a3356b949df6889e72ee3fc885a4e10af8d14e09591d7bd615ea468371c30b1695b73e996cb91526ab824a610e2667797eb24e94144ec46ddd22dc42395
6
+ metadata.gz: fd6f1a5b8c3fdd281080743065a366b7a0334423f373a0970ecfff386682e0fd545103a3eb42aa516bca0dfd0a6709d2fbcc422b4966e610ca5efe55ddf270a4
7
+ data.tar.gz: 76f592147f190433923741d40707b830448c80a7b3fe003392c9c8740c06a41b8f2433e7d832db27b8758f8d46f272b9fd33d9d2b3e33fb0a2742aa2fc6aa19d
data/README.md CHANGED
@@ -12,7 +12,7 @@ Fast, precise, and developer-friendly money handling for Ruby.
12
12
  ```ruby
13
13
  require 'minting'
14
14
 
15
- price = Mint.money(19.99, 'USD') #=> [USD 19.99]
15
+ price = Money.from(19.99, 'USD') #=> [USD 19.99]
16
16
  tax = price * 0.08 #=> [USD 1.60]
17
17
  total = price + tax #=> [USD 21.59]
18
18
 
@@ -23,8 +23,8 @@ total.currency_code #=> "USD"
23
23
  ### Exact precision
24
24
  Amounts are stored as `Rational` and rounded to the currency subunit. No floating-point surprises, ever.
25
25
 
26
- ### Blazing performance
27
- Minting is faster than the Money gem for everyday operations and **over 10× faster for formatting**. See full benchmarks in the [Performance Guide](test/performance/BENCHMARKS.md).
26
+ ### Good performance
27
+ Minting is fast! See full benchmarks in the [Performance Guide](bench/BENCHMARKS.md).
28
28
 
29
29
  ### Clean, modern API
30
30
  Intuitive interface, descriptive error messages, and sensible defaults. Works the way you expect.
@@ -55,38 +55,38 @@ gem 'minting'
55
55
  require 'minting'
56
56
 
57
57
  # Create money
58
- ten = Mint.money(10, 'USD') #=> [USD 10.00]
58
+ ten = Money.from(10, 'USD') #=> [USD 10.00]
59
59
 
60
- 1.dollar == Mint.money(1, 'USD') #=> true
60
+ 1.dollar == Money.from(1, 'USD') #=> true
61
61
  ten = 10.dollars #=> [USD 10.00]
62
62
  4.to_money('USD') #=> [USD 4.00]
63
63
 
64
64
  # Comparisons
65
65
  ten == 10.dollars #=> true
66
- ten == Mint.money(10, 'EUR') #=> false
67
- ten > Mint.money(9.99, 'USD') #=> true
66
+ ten == Money.from(10, 'EUR') #=> false
67
+ ten > Money.from(9.99, 'USD') #=> true
68
68
 
69
69
  # Zero equality semantics
70
70
  # Any zero amount is treated as equal, regardless of currency
71
- Mint.money(0, 'USD') == Mint.money(0, 'EUR') #=> true
72
- Mint.money(0, 'USD') == 0 #=> true
73
- Mint.money(0, 'USD') == 0.0 #=> true
71
+ Money.from(0, 'USD') == Money.from(0, 'EUR') #=> true
72
+ Money.from(0, 'USD') == 0 #=> true
73
+ Money.from(0, 'USD') == 0.0 #=> true
74
74
 
75
75
  # Non-zero numerics are not equal to Money objects
76
- Mint.money(10, 'USD') == 10 #=> false
76
+ Money.from(10, 'USD') == 10 #=> false
77
77
 
78
78
  # Format (uses Kernel.format syntax)
79
- price = Mint.money(9.99, 'USD')
80
- loss = Mint.money(-1234.56, 'USD')
79
+ price = Money.from(9.99, 'USD')
80
+ loss = Money.from(-1234.56, 'USD')
81
81
 
82
82
  # Built-in named presets
83
83
  loss.format(:accounting) #=> "($1,234.56)"
84
- Mint.money(1234.56, 'EUR').format(:european) #=> "1.234,56 €"
84
+ Money.from(1234.56, 'EUR').format(:european) #=> "1.234,56 €"
85
85
  price.format(:amount) #=> "9.99"
86
86
  price.format(:currency) #=> "USD 9.99"
87
87
 
88
88
  # Presets can be overridden with explicit kwargs
89
- Mint.money(1234.56, 'EUR').format(:european, format: '%<amount>f %<currency>s')
89
+ Money.from(1234.56, 'EUR').format(:european, format: '%<amount>f %<currency>s')
90
90
  #=> "1.234,56 EUR"
91
91
 
92
92
  # Or use direct format strings
@@ -97,7 +97,7 @@ price.format(format: '%<symbol>s%<amount>+f') #=> "$+9.99",
97
97
  (-price).format(format: '%<amount>f') #=> "-9.99",
98
98
 
99
99
  # Format with padding
100
- price_in_euros = Mint.money(12.34, 'EUR')
100
+ price_in_euros = Money.from(12.34, 'EUR')
101
101
 
102
102
  price.format(format: '--%<amount>7d') #=> "-- 9"
103
103
  price.format(format: ' %<amount>10f %<currency>s') #=> " 9.99 USD"
@@ -107,16 +107,21 @@ price_in_euros.format(format: '%<symbol>2s%<amount>+10f') #=> " € +12.34
107
107
 
108
108
  # Integral & fractional parts
109
109
  price.format(format: '%<integral>d %<fractional>d/100') #=> "9 99/100"
110
- Mint.money(0.99, 'USD').format(format: '%<integral>d dollars and %<fractional>02d cents')
110
+ Money.from(0.99, 'USD').format(format: '%<integral>d dollars and %<fractional>02d cents')
111
111
  #=> "0 dollars and 99 cents"
112
112
 
113
113
  # Per-sign Hash format (e.g. accounting parentheses for losses)
114
- loss = Mint.money(-1234.56, 'USD')
114
+ loss = Money.from(-1234.56, 'USD')
115
115
  loss.format(format: { negative: '(%<symbol>s%<amount>f)' }) #=> "($1,234.56)"
116
- Mint.money(0, 'BRL').format(format: { zero: '--' }) #=> "--"
116
+ Money.from(0, 'BRL').format(format: { zero: '--' }) #=> "--"
117
117
  # All three keys at once:
118
118
  fmt = { positive: '%<symbol>s%<amount>f', negative: '(%<symbol>s%<amount>f)', zero: '--' }
119
- Mint.money(1234.56, 'USD').format(format: fmt) #=> "$1,234.56"
119
+ Money.from(1234.56, 'USD').format(format: fmt) #=> "$1,234.56"
120
+
121
+ # Disambiguated symbol (e.g. "US$" vs "C$" vs "A$")
122
+ Money.from(10, 'USD').format(format: '%<dsymbol>s%<amount>f') #=> "US$10.00"
123
+ Money.from(10, 'CAD').format(format: '%<dsymbol>s%<amount>f') #=> "C$10.00"
124
+ Money.from(10, 'EUR').format(format: '%<dsymbol>s%<amount>f') #=> "€10.00" (no dsymbol, falls back to symbol)
120
125
 
121
126
  # Json serialization
122
127
 
@@ -147,8 +152,8 @@ ten.allocate([1, 2, 3]) #=> [[USD 1.67], [USD 3.33], [USD 5.00]]
147
152
 
148
153
  # Clamping to a range
149
154
 
150
- price = Mint.money(50, 'USD')
151
- min_price = Mint.money(75, 'USD')
155
+ price = Money.from(50, 'USD')
156
+ min_price = Money.from(75, 'USD')
152
157
 
153
158
  price.clamp(0, 100) #=> [USD 50.00] (returns self, no new object)
154
159
  price.clamp(0, 25) #=> [USD 25.00] (clamped to max)
@@ -201,8 +206,8 @@ Mint::Currency.for_symbol('€') #=> #<Currency code="EUR" ...>
201
206
  **Rounding modes** — Wrap operations in `Mint.with_rounding(mode)` to change how amounts are rounded to the subunit:
202
207
 
203
208
  ```ruby
204
- Mint.with_rounding(:half_down) { Mint.money(1.005, 'USD') } #=> [USD 1.00]
205
- Mint.with_rounding(:ceil) { Mint.money(1.001, 'USD') } #=> [USD 1.01]
209
+ Mint.with_rounding(:half_down) { Money.from(1.005, 'USD') } #=> [USD 1.00]
210
+ Mint.with_rounding(:ceil) { Money.from(1.001, 'USD') } #=> [USD 1.01]
206
211
  Mint.with_rounding(:floor) { Mint.parse('1.009', 'USD') } #=> [USD 1.00]
207
212
  ```
208
213
 
@@ -212,7 +217,7 @@ Modes: `:half_up` (default), `:half_down`, `:floor`, `:ceil`, `:truncate`, `:dow
212
217
 
213
218
  **Division** — `money / 5` returns new `Money`; `money / other_money` returns a numeric ratio, not money.
214
219
 
215
- **Zero equality** — Any zero amount is considered equal across currencies and to numeric zero (`Mint.money(0, 'USD') == Mint.money(0, 'EUR')` is intentionally `true`). Non-zero amounts must match currency and value.
220
+ **Zero equality** — Any zero amount is considered equal across currencies and to numeric zero (`Money.from(0, 'USD') == Money.from(0, 'EUR')` is intentionally `true`). Non-zero amounts must match currency and value.
216
221
 
217
222
  **Zero helper** — `Currency.zero('USD')` returns a frozen zero-Money, useful as a default value for discounts, totals, or counters.
218
223
 
data/Rakefile CHANGED
@@ -15,46 +15,42 @@ Rake::TestTask.new(:test) do |t|
15
15
  end
16
16
 
17
17
  Rake::TestTask.new('bench:all') do |t|
18
- t.libs = %w[lib test]
19
- t.pattern = 'test/performance/{core,memory,regression,competitive/money}/*_benchmark.rb'
18
+ t.libs = %w[lib bench]
19
+ t.pattern = 'bench/{core,memory,regression}/*_benchmark.rb'
20
20
  end
21
21
 
22
22
  Rake::TestTask.new('bench:core') do |t|
23
- t.libs = %w[lib test]
24
- t.pattern = 'test/performance/core/parse_benchmark.rb'
23
+ t.libs = %w[lib bench]
24
+ t.pattern = 'bench/core/parse_benchmark.rb'
25
25
  end
26
26
 
27
27
  Rake::TestTask.new('bench:memory') do |t|
28
- t.libs = %w[lib test]
29
- t.pattern = 'test/performance/memory/*_benchmark.rb'
28
+ t.libs = %w[lib bench]
29
+ t.pattern = 'bench/memory/*_benchmark.rb'
30
30
  end
31
31
 
32
32
  Rake::TestTask.new('bench:regression') do |t|
33
- t.libs = %w[lib test]
34
- t.pattern = 'test/performance/regression/*_benchmark.rb'
33
+ t.libs = %w[lib bench]
34
+ t.pattern = 'bench/regression/*_benchmark.rb'
35
35
  end
36
36
 
37
37
  desc 'Run competitive benchmarks (Money gem)'
38
- task 'bench:competitive' do
39
- sh 'bundle exec ruby -Ilib -Itest -e "Dir[File.join(__dir__, \"test/performance/competitive/money/**/*_benchmark.rb\")].each { |f| require f }"'
38
+ task 'bench:against:money' do
39
+ dir = 'bench/competitive/money'
40
+ sh "BUNDLE_GEMFILE=#{dir}/Gemfile bundle exec ruby -Ilib -I#{dir} -Ibench -e \"Dir[File.join(__dir__, '#{dir}/**/*_benchmark.rb')].each { |f| require f }\""
40
41
  end
41
42
 
42
43
  desc 'Run competitive benchmarks (Shopify Money)'
43
- task 'bench:competitive:shopify' do
44
- sh 'BUNDLE_WITHOUT=money_bench bundle exec ruby -Ilib -Itest -e "Dir[File.join(__dir__, \"test/performance/competitive/shopify/**/*_benchmark.rb\")].each { |f| require f }"'
45
- end
46
-
47
- desc 'Run all competitive benchmarks (both Money and Shopify)'
48
- task 'bench:competitive:all' do
49
- sh 'bundle exec ruby -Ilib -Itest -e "Dir[File.join(__dir__, \"test/performance/competitive/money/**/*_benchmark.rb\")].each { |f| require f }"'
50
- sh 'BUNDLE_WITHOUT=money_bench bundle exec ruby -Ilib -Itest -e "Dir[File.join(__dir__, \"test/performance/competitive/shopify/**/*_benchmark.rb\")].each { |f| require f }"'
44
+ task 'bench:against:shopify' do
45
+ dir = 'bench/competitive/shopify'
46
+ sh "BUNDLE_GEMFILE=#{dir}/Gemfile bundle exec ruby -Ilib -I#{dir} -Ibench -e \"Dir[File.join(__dir__, '#{dir}/**/*_benchmark.rb')].each { |f| require f }\""
51
47
  end
52
48
 
53
49
  desc 'Run core benchmarks and update the baseline'
54
50
  task 'bench:baseline' do
55
51
  platform = RUBY_PLATFORM
56
- baseline = "test/performance/check/results/baseline-#{platform}.json"
57
- sh "ruby test/performance/check/runner.rb #{baseline}"
52
+ baseline = "bench/check/results/baseline-#{platform}.json"
53
+ sh "ruby bench/check/runner.rb #{baseline}"
58
54
  puts "Baseline updated for #{platform}."
59
55
  end
60
56
 
data/bin/bench_check CHANGED
@@ -5,7 +5,7 @@ require 'json'
5
5
  require 'tempfile'
6
6
 
7
7
  platform = RUBY_PLATFORM
8
- results_dir = File.expand_path('../test/performance/check/results', __dir__)
8
+ results_dir = File.expand_path('../bench/check/results', __dir__)
9
9
  baseline_path = File.join(results_dir, "baseline-#{platform}.json")
10
10
  threshold = (ARGV[0] || 0.80).to_f
11
11
 
@@ -17,7 +17,7 @@ end
17
17
  baseline = JSON.parse(File.read(baseline_path))
18
18
  current_json = Tempfile.new(%w[bench_current .json])
19
19
 
20
- unless system("bundle exec ruby test/performance/check/runner.rb #{current_json.path}")
20
+ unless system("bundle exec ruby bench/check/runner.rb #{current_json.path}")
21
21
  puts 'Benchmark runner failed.'
22
22
  exit 1
23
23
  end