shopify-money 0.14.6 → 1.0.0.pre
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 +34 -0
- data/README.md +8 -2
- data/UPGRADING.md +57 -0
- data/config/currency_historic.yml +1 -1
- data/lib/money.rb +1 -1
- data/lib/money/allocator.rb +3 -1
- data/lib/money/config.rb +26 -0
- data/lib/money/currency.rb +4 -0
- data/lib/money/helpers.rb +12 -4
- data/lib/money/money.rb +52 -35
- data/lib/money/money_parser.rb +11 -5
- data/lib/money/null_currency.rb +32 -1
- data/lib/money/version.rb +1 -1
- data/lib/money_column/active_record_hooks.rb +12 -7
- data/lib/rubocop/cop/money.rb +1 -0
- data/lib/rubocop/cop/money/missing_currency.rb +16 -8
- data/lib/rubocop/cop/money/zero_money.rb +65 -0
- data/money.gemspec +1 -1
- data/spec/accounting_money_parser_spec.rb +4 -2
- data/spec/allocator_spec.rb +3 -3
- data/spec/config_spec.rb +60 -0
- data/spec/core_extensions_spec.rb +5 -5
- data/spec/currency_spec.rb +10 -0
- data/spec/helpers_spec.rb +11 -5
- data/spec/money_column_spec.rb +55 -34
- data/spec/money_parser_spec.rb +20 -8
- data/spec/money_spec.rb +123 -90
- data/spec/rubocop/cop/money/missing_currency_spec.rb +43 -8
- data/spec/rubocop/cop/money/zero_money_spec.rb +78 -0
- data/spec/spec_helper.rb +15 -0
- metadata +14 -10
- data/.travis.yml +0 -13
- data/lib/money_accessor.rb +0 -33
- data/spec/money_accessor_spec.rb +0 -87
data/lib/money/version.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module MoneyColumn
|
3
|
+
class CurrencyReadOnlyError < StandardError; end
|
4
|
+
|
3
5
|
module ActiveRecordHooks
|
4
6
|
def self.included(base)
|
5
7
|
base.extend(ClassMethods)
|
@@ -49,16 +51,19 @@ module MoneyColumn
|
|
49
51
|
return self[column] = nil
|
50
52
|
end
|
51
53
|
|
52
|
-
|
53
|
-
|
54
|
-
if !money.is_a?(Money)
|
55
|
-
return self[column] = Money.new(money, currency_raw_source).value
|
54
|
+
unless money.is_a?(Money)
|
55
|
+
return self[column] = Money::Helpers.value_to_decimal(money)
|
56
56
|
end
|
57
57
|
|
58
58
|
if options[:currency_read_only]
|
59
|
-
|
60
|
-
if
|
61
|
-
|
59
|
+
currency = options[:currency] || try(options[:currency_column])
|
60
|
+
if currency && !money.currency.compatible?(Money::Helpers.value_to_currency(currency))
|
61
|
+
msg = "[money_column] currency mismatch between #{currency} and #{money.currency} in column #{column}."
|
62
|
+
if Money.config.legacy_deprecations
|
63
|
+
Money.deprecate(msg)
|
64
|
+
else
|
65
|
+
raise MoneyColumn::CurrencyReadOnlyError, msg
|
66
|
+
end
|
62
67
|
end
|
63
68
|
else
|
64
69
|
self[options[:currency_column]] = money.currency.to_s unless money.no_currency?
|
data/lib/rubocop/cop/money.rb
CHANGED
@@ -20,11 +20,11 @@ module RuboCop
|
|
20
20
|
#
|
21
21
|
|
22
22
|
def_node_matcher :money_new, <<~PATTERN
|
23
|
-
(send (const nil? :Money) {:new :from_amount :from_cents} $...)
|
23
|
+
(send (const {nil? cbase} :Money) {:new :from_amount :from_cents} $...)
|
24
24
|
PATTERN
|
25
25
|
|
26
26
|
def_node_matcher :to_money_without_currency?, <<~PATTERN
|
27
|
-
(send _ :to_money)
|
27
|
+
({send csend} _ :to_money)
|
28
28
|
PATTERN
|
29
29
|
|
30
30
|
def_node_matcher :to_money_block?, <<~PATTERN
|
@@ -42,11 +42,9 @@ module RuboCop
|
|
42
42
|
add_offense(node, message: 'to_money is missing currency argument')
|
43
43
|
end
|
44
44
|
end
|
45
|
+
alias on_csend on_send
|
45
46
|
|
46
47
|
def autocorrect(node)
|
47
|
-
currency = cop_config['ReplacementCurrency']
|
48
|
-
return unless currency
|
49
|
-
|
50
48
|
receiver, method, _ = *node
|
51
49
|
|
52
50
|
lambda do |corrector|
|
@@ -55,20 +53,30 @@ module RuboCop
|
|
55
53
|
|
56
54
|
corrector.replace(
|
57
55
|
node.loc.expression,
|
58
|
-
"#{receiver.source}.#{method}(#{amount&.source || 0},
|
56
|
+
"#{receiver.source}.#{method}(#{amount&.source || 0}, #{replacement_currency})"
|
59
57
|
)
|
60
58
|
end
|
61
59
|
|
62
60
|
if to_money_without_currency?(node)
|
63
|
-
corrector.insert_after(node.loc.expression, "(
|
61
|
+
corrector.insert_after(node.loc.expression, "(#{replacement_currency})")
|
64
62
|
elsif to_money_block?(node)
|
65
63
|
corrector.replace(
|
66
64
|
node.loc.expression,
|
67
|
-
"#{receiver.source}.#{method} { |x| x.to_money(
|
65
|
+
"#{receiver.source}.#{method} { |x| x.to_money(#{replacement_currency}) }"
|
68
66
|
)
|
69
67
|
end
|
70
68
|
end
|
71
69
|
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def replacement_currency
|
74
|
+
if cop_config['ReplacementCurrency']
|
75
|
+
"'#{cop_config['ReplacementCurrency']}'"
|
76
|
+
else
|
77
|
+
'Money::NULL_CURRENCY'
|
78
|
+
end
|
79
|
+
end
|
72
80
|
end
|
73
81
|
end
|
74
82
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Money
|
6
|
+
class ZeroMoney < Cop
|
7
|
+
# `Money.zero` and it's alias `empty`, with or without currency
|
8
|
+
# argument is removed in favour of the more explicit Money.new
|
9
|
+
# syntax. Supplying it with a real currency is preferred for
|
10
|
+
# additional currency safety checks.
|
11
|
+
#
|
12
|
+
# If no currency was supplied, it defaults to
|
13
|
+
# Money::NULL_CURRENCY which was the default setting of
|
14
|
+
# Money.default_currency and should effectively be the same. The cop
|
15
|
+
# can be configured with a ReplacementCurrency in case that is more
|
16
|
+
# appropriate for your application.
|
17
|
+
#
|
18
|
+
# @example
|
19
|
+
#
|
20
|
+
# # bad
|
21
|
+
# Money.zero
|
22
|
+
#
|
23
|
+
# # good when configured with `ReplacementCurrency: CAD`
|
24
|
+
# Money.new(0, 'CAD')
|
25
|
+
#
|
26
|
+
|
27
|
+
MSG = 'Money.zero is removed, use `Money.new(0, %<currency>s)`.'
|
28
|
+
|
29
|
+
def_node_matcher :money_zero, <<~PATTERN
|
30
|
+
(send (const {nil? cbase} :Money) {:zero :empty} $...)
|
31
|
+
PATTERN
|
32
|
+
|
33
|
+
def on_send(node)
|
34
|
+
money_zero(node) do |currency_arg|
|
35
|
+
add_offense(node, message: format(MSG, currency: replacement_currency(currency_arg)))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def autocorrect(node)
|
40
|
+
receiver, _ = *node
|
41
|
+
|
42
|
+
lambda do |corrector|
|
43
|
+
money_zero(node) do |currency_arg|
|
44
|
+
replacement_currency = replacement_currency(currency_arg)
|
45
|
+
|
46
|
+
corrector.replace(
|
47
|
+
node.loc.expression,
|
48
|
+
"#{receiver.source}.new(0, #{replacement_currency})"
|
49
|
+
)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def replacement_currency(currency_arg)
|
57
|
+
return currency_arg.first.source unless currency_arg.empty?
|
58
|
+
return "'#{cop_config['ReplacementCurrency']}'" if cop_config['ReplacementCurrency']
|
59
|
+
|
60
|
+
'Money::NULL_CURRENCY'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/money.gemspec
CHANGED
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
|
|
15
15
|
|
16
16
|
s.metadata['allowed_push_host'] = "https://rubygems.org"
|
17
17
|
|
18
|
-
s.add_development_dependency("bundler"
|
18
|
+
s.add_development_dependency("bundler")
|
19
19
|
s.add_development_dependency("simplecov", ">= 0")
|
20
20
|
s.add_development_dependency("rails", "~> 6.0")
|
21
21
|
s.add_development_dependency("rspec", "~> 3.2")
|
@@ -20,8 +20,10 @@ RSpec.describe AccountingMoneyParser do
|
|
20
20
|
end
|
21
21
|
|
22
22
|
it "parses an invalid string to $0" do
|
23
|
-
|
24
|
-
|
23
|
+
configure(legacy_deprecations: true) do
|
24
|
+
expect(Money).to receive(:deprecate).once
|
25
|
+
expect(@parser.parse("no money", 'USD')).to eq(Money.new(0, 'USD'))
|
26
|
+
end
|
25
27
|
end
|
26
28
|
|
27
29
|
it "parses a single digit integer string" do
|
data/spec/allocator_spec.rb
CHANGED
@@ -43,7 +43,7 @@ RSpec.describe "Allocator" do
|
|
43
43
|
|
44
44
|
specify "#allocate will convert rationals with high precision" do
|
45
45
|
ratios = [Rational(1, 1), Rational(0)]
|
46
|
-
expect(new_allocator("858993456.12").allocate(ratios)).to eq([Money.new("858993456.12"), Money.
|
46
|
+
expect(new_allocator("858993456.12").allocate(ratios)).to eq([Money.new("858993456.12"), Money.new(0, Money::NULL_CURRENCY)])
|
47
47
|
ratios = [Rational(1, 6), Rational(5, 6)]
|
48
48
|
expect(new_allocator("3.00").allocate(ratios)).to eq([Money.new("0.50"), Money.new("2.50")])
|
49
49
|
end
|
@@ -131,8 +131,8 @@ RSpec.describe "Allocator" do
|
|
131
131
|
|
132
132
|
specify "#allocate_max_amounts supports all-zero maxima" do
|
133
133
|
expect(
|
134
|
-
new_allocator(3).allocate_max_amounts([Money.
|
135
|
-
).to eq([Money.
|
134
|
+
new_allocator(3).allocate_max_amounts([Money.new(0, Money::NULL_CURRENCY), Money.new(0, Money::NULL_CURRENCY), Money.new(0, Money::NULL_CURRENCY)]),
|
135
|
+
).to eq([Money.new(0, Money::NULL_CURRENCY), Money.new(0, Money::NULL_CURRENCY), Money.new(0, Money::NULL_CURRENCY)])
|
136
136
|
end
|
137
137
|
|
138
138
|
specify "#allocate_max_amounts allocates the right amount without rounding error" do
|
data/spec/config_spec.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
RSpec.describe "Money::Config" do
|
5
|
+
describe 'legacy_deprecations' do
|
6
|
+
it "respects the default currency" do
|
7
|
+
configure(default_currency: 'USD', legacy_deprecations: true) do
|
8
|
+
expect(Money.default_currency).to eq("USD")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'defaults to not opt-in to v1' do
|
13
|
+
expect(Money::Config.new.legacy_deprecations).to eq(false)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'legacy_deprecations returns true when opting in to v1' do
|
17
|
+
configure(legacy_deprecations: true) do
|
18
|
+
expect(Money.config.legacy_deprecations).to eq(true)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'sets the deprecations to raise' do
|
23
|
+
configure(legacy_deprecations: true) do
|
24
|
+
expect { Money.deprecate("test") }.to raise_error(ActiveSupport::DeprecationException)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'legacy_deprecations defaults to NULL_CURRENCY' do
|
29
|
+
configure(legacy_default_currency: true) do
|
30
|
+
expect(Money.config.default_currency).to eq(Money::NULL_CURRENCY)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'parser' do
|
36
|
+
it 'defaults to MoneyParser' do
|
37
|
+
expect(Money::Config.new.parser).to eq(MoneyParser)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'can be set to a new parser' do
|
41
|
+
configure(parser: AccountingMoneyParser) do
|
42
|
+
expect(Money.config.parser).to eq(AccountingMoneyParser)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'default_currency' do
|
48
|
+
it 'defaults to nil' do
|
49
|
+
configure do
|
50
|
+
expect(Money.config.default_currency).to eq(nil)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'can be set to a new currency' do
|
55
|
+
configure(default_currency: 'USD') do
|
56
|
+
expect(Money.config.default_currency).to eq('USD')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -17,7 +17,7 @@ RSpec.describe Integer do
|
|
17
17
|
it_should_behave_like "an object supporting to_money"
|
18
18
|
|
19
19
|
it "parses 0 to Money.zero" do
|
20
|
-
expect(0.to_money).to eq(Money.
|
20
|
+
expect(0.to_money).to eq(Money.new(0, Money::NULL_CURRENCY))
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
@@ -30,7 +30,7 @@ RSpec.describe Float do
|
|
30
30
|
it_should_behave_like "an object supporting to_money"
|
31
31
|
|
32
32
|
it "parses 0.0 to Money.zero" do
|
33
|
-
expect(0.0.to_money).to eq(Money.
|
33
|
+
expect(0.0.to_money).to eq(Money.new(0, Money::NULL_CURRENCY))
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
@@ -43,8 +43,8 @@ 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(''.to_money).to eq(Money.
|
47
|
-
expect(' '.to_money).to eq(Money.
|
46
|
+
expect(''.to_money).to eq(Money.new(0, Money::NULL_CURRENCY))
|
47
|
+
expect(' '.to_money).to eq(Money.new(0, Money::NULL_CURRENCY))
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
@@ -57,6 +57,6 @@ RSpec.describe BigDecimal do
|
|
57
57
|
it_should_behave_like "an object supporting to_money"
|
58
58
|
|
59
59
|
it "parses a zero BigDecimal to Money.zero" do
|
60
|
-
expect(BigDecimal("-0.000").to_money).to eq(Money.
|
60
|
+
expect(BigDecimal("-0.000").to_money).to eq(Money.new(0, Money::NULL_CURRENCY))
|
61
61
|
end
|
62
62
|
end
|
data/spec/currency_spec.rb
CHANGED
@@ -77,6 +77,16 @@ RSpec.describe "Currency" do
|
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
|
+
describe "#hash" do
|
81
|
+
specify "equal currencies from different loaders have the same hash" do
|
82
|
+
currency_1 = Money::Currency.find('USD')
|
83
|
+
currency_2 = YAML.load(Money::Currency.find('USD').to_yaml)
|
84
|
+
|
85
|
+
expect(currency_1.eql?(currency_2)).to eq(true)
|
86
|
+
expect(currency_1.hash).to eq(currency_2.hash)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
80
90
|
describe "==" do
|
81
91
|
it "returns true when both objects have the same currency" do
|
82
92
|
expect(currency == Money.new(1, 'USD').currency).to eq(true)
|
data/spec/helpers_spec.rb
CHANGED
@@ -46,8 +46,10 @@ RSpec.describe Money::Helpers do
|
|
46
46
|
end
|
47
47
|
|
48
48
|
it 'invalid string returns zero' do
|
49
|
-
|
50
|
-
|
49
|
+
configure(legacy_deprecations: true) do
|
50
|
+
expect(Money).to receive(:deprecate).once
|
51
|
+
expect(subject.value_to_decimal('invalid')).to eq(0)
|
52
|
+
end
|
51
53
|
end
|
52
54
|
|
53
55
|
it 'raises on invalid object' do
|
@@ -70,7 +72,9 @@ RSpec.describe Money::Helpers do
|
|
70
72
|
end
|
71
73
|
|
72
74
|
it 'returns the default currency when value is empty' do
|
73
|
-
|
75
|
+
configure(legacy_deprecations: true, default_currency: 'USD') do
|
76
|
+
expect(subject.value_to_currency('')).to eq(Money::Currency.new('USD'))
|
77
|
+
end
|
74
78
|
end
|
75
79
|
|
76
80
|
it 'returns the default currency when value is xxx' do
|
@@ -86,8 +90,10 @@ RSpec.describe Money::Helpers do
|
|
86
90
|
end
|
87
91
|
|
88
92
|
it 'returns the null currency when invalid iso is passed' do
|
89
|
-
|
90
|
-
|
93
|
+
configure(legacy_deprecations: true) do
|
94
|
+
expect(Money).to receive(:deprecate).once
|
95
|
+
expect(subject.value_to_currency('invalid')).to eq(Money::NULL_CURRENCY)
|
96
|
+
end
|
91
97
|
end
|
92
98
|
|
93
99
|
it 'raises on invalid object' do
|
data/spec/money_column_spec.rb
CHANGED
@@ -30,13 +30,18 @@ end
|
|
30
30
|
|
31
31
|
class MoneyWithDelegatedCurrency < ActiveRecord::Base
|
32
32
|
self.table_name = 'money_records'
|
33
|
-
attr_accessor :delegated_record
|
34
33
|
delegate :currency, to: :delegated_record
|
35
34
|
money_column :price, currency_column: 'currency', currency_read_only: true
|
36
35
|
money_column :prix, currency_column: 'currency2', currency_read_only: true
|
37
36
|
def currency2
|
38
37
|
delegated_record.currency
|
39
38
|
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def delegated_record
|
43
|
+
MoneyRecord.new(currency: 'USD')
|
44
|
+
end
|
40
45
|
end
|
41
46
|
|
42
47
|
class MoneyWithCustomAccessors < ActiveRecord::Base
|
@@ -97,11 +102,13 @@ RSpec.describe 'MoneyColumn' do
|
|
97
102
|
end
|
98
103
|
|
99
104
|
it 'returns money with null currency when the currency in the DB is invalid' do
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
+
configure(legacy_deprecations: true) do
|
106
|
+
expect(Money).to receive(:deprecate).once
|
107
|
+
record.update_columns(currency: 'invalid')
|
108
|
+
record.reload
|
109
|
+
expect(record.price.currency).to be_a(Money::NullCurrency)
|
110
|
+
expect(record.price.value).to eq(1.23)
|
111
|
+
end
|
105
112
|
end
|
106
113
|
|
107
114
|
it 'handles legacy support for saving floats' do
|
@@ -114,12 +121,12 @@ RSpec.describe 'MoneyColumn' do
|
|
114
121
|
expect(record.prix.currency.to_s).to eq('CAD')
|
115
122
|
end
|
116
123
|
|
117
|
-
it 'handles legacy support for saving floats
|
124
|
+
it 'handles legacy support for saving floats as provided' do
|
118
125
|
record.update(price: 3.2112, prix: 3.2156)
|
119
|
-
expect(record.attributes['price']).to eq(3.
|
126
|
+
expect(record.attributes['price']).to eq(3.2112)
|
120
127
|
expect(record.price.value).to eq(3.21)
|
121
128
|
expect(record.price.currency.to_s).to eq(currency)
|
122
|
-
expect(record.attributes['prix']).to eq(3.
|
129
|
+
expect(record.attributes['prix']).to eq(3.2156)
|
123
130
|
expect(record.prix.value).to eq(3.22)
|
124
131
|
expect(record.prix.currency.to_s).to eq('CAD')
|
125
132
|
end
|
@@ -136,7 +143,7 @@ RSpec.describe 'MoneyColumn' do
|
|
136
143
|
|
137
144
|
it 'does not overwrite a currency column with a default currency when saving zero' do
|
138
145
|
expect(record.currency.to_s).to eq('EUR')
|
139
|
-
record.update(price: Money.
|
146
|
+
record.update(price: Money.new(0, Money::NULL_CURRENCY))
|
140
147
|
expect(record.currency.to_s).to eq('EUR')
|
141
148
|
end
|
142
149
|
|
@@ -165,8 +172,8 @@ RSpec.describe 'MoneyColumn' do
|
|
165
172
|
describe 'garbage amount' do
|
166
173
|
let(:amount) { 'foo' }
|
167
174
|
|
168
|
-
it 'raises
|
169
|
-
expect { subject }.to raise_error(
|
175
|
+
it 'raises an ArgumentError' do
|
176
|
+
expect { subject }.to raise_error(ArgumentError)
|
170
177
|
end
|
171
178
|
end
|
172
179
|
|
@@ -174,7 +181,7 @@ RSpec.describe 'MoneyColumn' do
|
|
174
181
|
let(:currency) { 'foo' }
|
175
182
|
|
176
183
|
it 'raises an UnknownCurrency error' do
|
177
|
-
expect { subject }.to raise_error(
|
184
|
+
expect { subject }.to raise_error(Money::Currency::UnknownCurrency)
|
178
185
|
end
|
179
186
|
end
|
180
187
|
|
@@ -217,11 +224,20 @@ RSpec.describe 'MoneyColumn' do
|
|
217
224
|
describe 'read_only_currency true' do
|
218
225
|
it 'does not write the currency to the db' do
|
219
226
|
record = MoneyWithReadOnlyCurrency.create
|
220
|
-
record.update_columns(
|
221
|
-
expect(Money).to
|
222
|
-
|
223
|
-
|
224
|
-
|
227
|
+
record.update_columns(currency: 'USD')
|
228
|
+
expect { record.update(price: Money.new(4, 'CAD')) }.to raise_error(MoneyColumn::CurrencyReadOnlyError)
|
229
|
+
end
|
230
|
+
|
231
|
+
it 'legacy_deprecations does not write the currency to the db' do
|
232
|
+
configure(legacy_deprecations: true) do
|
233
|
+
record = MoneyWithReadOnlyCurrency.create
|
234
|
+
record.update_columns(currency: 'USD')
|
235
|
+
|
236
|
+
expect(Money).to receive(:deprecate).once
|
237
|
+
record.update(price: Money.new(4, 'CAD'))
|
238
|
+
expect(record.price.value).to eq(4)
|
239
|
+
expect(record.price.currency.to_s).to eq('USD')
|
240
|
+
end
|
225
241
|
end
|
226
242
|
|
227
243
|
it 'reads the currency that is already in the db' do
|
@@ -233,12 +249,14 @@ RSpec.describe 'MoneyColumn' do
|
|
233
249
|
end
|
234
250
|
|
235
251
|
it 'reads an invalid currency from the db and generates a no currency object' do
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
252
|
+
configure(legacy_deprecations: true) do
|
253
|
+
expect(Money).to receive(:deprecate).once
|
254
|
+
record = MoneyWithReadOnlyCurrency.create
|
255
|
+
record.update_columns(currency: 'invalid', price: 1)
|
256
|
+
record.reload
|
257
|
+
expect(record.price.value).to eq(1)
|
258
|
+
expect(record.price.currency.to_s).to eq('')
|
259
|
+
end
|
242
260
|
end
|
243
261
|
|
244
262
|
it 'sets the currency correctly when the currency is changed' do
|
@@ -248,12 +266,12 @@ RSpec.describe 'MoneyColumn' do
|
|
248
266
|
end
|
249
267
|
|
250
268
|
it 'handle cases where the delegate allow_nil is false' do
|
251
|
-
record = MoneyWithDelegatedCurrency.new(price: Money.new(10, 'USD')
|
269
|
+
record = MoneyWithDelegatedCurrency.new(price: Money.new(10, 'USD'))
|
252
270
|
expect(record.price.currency.to_s).to eq('USD')
|
253
271
|
end
|
254
272
|
|
255
273
|
it 'handle cases where a manual delegate does not allow nil' do
|
256
|
-
record = MoneyWithDelegatedCurrency.new(prix: Money.new(10, 'USD')
|
274
|
+
record = MoneyWithDelegatedCurrency.new(prix: Money.new(10, 'USD'))
|
257
275
|
expect(record.price.currency.to_s).to eq('USD')
|
258
276
|
end
|
259
277
|
end
|
@@ -370,10 +388,7 @@ RSpec.describe 'MoneyColumn' do
|
|
370
388
|
|
371
389
|
describe 'default_currency = nil' do
|
372
390
|
around do |example|
|
373
|
-
default_currency
|
374
|
-
Money.default_currency = nil
|
375
|
-
example.run
|
376
|
-
Money.default_currency = default_currency
|
391
|
+
configure(default_currency: nil) { example.run }
|
377
392
|
end
|
378
393
|
|
379
394
|
it 'writes currency from input value to the db' do
|
@@ -384,11 +399,17 @@ RSpec.describe 'MoneyColumn' do
|
|
384
399
|
expect(record.price.currency.to_s).to eq('GBP')
|
385
400
|
end
|
386
401
|
|
387
|
-
it 'raises missing currency error
|
388
|
-
record.update(currency: nil)
|
402
|
+
it 'raises missing currency error reading a value that was saved using legacy non-money object' do
|
403
|
+
record.update(currency: nil, price: 3)
|
404
|
+
expect { record.price }.to raise_error(ArgumentError, 'missing currency')
|
405
|
+
end
|
389
406
|
|
390
|
-
|
391
|
-
|
407
|
+
it 'handles legacy support for saving price and currency separately' do
|
408
|
+
record.update(currency: nil)
|
409
|
+
record.update(price: 7, currency: 'GBP')
|
410
|
+
record.reload
|
411
|
+
expect(record.price.value).to eq(7)
|
412
|
+
expect(record.price.currency.to_s).to eq('GBP')
|
392
413
|
end
|
393
414
|
end
|
394
415
|
end
|