shopify-money 1.2.1 → 2.0.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 +2 -2
- data/README.md +30 -16
- data/dev.yml +1 -1
- data/lib/money/core_extensions.rb +9 -1
- data/lib/money/deprecations.rb +4 -1
- data/lib/money/helpers.rb +0 -2
- data/lib/money/money.rb +2 -7
- data/lib/money/version.rb +1 -1
- data/lib/rubocop/cop/money/missing_currency.rb +2 -1
- data/lib/rubocop/cop/money/unsafe_to_money.rb +1 -1
- data/money.gemspec +1 -1
- data/spec/core_extensions_spec.rb +20 -2
- data/spec/deprecations_spec.rb +9 -0
- data/spec/helpers_spec.rb +2 -2
- data/spec/money_spec.rb +0 -7
- data/spec/rubocop/cop/money/missing_currency_spec.rb +7 -0
- data/spec/rubocop/cop/money/unsafe_to_money_spec.rb +6 -0
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 591c60e355144246085ac254fe82b099c85ab4bf7f1e37672b8082331bd9d0aa
|
4
|
+
data.tar.gz: 493384ced59c9a37ebc798b4cb499bd0532ea30243c8248704bf0df6f776ca0f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1867df0795206ccd5996b1d8471f23f60340ace3e5e685ddbb98f601402a7748aade38263dbc7f12971c1e4368919cb0122c53eacf0b96b96df44189be3ca32e
|
7
|
+
data.tar.gz: 9ed8869fce8e66c4e9aee275ac3a28c24db47fd2ae8537f2ff3ee100541f122cd9b8b87e7ca102567b976548eb04b53b06f6c560f2e6e12dc3ca506e0bb87f01
|
data/.github/workflows/tests.yml
CHANGED
data/README.md
CHANGED
@@ -1,20 +1,17 @@
|
|
1
1
|
# money
|
2
2
|
|
3
|
-
[](https://github.com/Shopify/money/actions?query=workflow%3Atests+branch%
|
3
|
+
[](https://github.com/Shopify/money/actions?query=workflow%3Atests+branch%3Amain)
|
4
4
|
|
5
5
|
|
6
6
|
money_column expects a DECIMAL(21,3) database field.
|
7
7
|
|
8
8
|
### Features
|
9
9
|
|
10
|
-
-
|
11
|
-
- Provides a `Money` class which encapsulates all information about
|
12
|
-
|
13
|
-
-
|
14
|
-
|
15
|
-
- Does NOT provides APIs for exchanging money from one currency to another.
|
16
|
-
- wont lose pennies during division!
|
17
|
-
- Money::NullCurrency for no currency support
|
10
|
+
- Provides a `Money` class which encapsulates all information about a certain amount of money, such as its value and its currency.
|
11
|
+
- Provides a `Money::Currency` class which encapsulates all information about a monetary unit.
|
12
|
+
- Represents monetary values as decimals. No need to convert your amounts every time you use them. Easily understand the data in your DB.
|
13
|
+
- Does NOT provide APIs for exchanging money from one currency to another.
|
14
|
+
- Will not lose pennies during divisions
|
18
15
|
|
19
16
|
## Installation
|
20
17
|
|
@@ -22,7 +19,7 @@ money_column expects a DECIMAL(21,3) database field.
|
|
22
19
|
|
23
20
|
## Upgrading to v1.0
|
24
21
|
|
25
|
-
see instructions and breaking changes: https://github.com/Shopify/money/blob/
|
22
|
+
see instructions and breaking changes: https://github.com/Shopify/money/blob/main/UPGRADING.md
|
26
23
|
|
27
24
|
## Usage
|
28
25
|
|
@@ -32,7 +29,7 @@ require 'money'
|
|
32
29
|
# 10.00 USD
|
33
30
|
money = Money.new(10.00, "USD")
|
34
31
|
money.subunits #=> 1000
|
35
|
-
money.currency
|
32
|
+
money.currency #=> Money::Currency.new("USD")
|
36
33
|
|
37
34
|
# Comparisons
|
38
35
|
Money.new(1000, "USD") == Money.new(1000, "USD") #=> true
|
@@ -43,13 +40,30 @@ Money.new(1000, "USD") != Money.new(1000, "EUR") #=> true
|
|
43
40
|
# Arithmetic
|
44
41
|
Money.new(1000, "USD") + Money.new(500, "USD") == Money.new(1500, "USD")
|
45
42
|
Money.new(1000, "USD") - Money.new(200, "USD") == Money.new(800, "USD")
|
46
|
-
Money.new(1000, "USD") / 5 == Money.new(200, "USD")
|
47
43
|
Money.new(1000, "USD") * 5 == Money.new(5000, "USD")
|
48
44
|
|
45
|
+
m = Money.new(1000, "USD")
|
46
|
+
# Splitting money evenly
|
47
|
+
m.split(2) == [Money.new(500, "USD"), Money.new(500, "USD")]
|
48
|
+
m.split(3).map(&:value) == [333.34, 333.33, 333.33]
|
49
|
+
m.calculate_splits(2) == { Money.new(500, "USD") => 2 }
|
50
|
+
m.calculate_splits(3) == { Money.new(333.34, "USD") => 1, Money.new(333.33, "USD") =>2 }
|
51
|
+
|
52
|
+
# Allocating money proportionally
|
53
|
+
m.allocate([0.50, 0.25, 0.25]).map(&:value) == [500, 250, 250]
|
54
|
+
m.allocate([Rational(2, 3), Rational(1, 3)]).map(&:value) == [666.67, 333.33]
|
55
|
+
|
56
|
+
## Allocating up to a cutoff
|
57
|
+
m.allocate_max_amounts([500, 300, 200]).map(&:value) == [500, 300, 200]
|
58
|
+
m.allocate_max_amounts([500, 300, 300]).map(&:value) == [454.55, 272.73, 272.72]
|
59
|
+
|
60
|
+
# Clamp
|
61
|
+
Money.new(50, "USD").clamp(1, 100) == Money.new(50, "USD")
|
62
|
+
|
49
63
|
# Unit to subunit conversions
|
50
|
-
Money.from_subunits(500, "USD")
|
51
|
-
Money.from_subunits(5, "JPY")
|
52
|
-
Money.from_subunits(5000, "TND") == Money.new(5, "TND")
|
64
|
+
Money.from_subunits(500, "USD") == Money.new(5, "USD") # 5 USD
|
65
|
+
Money.from_subunits(5, "JPY") == Money.new(5, "JPY") # 5 JPY
|
66
|
+
Money.from_subunits(5000, "TND") == Money.new(5, "TND") # 5 TND
|
53
67
|
```
|
54
68
|
|
55
69
|
## Currency
|
@@ -171,7 +185,7 @@ Money/UnsafeToMoney:
|
|
171
185
|
|
172
186
|
## Contributing to money
|
173
187
|
|
174
|
-
- Check out the latest
|
188
|
+
- Check out the latest main to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
175
189
|
- Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
176
190
|
- Fork the project
|
177
191
|
- Start a feature/bugfix branch
|
data/dev.yml
CHANGED
@@ -14,6 +14,14 @@ end
|
|
14
14
|
# '100.37'.to_money => #<Money @cents=10037>
|
15
15
|
class String
|
16
16
|
def to_money(currency = nil)
|
17
|
-
Money
|
17
|
+
if Money.config.legacy_deprecations
|
18
|
+
Money::Parser::Fuzzy.parse(self, currency).tap do |money|
|
19
|
+
message = "`#{self}.to_money` will behave like `Money.new` and raise on the next release. " \
|
20
|
+
"To parse user input, do so on the browser and use the user's locale."
|
21
|
+
Money.deprecate(message) if money.value != BigDecimal(self, exception: false)
|
22
|
+
end
|
23
|
+
else
|
24
|
+
Money.new(self, currency)
|
25
|
+
end
|
18
26
|
end
|
19
27
|
end
|
data/lib/money/deprecations.rb
CHANGED
@@ -3,7 +3,10 @@ Money.class_eval do
|
|
3
3
|
ACTIVE_SUPPORT_DEFINED = defined?(ActiveSupport)
|
4
4
|
|
5
5
|
def self.active_support_deprecator
|
6
|
-
@active_support_deprecator ||=
|
6
|
+
@active_support_deprecator ||= begin
|
7
|
+
next_major_version = Money::VERSION.split(".").first.to_i + 1
|
8
|
+
ActiveSupport::Deprecation.new("#{next_major_version}.0.0", "Shopify/Money")
|
9
|
+
end
|
7
10
|
end
|
8
11
|
|
9
12
|
def self.deprecate(message)
|
data/lib/money/helpers.rb
CHANGED
data/lib/money/money.rb
CHANGED
@@ -137,13 +137,8 @@ class Money
|
|
137
137
|
end
|
138
138
|
|
139
139
|
def *(numeric)
|
140
|
-
unless numeric.is_a?(Numeric)
|
141
|
-
|
142
|
-
Money.deprecate("Multiplying Money with #{numeric.class.name} is deprecated and will be removed in the next major release.")
|
143
|
-
else
|
144
|
-
raise ArgumentError, "Money objects can only be multiplied by a Numeric"
|
145
|
-
end
|
146
|
-
end
|
140
|
+
raise ArgumentError, "Money objects can only be multiplied by a Numeric" unless numeric.is_a?(Numeric)
|
141
|
+
|
147
142
|
return self if numeric == 1
|
148
143
|
Money.new(value.to_r * numeric, currency)
|
149
144
|
end
|
data/lib/money/version.rb
CHANGED
@@ -32,7 +32,8 @@ module RuboCop
|
|
32
32
|
PATTERN
|
33
33
|
|
34
34
|
def on_send(node)
|
35
|
-
money_new(node) do |
|
35
|
+
money_new(node) do |amount, currency_arg|
|
36
|
+
return if amount&.splat_type?
|
36
37
|
return if currency_arg
|
37
38
|
|
38
39
|
add_offense(node, message: 'Money is missing currency argument')
|
data/money.gemspec
CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |s|
|
|
22
22
|
s.add_development_dependency("database_cleaner", "~> 1.6")
|
23
23
|
s.add_development_dependency("sqlite3", "~> 1.4.2")
|
24
24
|
|
25
|
-
s.required_ruby_version = '>=
|
25
|
+
s.required_ruby_version = '>= 3.0'
|
26
26
|
|
27
27
|
s.files = `git ls-files`.split($/)
|
28
28
|
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
@@ -43,8 +43,26 @@ RSpec.describe String do
|
|
43
43
|
it_should_behave_like "an object supporting to_money"
|
44
44
|
|
45
45
|
it "parses an empty string to Money.zero" do
|
46
|
-
expect(
|
47
|
-
|
46
|
+
expect("".to_money("USD")).to eq(Money.new(0, "USD"))
|
47
|
+
|
48
|
+
configure(legacy_deprecations: true) do
|
49
|
+
expect(Money).to receive(:deprecate).once
|
50
|
+
expect(" ".to_money("CAD")).to eq(Money.new(0, "CAD"))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
it "#to_money to handle thousands delimiters" do
|
55
|
+
configure(legacy_deprecations: true) do
|
56
|
+
expect(Money).to receive(:deprecate).exactly(4).times
|
57
|
+
expect("29.000".to_money("USD")).to eq(Money.new("29000", "USD"))
|
58
|
+
expect("29.000,00".to_money("USD")).to eq(Money.new("29000", "USD"))
|
59
|
+
expect("29,000".to_money("USD")).to eq(Money.new("29000", "USD"))
|
60
|
+
expect("29,000.00".to_money("USD")).to eq(Money.new("29000", "USD"))
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
it "#to_money should behave like Money.new with three decimal places amounts" do
|
65
|
+
expect("29.000".to_money("USD")).to eq(Money.new("29.00", "USD"))
|
48
66
|
end
|
49
67
|
end
|
50
68
|
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
RSpec.describe "deprecations" do
|
5
|
+
it "has the deprecation_horizon as the next major release" do
|
6
|
+
allow(Money).to receive(:const_get).with('VERSION').and_return("2.0.0")
|
7
|
+
expect(Money.active_support_deprecator.deprecation_horizon).to eq("3.0.0")
|
8
|
+
end
|
9
|
+
end
|
data/spec/helpers_spec.rb
CHANGED
@@ -7,8 +7,8 @@ RSpec.describe Money::Helpers do
|
|
7
7
|
let (:amount) { BigDecimal('1.23') }
|
8
8
|
let (:money) { Money.new(amount) }
|
9
9
|
|
10
|
-
it '
|
11
|
-
expect
|
10
|
+
it 'raises when provided with a money object' do
|
11
|
+
expect { subject.value_to_decimal(money) }.to raise_error(ArgumentError)
|
12
12
|
end
|
13
13
|
|
14
14
|
it 'returns itself if it is already a big decimal' do
|
data/spec/money_spec.rb
CHANGED
@@ -290,13 +290,6 @@ RSpec.describe "Money" do
|
|
290
290
|
expect(((1.0 / 12) * Money.new(3.3))).to eq(Money.new(0.28))
|
291
291
|
end
|
292
292
|
|
293
|
-
it "legacy_deprecations is multipliable by a money object" do
|
294
|
-
configure(legacy_deprecations: true) do
|
295
|
-
expect(Money).to receive(:deprecate).once
|
296
|
-
expect((Money.new(3.3, 'USD') * Money.new(1, 'USD'))).to eq(Money.new(3.3, 'USD'))
|
297
|
-
end
|
298
|
-
end
|
299
|
-
|
300
293
|
it "raises when multiplied by a money object" do
|
301
294
|
expect{ (Money.new(3.3) * Money.new(1)) }.to raise_error(ArgumentError)
|
302
295
|
end
|
@@ -26,6 +26,13 @@ RSpec.describe RuboCop::Cop::Money::MissingCurrency do
|
|
26
26
|
RUBY
|
27
27
|
end
|
28
28
|
|
29
|
+
it 'does not register an offense for Money.new with splat argument' do
|
30
|
+
expect_no_offenses(<<~RUBY)
|
31
|
+
value_and_currency = [1, 'CAD']
|
32
|
+
Money.new(*value_and_currency)
|
33
|
+
RUBY
|
34
|
+
end
|
35
|
+
|
29
36
|
it 'registers an offense and corrects for Money.new without a currency argument' do
|
30
37
|
expect_offense(<<~RUBY)
|
31
38
|
Money.new
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shopify-money
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify Inc
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -149,6 +149,7 @@ files:
|
|
149
149
|
- spec/core_extensions_spec.rb
|
150
150
|
- spec/currency/loader_spec.rb
|
151
151
|
- spec/currency_spec.rb
|
152
|
+
- spec/deprecations_spec.rb
|
152
153
|
- spec/helpers_spec.rb
|
153
154
|
- spec/money_column_spec.rb
|
154
155
|
- spec/money_spec.rb
|
@@ -178,14 +179,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
178
179
|
requirements:
|
179
180
|
- - ">="
|
180
181
|
- !ruby/object:Gem::Version
|
181
|
-
version: '
|
182
|
+
version: '3.0'
|
182
183
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
183
184
|
requirements:
|
184
185
|
- - ">="
|
185
186
|
- !ruby/object:Gem::Version
|
186
187
|
version: '0'
|
187
188
|
requirements: []
|
188
|
-
rubygems_version: 3.
|
189
|
+
rubygems_version: 3.5.5
|
189
190
|
signing_key:
|
190
191
|
specification_version: 4
|
191
192
|
summary: Shopify's money gem
|
@@ -195,6 +196,7 @@ test_files:
|
|
195
196
|
- spec/core_extensions_spec.rb
|
196
197
|
- spec/currency/loader_spec.rb
|
197
198
|
- spec/currency_spec.rb
|
199
|
+
- spec/deprecations_spec.rb
|
198
200
|
- spec/helpers_spec.rb
|
199
201
|
- spec/money_column_spec.rb
|
200
202
|
- spec/money_spec.rb
|