shopify-money 0.10.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.
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.shared_examples_for "an object supporting to_money" do
4
+ it "supports to_money" do
5
+ expect(@value.to_money).to eq(@money)
6
+ expect(@value.to_money('CAD').currency).to eq(Money::Currency.find!('CAD'))
7
+ end
8
+ end
9
+
10
+ RSpec.describe Integer do
11
+ before(:each) do
12
+ @value = 1
13
+ @money = Money.new("1.00")
14
+ end
15
+
16
+ it_should_behave_like "an object supporting to_money"
17
+ end
18
+
19
+ RSpec.describe Float do
20
+ before(:each) do
21
+ @value = 1.23
22
+ @money = Money.new("1.23")
23
+ end
24
+
25
+ it_should_behave_like "an object supporting to_money"
26
+ end
27
+
28
+ RSpec.describe String do
29
+ before(:each) do
30
+ @value = "1.23"
31
+ @money = Money.new(@value)
32
+ end
33
+
34
+ it_should_behave_like "an object supporting to_money"
35
+ end
36
+
37
+ RSpec.describe BigDecimal do
38
+ before(:each) do
39
+ @value = BigDecimal.new("1.23")
40
+ @money = Money.new("1.23")
41
+ end
42
+
43
+ it_should_behave_like "an object supporting to_money"
44
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Money::Currency::Loader do
4
+
5
+ describe 'load_currencies' do
6
+ it 'loads the iso currency file' do
7
+ expect(subject.load_currencies['usd']['iso_code']).to eq('USD')
8
+ expect(subject.load_currencies['usd']['symbol']).to eq('$')
9
+ expect(subject.load_currencies['usd']['subunit_to_unit']).to eq(100)
10
+ expect(subject.load_currencies['usd']['smallest_denomination']).to eq(1)
11
+ end
12
+
13
+ it 'loads the non iso currency file' do
14
+ expect(subject.load_currencies['jep']['iso_code']).to eq('JEP')
15
+ end
16
+
17
+ it 'loads the historic iso currency file' do
18
+ expect(subject.load_currencies['eek']['iso_code']).to eq('EEK')
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,113 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe "Currency" do
4
+ CURRENCY_DATA = {
5
+ "iso_code": "USD",
6
+ "name": "United States Dollar",
7
+ "subunit_to_unit": 100,
8
+ "iso_numeric": "840",
9
+ "smallest_denomination": 1,
10
+ "minor_units": 2,
11
+ "symbol": '$',
12
+ "disambiguate_symbol": "US$",
13
+ "subunit_symbol": "¢",
14
+ "decimal_mark": ".",
15
+ }
16
+
17
+ let(:currency) { Money::Currency.new('usd') }
18
+
19
+ describe ".new" do
20
+ it "is constructable with a uppercase string" do
21
+ expect(Money::Currency.new('USD').iso_code).to eq('USD')
22
+ end
23
+
24
+ it "is constructable with a symbol" do
25
+ expect(Money::Currency.new(:usd).iso_code).to eq('USD')
26
+ end
27
+
28
+ it "is constructable with a lowercase string" do
29
+ expect(Money::Currency.new('usd').iso_code).to eq('USD')
30
+ end
31
+
32
+ it "raises when the currency is invalid" do
33
+ expect { Money::Currency.new('yyy') }.to raise_error(Money::Currency::UnknownCurrency)
34
+ end
35
+
36
+ it "raises when the currency is nil" do
37
+ expect { Money::Currency.new(nil) }.to raise_error(Money::Currency::UnknownCurrency)
38
+ end
39
+ end
40
+
41
+ describe ".find" do
42
+ it "returns nil when the currency is invalid" do
43
+ expect(Money::Currency.find('yyy')).to eq(nil)
44
+ end
45
+
46
+ it "returns a valid currency" do
47
+ expect(Money::Currency.find('usd')).to eq(Money::Currency.new('usd'))
48
+ end
49
+ end
50
+
51
+ describe ".find!" do
52
+ it "raises when the currency is invalid" do
53
+ expect { Money::Currency.find!('yyy') }.to raise_error(Money::Currency::UnknownCurrency)
54
+ end
55
+
56
+ it "returns a valid currency" do
57
+ expect(Money::Currency.find!('CAD')).to eq(Money::Currency.new('CAD'))
58
+ end
59
+ end
60
+
61
+ CURRENCY_DATA.each do |attribute, value|
62
+ describe "##{attribute}" do
63
+ it 'returns the correct value' do
64
+ expect(currency.public_send(attribute)).to eq(value)
65
+ end
66
+ end
67
+ end
68
+
69
+ describe "#eql?" do
70
+ it "returns true when both objects represent the same currency" do
71
+ expect(currency.eql?(Money.new(1, 'USD').currency)).to eq(true)
72
+ end
73
+
74
+ it "returns false when the currency iso is different" do
75
+ expect(currency.eql?(Money.new(1, 'CAD').currency)).to eq(false)
76
+ end
77
+ end
78
+
79
+ describe "==" do
80
+ it "returns true when both objects have the same currency" do
81
+ expect(currency == Money.new(1, 'USD').currency).to eq(true)
82
+ end
83
+
84
+ it "returns false when the currency iso is different" do
85
+ expect(currency == Money.new(1, 'CAD').currency).to eq(false)
86
+ end
87
+ end
88
+
89
+ describe "#to_s" do
90
+ it "to return the iso code string" do
91
+ expect(currency.to_s).to eq('USD')
92
+ end
93
+ end
94
+
95
+ describe "#compatible" do
96
+
97
+ it "returns true for the same currency" do
98
+ expect(currency.compatible?(Money::Currency.new('USD'))).to eq(true)
99
+ end
100
+
101
+ it "returns true for null_currency" do
102
+ expect(currency.compatible?(Money::NULL_CURRENCY)).to eq(true)
103
+ end
104
+
105
+ it "returns false for nil" do
106
+ expect(currency.compatible?(nil)).to eq(false)
107
+ end
108
+
109
+ it "returns false for a different currency" do
110
+ expect(currency.compatible?(Money::Currency.new('JPY'))).to eq(false)
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,103 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Money::Helpers do
4
+
5
+ describe 'value_to_decimal' do
6
+ let (:amount) { BigDecimal.new('1.23') }
7
+ let (:money) { Money.new(amount) }
8
+
9
+ it 'returns the value of a money object' do
10
+ expect(subject.value_to_decimal(money)).to eq(amount)
11
+ end
12
+
13
+ it 'returns itself if it is already a big decimal' do
14
+ expect(subject.value_to_decimal(BigDecimal.new('1.23'))).to eq(amount)
15
+ end
16
+
17
+ it 'returns zero when nil' do
18
+ expect(subject.value_to_decimal(nil)).to eq(0)
19
+ end
20
+
21
+ it 'returns zero when empty' do
22
+ expect(subject.value_to_decimal('')).to eq(0)
23
+ end
24
+
25
+ it 'returns the bigdecimal version of a integer' do
26
+ expect(subject.value_to_decimal(1)).to eq(BigDecimal.new('1'))
27
+ end
28
+
29
+ it 'returns the bigdecimal version of a float' do
30
+ expect(subject.value_to_decimal(1.23)).to eq(amount)
31
+ end
32
+
33
+ it 'returns the bigdecimal version of a rational' do
34
+ expect(subject.value_to_decimal(amount.to_r)).to eq(amount)
35
+ end
36
+
37
+ it 'returns the bigdecimal version of a ruby number string' do
38
+ expect(subject.value_to_decimal('1.23')).to eq(amount)
39
+ end
40
+
41
+ it 'returns the bigdecimal version of a ruby number string with whitespace padding' do
42
+ expect(subject.value_to_decimal(' 1.23 ')).to eq(amount)
43
+ expect(subject.value_to_decimal("1.23\n")).to eq(amount)
44
+ expect(subject.value_to_decimal(' -1.23 ')).to eq(-amount)
45
+ end
46
+
47
+ it 'invalid string returns zero' do
48
+ expect(Money).to receive(:deprecate).once
49
+ expect(subject.value_to_decimal('invalid')).to eq(0)
50
+ end
51
+
52
+ it 'returns the bigdecimal representation of numbers while they are deprecated' do
53
+ expect(Money).to receive(:deprecate).exactly(2).times
54
+ expect(subject.value_to_decimal('1.23abc')).to eq(amount)
55
+ expect(subject.value_to_decimal("1.23\n23")).to eq(amount)
56
+ end
57
+
58
+ it 'raises on invalid object' do
59
+ expect { subject.value_to_decimal(OpenStruct.new(amount: 1)) }.to raise_error(ArgumentError)
60
+ end
61
+
62
+ it 'returns regular zero for a negative zero value' do
63
+ expect(subject.value_to_decimal(-BigDecimal.new(0))).to eq(BigDecimal.new(0))
64
+ end
65
+ end
66
+
67
+ describe 'subject.value_to_currency' do
68
+ it 'returns itself if it is already a currency' do
69
+ expect(subject.value_to_currency(Money::Currency.new('usd'))).to eq(Money::Currency.find!('usd'))
70
+ expect(subject.value_to_currency(Money::NULL_CURRENCY)).to be_a(Money::NullCurrency)
71
+ end
72
+
73
+ it 'returns the default currency when value is nil' do
74
+ expect(subject.value_to_currency(nil)).to eq(Money.default_currency)
75
+ end
76
+
77
+ it 'returns the default currency when value is empty' do
78
+ expect(subject.value_to_currency('')).to eq(Money.default_currency)
79
+ end
80
+
81
+ it 'returns the default currency when value is xxx' do
82
+ expect(subject.value_to_currency('xxx')).to eq(Money::NULL_CURRENCY)
83
+ end
84
+
85
+ it 'returns the current currency when value is set' do
86
+ expect(Money.with_currency('USD') { subject.value_to_currency(nil) }).to eq(Money::Currency.find!('usd'))
87
+ end
88
+
89
+ it 'returns the matching currency' do
90
+ expect(subject.value_to_currency('usd')).to eq(Money::Currency.new('USD'))
91
+ end
92
+
93
+ it 'returns the null currency when invalid iso is passed' do
94
+ expect(Money).to receive(:deprecate).once
95
+ expect(subject.value_to_currency('invalid')).to eq(Money::NULL_CURRENCY)
96
+ end
97
+
98
+ it 'raises on invalid object' do
99
+ expect { subject.value_to_currency(OpenStruct.new(amount: 1)) }.to raise_error(ArgumentError)
100
+ expect { subject.value_to_currency(1) }.to raise_error(ArgumentError)
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,86 @@
1
+ require 'spec_helper'
2
+
3
+ class NormalObject
4
+ include MoneyAccessor
5
+
6
+ money_accessor :price
7
+
8
+ def initialize(price)
9
+ @price = price
10
+ end
11
+ end
12
+
13
+ class StructObject < Struct.new(:price)
14
+ include MoneyAccessor
15
+
16
+ money_accessor :price
17
+ end
18
+
19
+ RSpec.shared_examples_for "an object with a money accessor" do
20
+ it "generates an attribute reader that returns a money object" do
21
+ object = described_class.new(100)
22
+
23
+ expect(object.price).to eq(Money.new(100))
24
+ end
25
+
26
+ it "generates an attribute reader that returns a nil object if the value was nil" do
27
+ object = described_class.new(nil)
28
+
29
+ expect(object.price).to eq(nil)
30
+ end
31
+
32
+ it "generates an attribute reader that returns a nil object if the value was blank" do
33
+ object = described_class.new('')
34
+
35
+ expect(object.price).to eq(nil)
36
+ end
37
+
38
+ it "generates an attribute writer that allow setting a money object" do
39
+ object = described_class.new(0)
40
+ object.price = Money.new(10)
41
+
42
+ expect(object.price).to eq(Money.new(10))
43
+ end
44
+
45
+ it "generates an attribute writer that allow setting a integer value" do
46
+ object = described_class.new(0)
47
+ object.price = 10
48
+
49
+ expect(object.price).to eq(Money.new(10))
50
+ end
51
+
52
+ it "generates an attribute writer that allow setting a float value" do
53
+ object = described_class.new(0)
54
+ object.price = 10.12
55
+
56
+ expect(object.price).to eq(Money.new(10.12))
57
+ end
58
+
59
+ it "generates an attribute writer that allow setting a nil value" do
60
+ object = described_class.new(0)
61
+ object.price = nil
62
+
63
+ expect(object.price).to eq(nil)
64
+ end
65
+
66
+ it "generates an attribute writer that allow setting a blank value" do
67
+ object = described_class.new(0)
68
+ object.price = ''
69
+
70
+ expect(object.price).to eq(nil)
71
+ end
72
+ end
73
+
74
+ RSpec.describe NormalObject do
75
+ it_behaves_like "an object with a money accessor"
76
+ end
77
+
78
+ RSpec.describe StructObject do
79
+ it_behaves_like "an object with a money accessor"
80
+
81
+ it 'does not generate an ivar to store the price value' do
82
+ object = described_class.new(10.00)
83
+
84
+ expect(object.instance_variable_get(:@price)).to eq(nil)
85
+ end
86
+ end
@@ -0,0 +1,298 @@
1
+ require 'spec_helper'
2
+
3
+ class MoneyRecord < ActiveRecord::Base
4
+ RATE = 1.17
5
+ before_validation do
6
+ self.price_usd = Money.new(self["price"] * RATE, 'USD') if self["price"]
7
+ end
8
+ money_column :price, currency_column: 'currency'
9
+ money_column :prix, currency_column: :devise
10
+ money_column :price_usd, currency: 'USD'
11
+ end
12
+
13
+ class MoneyWithValidation < ActiveRecord::Base
14
+ self.table_name = 'money_records'
15
+ validates :price, :currency, presence: true
16
+ money_column :price, currency_column: 'currency'
17
+ end
18
+
19
+ class MoneyWithReadOnlyCurrency < ActiveRecord::Base
20
+ self.table_name = 'money_records'
21
+ money_column :price, currency_column: 'currency', currency_read_only: true
22
+ end
23
+
24
+ class MoneyRecordCoerceNull < ActiveRecord::Base
25
+ self.table_name = 'money_records'
26
+ money_column :price, currency_column: 'currency', coerce_null: true
27
+ money_column :price_usd, currency: 'USD', coerce_null: true
28
+ end
29
+
30
+ class MoneyWithDelegatedCurrency < ActiveRecord::Base
31
+ self.table_name = 'money_records'
32
+ attr_accessor :delegated_record
33
+ delegate :currency, to: :delegated_record
34
+ money_column :price, currency_column: 'currency', currency_read_only: true
35
+ money_column :prix, currency_column: 'currency2', currency_read_only: true
36
+ def currency2
37
+ delegated_record.currency
38
+ end
39
+ end
40
+
41
+ RSpec.describe 'MoneyColumn' do
42
+ let(:amount) { 1.23 }
43
+ let(:currency) { 'EUR' }
44
+ let(:money) { Money.new(amount, currency) }
45
+ let(:toonie) { Money.new(2.00, 'CAD') }
46
+ let(:subject) { MoneyRecord.new(price: money, prix: toonie) }
47
+ let(:record) do
48
+ subject.devise = 'CAD'
49
+ subject.save
50
+ subject.reload
51
+ end
52
+
53
+ it 'returns money with currency from the default column' do
54
+ expect(record.price).to eq(Money.new(1.23, 'EUR'))
55
+ end
56
+
57
+ it 'writes the currency to the db' do
58
+ record.update(currency: nil)
59
+ record.update(price: Money.new(4, 'JPY'))
60
+ record.reload
61
+ expect(record.price.value).to eq(4)
62
+ expect(record.price.currency.to_s).to eq('JPY')
63
+ end
64
+
65
+ it 'duplicating the record keeps the money values' do
66
+ expect(MoneyRecord.new(price: money).clone.price).to eq(money)
67
+ expect(MoneyRecord.new(price: money).dup.price).to eq(money)
68
+ end
69
+
70
+ it 'returns money with currency from the specified column' do
71
+ expect(record.prix).to eq(Money.new(2.00, 'CAD'))
72
+ end
73
+
74
+ it 'returns money with the hardcoded currency' do
75
+ expect(record.price_usd).to eq(Money.new(1.44, 'USD'))
76
+ end
77
+
78
+ it 'returns money with null currency when the currency in the DB is invalid' do
79
+ expect(Money).to receive(:deprecate).once
80
+ record.update_columns(currency: 'invalid')
81
+ record.reload
82
+ expect(record.price.currency).to be_a(Money::NullCurrency)
83
+ expect(record.price.value).to eq(1.23)
84
+ end
85
+
86
+ it 'handles legacy support for saving floats' do
87
+ record.update(price: 3.21, prix: 3.21)
88
+ expect(record.price.value).to eq(3.21)
89
+ expect(record.price.currency.to_s).to eq(currency)
90
+ expect(record.price_usd.value).to eq(3.76)
91
+ expect(record.price_usd.currency.to_s).to eq('USD')
92
+ expect(record.prix.value).to eq(3.21)
93
+ expect(record.prix.currency.to_s).to eq('CAD')
94
+ end
95
+
96
+ it 'handles legacy support for saving floats with correct currency rounding' do
97
+ record.update(price: 3.2112, prix: 3.2156)
98
+ expect(record.attributes['price']).to eq(3.21)
99
+ expect(record.price.value).to eq(3.21)
100
+ expect(record.price.currency.to_s).to eq(currency)
101
+ expect(record.attributes['prix']).to eq(3.22)
102
+ expect(record.prix.value).to eq(3.22)
103
+ expect(record.prix.currency.to_s).to eq('CAD')
104
+ end
105
+
106
+ it 'handles legacy support for saving string' do
107
+ record.update(price: '3.21', prix: '3.21')
108
+ expect(record.price.value).to eq(3.21)
109
+ expect(record.price.currency.to_s).to eq(currency)
110
+ expect(record.price_usd.value).to eq(3.76)
111
+ expect(record.price_usd.currency.to_s).to eq('USD')
112
+ expect(record.prix.value).to eq(3.21)
113
+ expect(record.prix.currency.to_s).to eq('CAD')
114
+ end
115
+
116
+ it 'does not overwrite a currency column with a default currency when saving zero' do
117
+ expect(record.currency.to_s).to eq('EUR')
118
+ record.update(price: Money.zero)
119
+ expect(record.currency.to_s).to eq('EUR')
120
+ end
121
+
122
+ it 'does overwrite a currency if changed but will show a deprecation notice' do
123
+ expect(record.currency.to_s).to eq('EUR')
124
+ expect(Money).to receive(:deprecate).once
125
+ record.update(price: Money.new(4, 'JPY'))
126
+ expect(record.currency.to_s).to eq('JPY')
127
+ end
128
+
129
+ describe 'non-fractional-currencies' do
130
+ let(:money) { Money.new(1, 'JPY') }
131
+
132
+ it 'returns money with currency from the default column' do
133
+ expect(record.price).to eq(Money.new(1, 'JPY'))
134
+ end
135
+ end
136
+
137
+ describe 'three-decimal currencies' do
138
+ let(:money) { Money.new(1.234, 'JOD') }
139
+
140
+ it 'returns money with currency from the default column' do
141
+ expect(record.price).to eq(Money.new(1.234, 'JOD'))
142
+ end
143
+ end
144
+
145
+ describe 'garbage amount' do
146
+ let(:amount) { 'foo' }
147
+
148
+ it 'raises a deprecation warning' do
149
+ expect { subject }.to raise_error(ActiveSupport::DeprecationException)
150
+ end
151
+ end
152
+
153
+ describe 'garbage currency' do
154
+ let(:currency) { 'foo' }
155
+
156
+ it 'raises an UnknownCurrency error' do
157
+ expect { subject }.to raise_error(ActiveSupport::DeprecationException)
158
+ end
159
+ end
160
+
161
+ describe 'wrong money_column currency arguments' do
162
+ let(:subject) do
163
+ class MoneyWithWrongCurrencyArguments < ActiveRecord::Base
164
+ self.table_name = 'money_records'
165
+ money_column :price, currency_column: :currency, currency: 'USD'
166
+ end
167
+ end
168
+
169
+ it 'raises an ArgumentError' do
170
+ expect { subject }.to raise_error(ArgumentError, 'cannot set both currency_column and a fixed currency')
171
+ end
172
+ end
173
+
174
+ describe 'missing money_column currency arguments' do
175
+ let(:subject) do
176
+ class MoneyWithWrongCurrencyArguments < ActiveRecord::Base
177
+ self.table_name = 'money_records'
178
+ money_column :price
179
+ end
180
+ end
181
+
182
+ it 'raises an ArgumentError' do
183
+ expect { subject }.to raise_error(ArgumentError, 'must set one of :currency_column or :currency options')
184
+ end
185
+ end
186
+
187
+ describe 'null currency and validations' do
188
+ let(:currency) { Money::NULL_CURRENCY }
189
+ let(:subject) { MoneyWithValidation.new(price: money) }
190
+
191
+ it 'is not allowed to be saved because `to_s` returns a blank string' do
192
+ subject.valid?
193
+ expect(subject.errors[:currency]).to include("can't be blank")
194
+ end
195
+ end
196
+
197
+ describe 'read_only_currency true' do
198
+ it 'does not write the currency to the db' do
199
+ record = MoneyWithReadOnlyCurrency.create
200
+ record.update_columns(price: 1, currency: 'USD')
201
+ expect(Money).to receive(:deprecate).once
202
+ record.update(price: Money.new(4, 'CAD'))
203
+ expect(record.price.value).to eq(4)
204
+ expect(record.price.currency.to_s).to eq('USD')
205
+ end
206
+
207
+ it 'reads the currency that is already in the db' do
208
+ record = MoneyWithReadOnlyCurrency.create
209
+ record.update_columns(currency: 'USD', price: 1)
210
+ record.reload
211
+ expect(record.price.value).to eq(1)
212
+ expect(record.price.currency.to_s).to eq('USD')
213
+ end
214
+
215
+ it 'reads an invalid currency from the db and generates a no currency object' do
216
+ expect(Money).to receive(:deprecate).once
217
+ record = MoneyWithReadOnlyCurrency.create
218
+ record.update_columns(currency: 'invalid', price: 1)
219
+ record.reload
220
+ expect(record.price.value).to eq(1)
221
+ expect(record.price.currency.to_s).to eq('')
222
+ end
223
+
224
+ it 'sets the currency correctly when the currency is changed' do
225
+ record = MoneyWithReadOnlyCurrency.create(currency: 'CAD', price: 1)
226
+ record.currency = 'USD'
227
+ expect(record.price.currency.to_s).to eq('USD')
228
+ end
229
+
230
+ it 'handle cases where the delegate allow_nil is false' do
231
+ record = MoneyWithDelegatedCurrency.new(price: Money.new(10, 'USD'), delegated_record: MoneyRecord.new(currency: 'USD'))
232
+ expect(record.price.currency.to_s).to eq('USD')
233
+ end
234
+
235
+ it 'handle cases where a manual delegate does not allow nil' do
236
+ record = MoneyWithDelegatedCurrency.new(prix: Money.new(10, 'USD'), delegated_record: MoneyRecord.new(currency: 'USD'))
237
+ expect(record.price.currency.to_s).to eq('USD')
238
+ end
239
+ end
240
+
241
+ describe 'coerce_null' do
242
+ it 'returns nil when money value have not been set and coerce_null is false' do
243
+ record = MoneyRecord.new(price: nil)
244
+ expect(record.price).to eq(nil)
245
+ expect(record.price_usd).to eq(nil)
246
+ end
247
+
248
+ it 'returns 0$ when money value have not been set and coerce_null is true' do
249
+ record = MoneyRecordCoerceNull.new(price: nil)
250
+ expect(record.price.value).to eq(0)
251
+ expect(record.price_usd.value).to eq(0)
252
+ end
253
+ end
254
+
255
+ describe 'memoization' do
256
+ it 'correctly memoizes the read value' do
257
+ expect(record.instance_variable_get(:@money_column_cache)["price"]).to eq(nil)
258
+ price = Money.new(1, 'USD')
259
+ record = MoneyRecord.new(price: price)
260
+ expect(record.price).to eq(price)
261
+ expect(record.instance_variable_get(:@money_column_cache)["price"]).to eq(price)
262
+ end
263
+
264
+ it 'memoizes values get reset when writing a new value' do
265
+ price = Money.new(1, 'USD')
266
+ record = MoneyRecord.new(price: price)
267
+ expect(record.price).to eq(price)
268
+ price = Money.new(2, 'USD')
269
+ record.update!(price: price)
270
+ expect(record.price).to eq(price)
271
+ expect(record.instance_variable_get(:@money_column_cache)["price"]).to eq(price)
272
+ end
273
+
274
+ it 'reload will clear memoizes money values' do
275
+ price = Money.new(1, 'USD')
276
+ record = MoneyRecord.create(price: price)
277
+ expect(record.price).to eq(price)
278
+ expect(record.instance_variable_get(:@money_column_cache)["price"]).to eq(price)
279
+ record.reload
280
+ expect(record.instance_variable_get(:@money_column_cache)["price"]).to eq(nil)
281
+ record.price
282
+ expect(record.instance_variable_get(:@money_column_cache)["price"]).to eq(price)
283
+ end
284
+ end
285
+
286
+ describe 'ActiveRecord querying' do
287
+ it 'can be serialized for querying on the value' do
288
+ price = Money.new(1, 'USD')
289
+ record = MoneyRecord.create!(price: price)
290
+ expect(MoneyRecord.find_by(price: price)).to eq(record)
291
+ end
292
+
293
+ it 'nil value persist in the DB' do
294
+ record = MoneyRecord.create!(price: nil)
295
+ expect(MoneyRecord.find_by(price: nil)).to eq(record)
296
+ end
297
+ end
298
+ end