shopify-money 0.14.6 → 1.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- 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
|