shopify-money 2.0.0 → 2.2.1
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/.gitignore +1 -2
- data/.ruby-version +1 -0
- data/Gemfile.lock +234 -0
- data/README.md +43 -9
- data/dev.yml +1 -1
- data/lib/money/allocator.rb +57 -25
- data/lib/money/helpers.rb +2 -0
- data/lib/money/money.rb +87 -53
- data/lib/money/splitter.rb +115 -0
- data/lib/money/version.rb +1 -1
- data/lib/money.rb +1 -0
- data/lib/rubocop/cop/money.rb +0 -1
- data/money.gemspec +1 -1
- data/spec/allocator_spec.rb +175 -25
- data/spec/deprecations_spec.rb +1 -1
- data/spec/helpers_spec.rb +2 -2
- data/spec/money_spec.rb +137 -7
- data/spec/splitter_spec.rb +104 -0
- metadata +12 -10
- data/lib/rubocop/cop/money/unsafe_to_money.rb +0 -35
- data/spec/rubocop/cop/money/unsafe_to_money_spec.rb +0 -63
data/spec/money_spec.rb
CHANGED
@@ -30,15 +30,30 @@ RSpec.describe "Money" do
|
|
30
30
|
|
31
31
|
it "returns itself with to_money" do
|
32
32
|
expect(money.to_money).to eq(money)
|
33
|
+
expect(amount_money.to_money).to eq(amount_money)
|
33
34
|
end
|
34
35
|
|
35
36
|
it "#to_money uses the provided currency when it doesn't already have one" do
|
36
37
|
expect(Money.new(1).to_money('CAD')).to eq(Money.new(1, 'CAD'))
|
37
38
|
end
|
38
39
|
|
40
|
+
it "#to_money works with money objects of the same currency" do
|
41
|
+
expect(Money.new(1, 'CAD').to_money('CAD')).to eq(Money.new(1, 'CAD'))
|
42
|
+
end
|
43
|
+
|
44
|
+
it "#to_money works with money objects that doesn't have a currency" do
|
45
|
+
money = Money.new(1, Money::NULL_CURRENCY).to_money('USD')
|
46
|
+
expect(money.value).to eq(1)
|
47
|
+
expect(money.currency.to_s).to eq('USD')
|
48
|
+
|
49
|
+
money = Money.new(1, 'USD').to_money(Money::NULL_CURRENCY)
|
50
|
+
expect(money.value).to eq(1)
|
51
|
+
expect(money.currency.to_s).to eq('USD')
|
52
|
+
end
|
53
|
+
|
39
54
|
it "legacy_deprecations #to_money doesn't overwrite the money object's currency" do
|
40
55
|
configure(legacy_deprecations: true) do
|
41
|
-
expect(Money).to receive(:deprecate).once
|
56
|
+
expect(Money).to receive(:deprecate).with(match(/to_money is attempting to change currency of an existing money object/)).once
|
42
57
|
expect(Money.new(1, 'USD').to_money('CAD')).to eq(Money.new(1, 'USD'))
|
43
58
|
end
|
44
59
|
end
|
@@ -55,6 +70,40 @@ RSpec.describe "Money" do
|
|
55
70
|
expect(Money.new('')).to eq(Money.new(0))
|
56
71
|
end
|
57
72
|
|
73
|
+
it "can be constructed with a string" do
|
74
|
+
expect(Money.new('1')).to eq(Money.new(1))
|
75
|
+
end
|
76
|
+
|
77
|
+
it "can be constructed with a numeric" do
|
78
|
+
expect(Money.new(1.00)).to eq(Money.new(1))
|
79
|
+
end
|
80
|
+
|
81
|
+
it "can be constructed with a money object" do
|
82
|
+
expect(Money.new(Money.new(1))).to eq(Money.new(1))
|
83
|
+
expect(Money.new(Money.new(1, "USD"), "USD")).to eq(Money.new(1, "USD"))
|
84
|
+
end
|
85
|
+
|
86
|
+
it "can be constructed with a money object with a null currency" do
|
87
|
+
money = Money.new(Money.new(1, Money::NULL_CURRENCY), 'USD')
|
88
|
+
expect(money.value).to eq(1)
|
89
|
+
expect(money.currency.to_s).to eq('USD')
|
90
|
+
|
91
|
+
money = Money.new(Money.new(1, 'USD'), Money::NULL_CURRENCY)
|
92
|
+
expect(money.value).to eq(1)
|
93
|
+
expect(money.currency.to_s).to eq('USD')
|
94
|
+
end
|
95
|
+
|
96
|
+
it "constructor raises when changing currency" do
|
97
|
+
expect { Money.new(Money.new(1, 'USD'), 'CAD') }.to raise_error(Money::IncompatibleCurrencyError)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "legacy_deprecations constructor with money used the constructor currency" do
|
101
|
+
configure(legacy_deprecations: true) do
|
102
|
+
expect(Money).to receive(:deprecate).with(match(/Money.new is attempting to change currency of an existing money object/)).once
|
103
|
+
expect(Money.new(Money.new(1, 'USD'), 'CAD')).to eq(Money.new(1, 'CAD'))
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
58
107
|
it "legacy_deprecations defaults to 0 when constructed with an invalid string" do
|
59
108
|
configure(legacy_deprecations: true) do
|
60
109
|
expect(Money).to receive(:deprecate).once
|
@@ -192,7 +241,7 @@ RSpec.describe "Money" do
|
|
192
241
|
|
193
242
|
it "logs a deprecation warning when adding across currencies" do
|
194
243
|
configure(legacy_deprecations: true) do
|
195
|
-
expect(Money).to receive(:deprecate)
|
244
|
+
expect(Money).to receive(:deprecate).with(match(/mathematical operation not permitted for Money objects with different currencies/))
|
196
245
|
expect(Money.new(10, 'USD') - Money.new(1, 'JPY')).to eq(Money.new(9, 'USD'))
|
197
246
|
end
|
198
247
|
end
|
@@ -528,13 +577,49 @@ RSpec.describe "Money" do
|
|
528
577
|
it { expect(cad_10 == usd_10).to(eq(false)) }
|
529
578
|
end
|
530
579
|
|
531
|
-
describe('
|
580
|
+
describe('coerced types') do
|
532
581
|
it { expect(cad_10 <=> 10.00).to(eq(0)) }
|
533
582
|
it { expect(cad_10 > 10.00).to(eq(false)) }
|
534
583
|
it { expect(cad_10 >= 10.00).to(eq(true)) }
|
535
584
|
it { expect(cad_10 == 10.00).to(eq(false)) }
|
536
585
|
it { expect(cad_10 <= 10.00).to(eq(true)) }
|
537
586
|
it { expect(cad_10 < 10.00).to(eq(false)) }
|
587
|
+
it { expect(cad_10 <=>'10.00').to(eq(0)) }
|
588
|
+
it { expect(cad_10 > '10.00').to(eq(false)) }
|
589
|
+
it { expect(cad_10 >= '10.00').to(eq(true)) }
|
590
|
+
it { expect(cad_10 == '10.00').to(eq(false)) }
|
591
|
+
it { expect(cad_10 <= '10.00').to(eq(true)) }
|
592
|
+
it { expect(cad_10 < '10.00').to(eq(false)) }
|
593
|
+
end
|
594
|
+
|
595
|
+
describe('to_money coerced types') do
|
596
|
+
let(:coercible_object) do
|
597
|
+
double("coercible_object").tap do |mock|
|
598
|
+
allow(mock).to receive(:to_money).with(any_args) { |currency| Money.new(10, currency) }
|
599
|
+
end
|
600
|
+
end
|
601
|
+
|
602
|
+
it { expect { cad_10 <=> coercible_object }.to(raise_error(TypeError)) }
|
603
|
+
it { expect { cad_10 > coercible_object }.to(raise_error(TypeError)) }
|
604
|
+
it { expect { cad_10 >= coercible_object }.to(raise_error(TypeError)) }
|
605
|
+
it { expect { cad_10 <= coercible_object }.to(raise_error(TypeError)) }
|
606
|
+
it { expect { cad_10 < coercible_object }.to(raise_error(TypeError)) }
|
607
|
+
it { expect { cad_10 + coercible_object }.to(raise_error(TypeError)) }
|
608
|
+
it { expect { cad_10 - coercible_object }.to(raise_error(TypeError)) }
|
609
|
+
|
610
|
+
describe('with legacy_deprecations') do
|
611
|
+
around(:each) do |test|
|
612
|
+
configure(legacy_deprecations: true) { test.run }
|
613
|
+
end
|
614
|
+
|
615
|
+
it { expect(Money).to(receive(:deprecate).once); expect(cad_10 <=> coercible_object).to(eq(0)) }
|
616
|
+
it { expect(Money).to(receive(:deprecate).once); expect(cad_10 > coercible_object).to(eq(false)) }
|
617
|
+
it { expect(Money).to(receive(:deprecate).once); expect(cad_10 >= coercible_object).to(eq(true)) }
|
618
|
+
it { expect(Money).to(receive(:deprecate).once); expect(cad_10 <= coercible_object).to(eq(true)) }
|
619
|
+
it { expect(Money).to(receive(:deprecate).once); expect(cad_10 < coercible_object).to(eq(false)) }
|
620
|
+
it { expect(Money).to(receive(:deprecate).once); expect(cad_10 + coercible_object).to(eq(Money.new(20, 'CAD'))) }
|
621
|
+
it { expect(Money).to(receive(:deprecate).once); expect(cad_10 - coercible_object).to(eq(Money.new(0, 'CAD'))) }
|
622
|
+
end
|
538
623
|
end
|
539
624
|
end
|
540
625
|
|
@@ -723,22 +808,32 @@ RSpec.describe "Money" do
|
|
723
808
|
specify "#split needs at least one party" do
|
724
809
|
expect {Money.new(1).split(0)}.to raise_error(ArgumentError)
|
725
810
|
expect {Money.new(1).split(-1)}.to raise_error(ArgumentError)
|
811
|
+
expect {Money.new(1).split(0.1)}.to raise_error(ArgumentError)
|
812
|
+
expect(Money.new(1).split(BigDecimal("0.1e1")).to_a).to eq([Money.new(1)])
|
813
|
+
end
|
814
|
+
|
815
|
+
specify "#split can be zipped" do
|
816
|
+
expect(Money.new(100).split(3).zip(Money.new(50).split(3)).to_a).to eq([
|
817
|
+
[Money.new(33.34), Money.new(16.67)],
|
818
|
+
[Money.new(33.33), Money.new(16.67)],
|
819
|
+
[Money.new(33.33), Money.new(16.66)],
|
820
|
+
])
|
726
821
|
end
|
727
822
|
|
728
823
|
specify "#gives 1 cent to both people if we start with 2" do
|
729
|
-
expect(Money.new(0.02).split(2)).to eq([Money.new(0.01), Money.new(0.01)])
|
824
|
+
expect(Money.new(0.02).split(2).to_a).to eq([Money.new(0.01), Money.new(0.01)])
|
730
825
|
end
|
731
826
|
|
732
827
|
specify "#split may distribute no money to some parties if there isnt enough to go around" do
|
733
|
-
expect(Money.new(0.02).split(3)).to eq([Money.new(0.01), Money.new(0.01), Money.new(0)])
|
828
|
+
expect(Money.new(0.02).split(3).to_a).to eq([Money.new(0.01), Money.new(0.01), Money.new(0)])
|
734
829
|
end
|
735
830
|
|
736
831
|
specify "#split does not lose pennies" do
|
737
|
-
expect(Money.new(0.05).split(2)).to eq([Money.new(0.03), Money.new(0.02)])
|
832
|
+
expect(Money.new(0.05).split(2).to_a).to eq([Money.new(0.03), Money.new(0.02)])
|
738
833
|
end
|
739
834
|
|
740
835
|
specify "#split does not lose dollars with non-decimal currencies" do
|
741
|
-
expect(Money.new(5, 'JPY').split(2)).to eq([Money.new(3, 'JPY'), Money.new(2, 'JPY')])
|
836
|
+
expect(Money.new(5, 'JPY').split(2).to_a).to eq([Money.new(3, 'JPY'), Money.new(2, 'JPY')])
|
742
837
|
end
|
743
838
|
|
744
839
|
specify "#split a dollar" do
|
@@ -754,6 +849,41 @@ RSpec.describe "Money" do
|
|
754
849
|
expect(moneys[1].value).to eq(33)
|
755
850
|
expect(moneys[2].value).to eq(33)
|
756
851
|
end
|
852
|
+
|
853
|
+
specify "#split return respond to #first" do
|
854
|
+
expect(Money.new(100).split(3).first).to eq(Money.new(33.34))
|
855
|
+
expect(Money.new(100).split(3).first(2)).to eq([Money.new(33.34), Money.new(33.33)])
|
856
|
+
|
857
|
+
expect(Money.new(100).split(10).first).to eq(Money.new(10))
|
858
|
+
expect(Money.new(100).split(10).first(2)).to eq([Money.new(10), Money.new(10)])
|
859
|
+
expect(Money.new(20).split(2).first(4)).to eq([Money.new(10), Money.new(10)])
|
860
|
+
end
|
861
|
+
|
862
|
+
specify "#split return respond to #last" do
|
863
|
+
expect(Money.new(100).split(3).last).to eq(Money.new(33.33))
|
864
|
+
expect(Money.new(100).split(3).last(2)).to eq([Money.new(33.33), Money.new(33.33)])
|
865
|
+
expect(Money.new(20).split(2).last(4)).to eq([Money.new(10), Money.new(10)])
|
866
|
+
end
|
867
|
+
|
868
|
+
specify "#split return supports destructuring" do
|
869
|
+
first, second = Money.new(100).split(3)
|
870
|
+
expect(first).to eq(Money.new(33.34))
|
871
|
+
expect(second).to eq(Money.new(33.33))
|
872
|
+
|
873
|
+
first, *rest = Money.new(100).split(3)
|
874
|
+
expect(first).to eq(Money.new(33.34))
|
875
|
+
expect(rest).to eq([Money.new(33.33), Money.new(33.33)])
|
876
|
+
end
|
877
|
+
|
878
|
+
specify "#split return can be reversed" do
|
879
|
+
list = Money.new(100).split(3)
|
880
|
+
expect(list.first).to eq(Money.new(33.34))
|
881
|
+
expect(list.last).to eq(Money.new(33.33))
|
882
|
+
|
883
|
+
list = list.reverse
|
884
|
+
expect(list.first).to eq(Money.new(33.33))
|
885
|
+
expect(list.last).to eq(Money.new(33.34))
|
886
|
+
end
|
757
887
|
end
|
758
888
|
|
759
889
|
describe "calculate_splits" do
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
RSpec.describe "Money::Splitter" do
|
6
|
+
specify "#split needs at least one party" do
|
7
|
+
expect {Money.new(1).split(0)}.to raise_error(ArgumentError)
|
8
|
+
expect {Money.new(1).split(-1)}.to raise_error(ArgumentError)
|
9
|
+
expect {Money.new(1).split(0.1)}.to raise_error(ArgumentError)
|
10
|
+
expect(Money.new(1).split(BigDecimal("0.1e1")).to_a).to eq([Money.new(1)])
|
11
|
+
end
|
12
|
+
|
13
|
+
specify "#split can be zipped" do
|
14
|
+
expect(Money.new(100).split(3).zip(Money.new(50).split(3)).to_a).to eq([
|
15
|
+
[Money.new(33.34), Money.new(16.67)],
|
16
|
+
[Money.new(33.33), Money.new(16.67)],
|
17
|
+
[Money.new(33.33), Money.new(16.66)],
|
18
|
+
])
|
19
|
+
end
|
20
|
+
|
21
|
+
specify "#gives 1 cent to both people if we start with 2" do
|
22
|
+
expect(Money.new(0.02).split(2).to_a).to eq([Money.new(0.01), Money.new(0.01)])
|
23
|
+
end
|
24
|
+
|
25
|
+
specify "#split may distribute no money to some parties if there isnt enough to go around" do
|
26
|
+
expect(Money.new(0.02).split(3).to_a).to eq([Money.new(0.01), Money.new(0.01), Money.new(0)])
|
27
|
+
end
|
28
|
+
|
29
|
+
specify "#split does not lose pennies" do
|
30
|
+
expect(Money.new(0.05).split(2).to_a).to eq([Money.new(0.03), Money.new(0.02)])
|
31
|
+
end
|
32
|
+
|
33
|
+
specify "#split does not lose dollars with non-decimal currencies" do
|
34
|
+
expect(Money.new(5, 'JPY').split(2).to_a).to eq([Money.new(3, 'JPY'), Money.new(2, 'JPY')])
|
35
|
+
end
|
36
|
+
|
37
|
+
specify "#split a dollar" do
|
38
|
+
moneys = Money.new(1).split(3)
|
39
|
+
expect(moneys[0].subunits).to eq(34)
|
40
|
+
expect(moneys[1].subunits).to eq(33)
|
41
|
+
expect(moneys[2].subunits).to eq(33)
|
42
|
+
end
|
43
|
+
|
44
|
+
specify "#split a 100 yen" do
|
45
|
+
moneys = Money.new(100, 'JPY').split(3)
|
46
|
+
expect(moneys[0].value).to eq(34)
|
47
|
+
expect(moneys[1].value).to eq(33)
|
48
|
+
expect(moneys[2].value).to eq(33)
|
49
|
+
end
|
50
|
+
|
51
|
+
specify "#split return respond to #first" do
|
52
|
+
expect(Money.new(100).split(3).first).to eq(Money.new(33.34))
|
53
|
+
expect(Money.new(100).split(3).first(2)).to eq([Money.new(33.34), Money.new(33.33)])
|
54
|
+
|
55
|
+
expect(Money.new(100).split(10).first).to eq(Money.new(10))
|
56
|
+
expect(Money.new(100).split(10).first(2)).to eq([Money.new(10), Money.new(10)])
|
57
|
+
expect(Money.new(20).split(2).first(4)).to eq([Money.new(10), Money.new(10)])
|
58
|
+
end
|
59
|
+
|
60
|
+
specify "#split return respond to #last" do
|
61
|
+
expect(Money.new(100).split(3).last).to eq(Money.new(33.33))
|
62
|
+
expect(Money.new(100).split(3).last(2)).to eq([Money.new(33.33), Money.new(33.33)])
|
63
|
+
expect(Money.new(20).split(2).last(4)).to eq([Money.new(10), Money.new(10)])
|
64
|
+
end
|
65
|
+
|
66
|
+
specify "#split return supports destructuring" do
|
67
|
+
first, second = Money.new(100).split(3)
|
68
|
+
expect(first).to eq(Money.new(33.34))
|
69
|
+
expect(second).to eq(Money.new(33.33))
|
70
|
+
|
71
|
+
first, *rest = Money.new(100).split(3)
|
72
|
+
expect(first).to eq(Money.new(33.34))
|
73
|
+
expect(rest).to eq([Money.new(33.33), Money.new(33.33)])
|
74
|
+
end
|
75
|
+
|
76
|
+
specify "#split return can be reversed" do
|
77
|
+
list = Money.new(100).split(3)
|
78
|
+
expect(list.first).to eq(Money.new(33.34))
|
79
|
+
expect(list.last).to eq(Money.new(33.33))
|
80
|
+
|
81
|
+
list = list.reverse
|
82
|
+
expect(list.first).to eq(Money.new(33.33))
|
83
|
+
expect(list.last).to eq(Money.new(33.34))
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "calculate_splits" do
|
87
|
+
specify "#calculate_splits gives 1 cent to both people if we start with 2" do
|
88
|
+
actual = Money.new(0.02, 'CAD').calculate_splits(2)
|
89
|
+
|
90
|
+
expect(actual).to eq({
|
91
|
+
Money.new(0.01, 'CAD') => 2,
|
92
|
+
})
|
93
|
+
end
|
94
|
+
|
95
|
+
specify "#calculate_splits gives an extra penny to one" do
|
96
|
+
actual = Money.new(0.04, 'CAD').calculate_splits(3)
|
97
|
+
|
98
|
+
expect(actual).to eq({
|
99
|
+
Money.new(0.02, 'CAD') => 1,
|
100
|
+
Money.new(0.01, 'CAD') => 2,
|
101
|
+
})
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
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: 2.
|
4
|
+
version: 2.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify Inc
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-04-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -84,16 +84,16 @@ dependencies:
|
|
84
84
|
name: sqlite3
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - "
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
89
|
+
version: '0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - "
|
94
|
+
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
96
|
+
version: '0'
|
97
97
|
description: Manage money in Shopify with a class that wont lose pennies during division!
|
98
98
|
email: gems@shopify.com
|
99
99
|
executables:
|
@@ -106,7 +106,9 @@ files:
|
|
106
106
|
- ".github/workflows/tests.yml"
|
107
107
|
- ".gitignore"
|
108
108
|
- ".rspec"
|
109
|
+
- ".ruby-version"
|
109
110
|
- Gemfile
|
111
|
+
- Gemfile.lock
|
110
112
|
- LICENSE.txt
|
111
113
|
- README.md
|
112
114
|
- Rakefile
|
@@ -133,6 +135,7 @@ files:
|
|
133
135
|
- lib/money/parser/simple.rb
|
134
136
|
- lib/money/rails/job_argument_serializer.rb
|
135
137
|
- lib/money/railtie.rb
|
138
|
+
- lib/money/splitter.rb
|
136
139
|
- lib/money/version.rb
|
137
140
|
- lib/money_column.rb
|
138
141
|
- lib/money_column/active_record_hooks.rb
|
@@ -140,7 +143,6 @@ files:
|
|
140
143
|
- lib/money_column/railtie.rb
|
141
144
|
- lib/rubocop/cop/money.rb
|
142
145
|
- lib/rubocop/cop/money/missing_currency.rb
|
143
|
-
- lib/rubocop/cop/money/unsafe_to_money.rb
|
144
146
|
- lib/rubocop/cop/money/zero_money.rb
|
145
147
|
- lib/shopify-money.rb
|
146
148
|
- money.gemspec
|
@@ -161,11 +163,11 @@ files:
|
|
161
163
|
- spec/rails/job_argument_serializer_spec.rb
|
162
164
|
- spec/rails_spec_helper.rb
|
163
165
|
- spec/rubocop/cop/money/missing_currency_spec.rb
|
164
|
-
- spec/rubocop/cop/money/unsafe_to_money_spec.rb
|
165
166
|
- spec/rubocop/cop/money/zero_money_spec.rb
|
166
167
|
- spec/rubocop_helper.rb
|
167
168
|
- spec/schema.rb
|
168
169
|
- spec/spec_helper.rb
|
170
|
+
- spec/splitter_spec.rb
|
169
171
|
homepage: https://github.com/Shopify/money
|
170
172
|
licenses:
|
171
173
|
- MIT
|
@@ -186,7 +188,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
186
188
|
- !ruby/object:Gem::Version
|
187
189
|
version: '0'
|
188
190
|
requirements: []
|
189
|
-
rubygems_version: 3.5.
|
191
|
+
rubygems_version: 3.5.9
|
190
192
|
signing_key:
|
191
193
|
specification_version: 4
|
192
194
|
summary: Shopify's money gem
|
@@ -208,8 +210,8 @@ test_files:
|
|
208
210
|
- spec/rails/job_argument_serializer_spec.rb
|
209
211
|
- spec/rails_spec_helper.rb
|
210
212
|
- spec/rubocop/cop/money/missing_currency_spec.rb
|
211
|
-
- spec/rubocop/cop/money/unsafe_to_money_spec.rb
|
212
213
|
- spec/rubocop/cop/money/zero_money_spec.rb
|
213
214
|
- spec/rubocop_helper.rb
|
214
215
|
- spec/schema.rb
|
215
216
|
- spec/spec_helper.rb
|
217
|
+
- spec/splitter_spec.rb
|
@@ -1,35 +0,0 @@
|
|
1
|
-
|
2
|
-
module RuboCop
|
3
|
-
module Cop
|
4
|
-
module Money
|
5
|
-
# Prevents the use of `to_money` because it has inconsistent behaviour.
|
6
|
-
# Use `Money.new` instead.
|
7
|
-
#
|
8
|
-
# @example
|
9
|
-
# # bad
|
10
|
-
# "2.000".to_money("USD") #<Money value:2000.00 currency:USD>
|
11
|
-
#
|
12
|
-
# # good
|
13
|
-
# Money.new("2.000", "USD") #<Money value:2.00 currency:USD>
|
14
|
-
class UnsafeToMoney < Cop
|
15
|
-
MSG = '`to_money` has inconsistent behaviour. Use `Money.new` instead.'.freeze
|
16
|
-
|
17
|
-
def on_send(node)
|
18
|
-
return unless node.method?(:to_money)
|
19
|
-
return if node.receiver.nil? || node.receiver.is_a?(AST::NumericNode)
|
20
|
-
|
21
|
-
add_offense(node, location: :selector)
|
22
|
-
end
|
23
|
-
|
24
|
-
def autocorrect(node)
|
25
|
-
lambda do |corrector|
|
26
|
-
receiver = node.receiver.source
|
27
|
-
args = node.arguments.map(&:source)
|
28
|
-
args.prepend(receiver)
|
29
|
-
corrector.replace(node.loc.expression, "Money.new(#{args.join(', ')})")
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1,63 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../../../rubocop_helper'
|
4
|
-
require 'rubocop/cop/money/unsafe_to_money'
|
5
|
-
|
6
|
-
RSpec.describe RuboCop::Cop::Money::UnsafeToMoney do
|
7
|
-
subject(:cop) { described_class.new(config) }
|
8
|
-
|
9
|
-
let(:config) { RuboCop::Config.new }
|
10
|
-
|
11
|
-
context 'with default configuration' do
|
12
|
-
it 'does not register an offense for literal integer' do
|
13
|
-
expect_no_offenses(<<~RUBY)
|
14
|
-
1.to_money
|
15
|
-
RUBY
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'does not register an offense for literal float' do
|
19
|
-
expect_no_offenses(<<~RUBY)
|
20
|
-
1.000.to_money
|
21
|
-
RUBY
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'registers an offense and corrects for Money.new without a currency argument' do
|
25
|
-
expect_offense(<<~RUBY)
|
26
|
-
'2.000'.to_money
|
27
|
-
^^^^^^^^ #{described_class::MSG}
|
28
|
-
RUBY
|
29
|
-
|
30
|
-
expect_correction(<<~RUBY)
|
31
|
-
Money.new('2.000')
|
32
|
-
RUBY
|
33
|
-
end
|
34
|
-
|
35
|
-
it 'registers an offense and corrects for Money.new with a currency argument' do
|
36
|
-
expect_offense(<<~RUBY)
|
37
|
-
'2.000'.to_money('USD')
|
38
|
-
^^^^^^^^ #{described_class::MSG}
|
39
|
-
RUBY
|
40
|
-
|
41
|
-
expect_correction(<<~RUBY)
|
42
|
-
Money.new('2.000', 'USD')
|
43
|
-
RUBY
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'registers an offense and corrects for Money.new with a complex receiver' do
|
47
|
-
expect_offense(<<~RUBY)
|
48
|
-
obj.money.to_money('USD')
|
49
|
-
^^^^^^^^ #{described_class::MSG}
|
50
|
-
RUBY
|
51
|
-
|
52
|
-
expect_correction(<<~RUBY)
|
53
|
-
Money.new(obj.money, 'USD')
|
54
|
-
RUBY
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'does not register an offense for receiver-less calls' do
|
58
|
-
expect_no_offenses(<<~RUBY)
|
59
|
-
a = to_money
|
60
|
-
RUBY
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|