shopify-money 0.16.0 → 1.0.2.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/README.md +8 -2
- data/UPGRADING.md +59 -0
- data/config/currency_historic.yml +14 -0
- data/config/currency_iso.yml +22 -4
- data/lib/money/allocator.rb +3 -1
- data/lib/money/config.rb +25 -0
- data/lib/money/core_extensions.rb +1 -1
- data/lib/money/helpers.rb +8 -4
- data/lib/money/money.rb +48 -23
- data/lib/money/parser/accounting.rb +11 -0
- data/lib/money/parser/fuzzy.rb +174 -0
- data/lib/money/parser/locale_aware.rb +52 -0
- data/lib/money/parser/simple.rb +30 -0
- data/lib/money/rails/job_argument_serializer.rb +22 -0
- data/lib/money/railtie.rb +19 -0
- data/lib/money/version.rb +1 -1
- data/lib/money.rb +7 -2
- data/lib/money_column/active_record_hooks.rb +12 -7
- data/spec/config_spec.rb +48 -0
- data/spec/helpers_spec.rb +11 -5
- data/spec/money_column_spec.rb +54 -33
- data/spec/money_spec.rb +129 -62
- data/spec/{accounting_money_parser_spec.rb → parser/accounting_spec.rb} +9 -15
- data/spec/{money_parser_spec.rb → parser/fuzzy_spec.rb} +25 -13
- data/spec/parser/locale_aware_spec.rb +208 -0
- data/spec/parser/simple_spec.rb +62 -0
- data/spec/rails/job_argument_serializer_spec.rb +20 -0
- data/spec/rails_spec_helper.rb +11 -0
- data/spec/spec_helper.rb +15 -0
- metadata +27 -11
- data/lib/money/accounting_money_parser.rb +0 -8
- data/lib/money/money_parser.rb +0 -156
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Money
|
4
|
+
module Rails
|
5
|
+
class JobArgumentSerializer < ::ActiveJob::Serializers::ObjectSerializer
|
6
|
+
def serialize(money)
|
7
|
+
super("value" => money.value, "currency" => money.currency.iso_code)
|
8
|
+
end
|
9
|
+
|
10
|
+
def deserialize(hash)
|
11
|
+
Money.new(hash["value"], hash["currency"])
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def klass
|
17
|
+
Money
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Money
|
4
|
+
class Railtie < Rails::Railtie
|
5
|
+
initializer "shopify-money.setup_active_job_serializer" do
|
6
|
+
ActiveSupport.on_load :active_job do
|
7
|
+
require_relative "rails/job_argument_serializer"
|
8
|
+
ActiveJob::Serializers.add_serializers ::Money::Rails::JobArgumentSerializer
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
initializer "shopify-money.setup_locale_aware_parser" do
|
13
|
+
ActiveSupport.on_load(:action_view) do
|
14
|
+
Money::Parser::LocaleAware.decimal_separator_resolver =
|
15
|
+
-> { ::I18n.translate("number.currency.format.separator") }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/money/version.rb
CHANGED
data/lib/money.rb
CHANGED
@@ -1,14 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require_relative 'money/
|
2
|
+
require_relative 'money/version'
|
3
|
+
require_relative 'money/parser/fuzzy'
|
3
4
|
require_relative 'money/helpers'
|
4
5
|
require_relative 'money/currency'
|
5
6
|
require_relative 'money/null_currency'
|
6
7
|
require_relative 'money/allocator'
|
8
|
+
require_relative 'money/config'
|
7
9
|
require_relative 'money/money'
|
8
10
|
require_relative 'money/errors'
|
9
11
|
require_relative 'money/deprecations'
|
10
|
-
require_relative 'money/
|
12
|
+
require_relative 'money/parser/accounting'
|
13
|
+
require_relative 'money/parser/locale_aware'
|
14
|
+
require_relative 'money/parser/simple'
|
11
15
|
require_relative 'money/core_extensions'
|
12
16
|
require_relative 'money_column' if defined?(ActiveRecord)
|
17
|
+
require_relative 'money/railtie' if defined?(Rails::Railtie)
|
13
18
|
|
14
19
|
require_relative 'rubocop/cop/money' if defined?(RuboCop)
|
@@ -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/spec/config_spec.rb
ADDED
@@ -0,0 +1,48 @@
|
|
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 'default_currency' do
|
36
|
+
it 'defaults to nil' do
|
37
|
+
configure do
|
38
|
+
expect(Money.config.default_currency).to eq(nil)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'can be set to a new currency' do
|
43
|
+
configure(default_currency: 'USD') do
|
44
|
+
expect(Money.config.default_currency).to eq('USD')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
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
|
@@ -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
|
data/spec/money_spec.rb
CHANGED
@@ -3,23 +3,20 @@ require 'spec_helper'
|
|
3
3
|
require 'yaml'
|
4
4
|
|
5
5
|
RSpec.describe "Money" do
|
6
|
-
|
7
6
|
let (:money) { Money.new(1) }
|
8
7
|
let (:amount_money) { Money.new(1.23, 'USD') }
|
9
8
|
let (:non_fractional_money) { Money.new(1, 'JPY') }
|
10
9
|
let (:zero_money) { Money.new(0) }
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
Money.default_currency = nil
|
16
|
-
end
|
17
|
-
after(:each) do
|
18
|
-
Money.default_currency = @default_currency
|
19
|
-
end
|
11
|
+
it "has a version" do
|
12
|
+
expect(Money::VERSION).not_to(eq(nil))
|
13
|
+
end
|
20
14
|
|
15
|
+
context "default currency not set" do
|
21
16
|
it "raises an error" do
|
22
|
-
|
17
|
+
configure(default_currency: nil) do
|
18
|
+
expect { money }.to raise_error(ArgumentError)
|
19
|
+
end
|
23
20
|
end
|
24
21
|
end
|
25
22
|
|
@@ -39,9 +36,15 @@ RSpec.describe "Money" do
|
|
39
36
|
expect(Money.new(1).to_money('CAD')).to eq(Money.new(1, 'CAD'))
|
40
37
|
end
|
41
38
|
|
42
|
-
it "#to_money doesn't overwrite the money object's currency" do
|
43
|
-
|
44
|
-
|
39
|
+
it "legacy_deprecations #to_money doesn't overwrite the money object's currency" do
|
40
|
+
configure(legacy_deprecations: true) do
|
41
|
+
expect(Money).to receive(:deprecate).once
|
42
|
+
expect(Money.new(1, 'USD').to_money('CAD')).to eq(Money.new(1, 'USD'))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it "#to_money raises when changing currency" do
|
47
|
+
expect{ Money.new(1, 'USD').to_money('CAD') }.to raise_error(Money::IncompatibleCurrencyError)
|
45
48
|
end
|
46
49
|
|
47
50
|
it "defaults to 0 when constructed with no arguments" do
|
@@ -52,9 +55,15 @@ RSpec.describe "Money" do
|
|
52
55
|
expect(Money.new('')).to eq(Money.new(0))
|
53
56
|
end
|
54
57
|
|
55
|
-
it "defaults to 0 when constructed with an invalid string" do
|
56
|
-
|
57
|
-
|
58
|
+
it "legacy_deprecations defaults to 0 when constructed with an invalid string" do
|
59
|
+
configure(legacy_deprecations: true) do
|
60
|
+
expect(Money).to receive(:deprecate).once
|
61
|
+
expect(Money.new('invalid', 'USD')).to eq(Money.new(0.00, 'USD'))
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
it "raises when constructed with an invalid string" do
|
66
|
+
expect{ Money.new('invalid') }.to raise_error(ArgumentError)
|
58
67
|
end
|
59
68
|
|
60
69
|
it "to_s correctly displays the right number of decimal places" do
|
@@ -62,14 +71,14 @@ RSpec.describe "Money" do
|
|
62
71
|
expect(non_fractional_money.to_s).to eq("1")
|
63
72
|
end
|
64
73
|
|
65
|
-
it "
|
66
|
-
expect(amount_money.
|
67
|
-
expect(non_fractional_money.
|
74
|
+
it "to_fs with a legacy_dollars style" do
|
75
|
+
expect(amount_money.to_fs(:legacy_dollars)).to eq("1.23")
|
76
|
+
expect(non_fractional_money.to_fs(:legacy_dollars)).to eq("1.00")
|
68
77
|
end
|
69
78
|
|
70
|
-
it "
|
71
|
-
expect(amount_money.
|
72
|
-
expect(non_fractional_money.
|
79
|
+
it "to_fs with a amount style" do
|
80
|
+
expect(amount_money.to_fs(:amount)).to eq("1.23")
|
81
|
+
expect(non_fractional_money.to_fs(:amount)).to eq("1")
|
73
82
|
end
|
74
83
|
|
75
84
|
it "to_s correctly displays negative numbers" do
|
@@ -95,12 +104,31 @@ RSpec.describe "Money" do
|
|
95
104
|
expect(Money.new("999999999999999999.99", "USD").to_s).to eq("999999999999999999.99")
|
96
105
|
end
|
97
106
|
|
98
|
-
it "
|
99
|
-
expect{ money.
|
107
|
+
it "to_fs raises ArgumentError on unsupported style" do
|
108
|
+
expect{ money.to_fs(:some_weird_style) }.to raise_error(ArgumentError)
|
109
|
+
end
|
110
|
+
|
111
|
+
it "to_fs is aliased as to_s for backward compatibility" do
|
112
|
+
expect(money.method(:to_s)).to eq(money.method(:to_fs))
|
113
|
+
end
|
114
|
+
|
115
|
+
it "to_fs is aliased as to_formatted_s for backward compatibility" do
|
116
|
+
expect(money.method(:to_formatted_s)).to eq(money.method(:to_fs))
|
117
|
+
end
|
118
|
+
|
119
|
+
it "legacy_json_format makes as_json return the legacy format" do
|
120
|
+
configure(legacy_json_format: true) do
|
121
|
+
expect(Money.new(1, 'CAD').as_json).to eq("1.00")
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
it "legacy_format correctly sets the json format" do
|
126
|
+
expect(Money.new(1, 'CAD').as_json(legacy_format: true)).to eq("1.00")
|
127
|
+
expect(Money.new(1, 'CAD').to_json(legacy_format: true)).to eq("1.00")
|
100
128
|
end
|
101
129
|
|
102
|
-
it "as_json as a
|
103
|
-
expect(money.as_json).to eq("1.00")
|
130
|
+
it "as_json as a json containing the value and currency" do
|
131
|
+
expect(money.as_json).to eq(value: "1.00", currency: "CAD")
|
104
132
|
end
|
105
133
|
|
106
134
|
it "is constructable with a BigDecimal" do
|
@@ -139,9 +167,15 @@ RSpec.describe "Money" do
|
|
139
167
|
expect((Money.new + Money.new)).to eq(Money.new)
|
140
168
|
end
|
141
169
|
|
142
|
-
it "adds inconsistent currencies" do
|
143
|
-
|
144
|
-
|
170
|
+
it "legacy_deprecations adds inconsistent currencies" do
|
171
|
+
configure(legacy_deprecations: true) do
|
172
|
+
expect(Money).to receive(:deprecate).once
|
173
|
+
expect(Money.new(5, 'USD') + Money.new(1, 'CAD')).to eq(Money.new(6, 'USD'))
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
it "raises when adding inconsistent currencies" do
|
178
|
+
expect{ Money.new(5, 'USD') + Money.new(1, 'CAD') }.to raise_error(Money::IncompatibleCurrencyError)
|
145
179
|
end
|
146
180
|
|
147
181
|
it "is subtractable" do
|
@@ -157,8 +191,10 @@ RSpec.describe "Money" do
|
|
157
191
|
end
|
158
192
|
|
159
193
|
it "logs a deprecation warning when adding across currencies" do
|
160
|
-
|
161
|
-
|
194
|
+
configure(legacy_deprecations: true) do
|
195
|
+
expect(Money).to receive(:deprecate)
|
196
|
+
expect(Money.new(10, 'USD') - Money.new(1, 'JPY')).to eq(Money.new(9, 'USD'))
|
197
|
+
end
|
162
198
|
end
|
163
199
|
|
164
200
|
it "keeps currency when doing a computation with a null currency" do
|
@@ -254,9 +290,15 @@ RSpec.describe "Money" do
|
|
254
290
|
expect(((1.0 / 12) * Money.new(3.3))).to eq(Money.new(0.28))
|
255
291
|
end
|
256
292
|
|
257
|
-
it "is multipliable by a money object" do
|
258
|
-
|
259
|
-
|
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
|
+
it "raises when multiplied by a money object" do
|
301
|
+
expect{ (Money.new(3.3) * Money.new(1)) }.to raise_error(ArgumentError)
|
260
302
|
end
|
261
303
|
|
262
304
|
it "rounds multiplication result with fractional penny of 5 or higher up" do
|
@@ -294,7 +336,14 @@ RSpec.describe "Money" do
|
|
294
336
|
end
|
295
337
|
|
296
338
|
it "returns cents in to_json" do
|
297
|
-
|
339
|
+
configure(legacy_json_format: true) do
|
340
|
+
expect(Money.new('1.23', 'USD').to_json).to eq('1.23')
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
it "returns value and currency in to_json" do
|
345
|
+
expect(Money.new(1.00).to_json).to eq('{"value":"1.00","currency":"CAD"}')
|
346
|
+
expect(JSON.dump(Money.new(1.00, "CAD"))).to eq('{"value":"1.00","currency":"CAD"}')
|
298
347
|
end
|
299
348
|
|
300
349
|
it "supports absolute value" do
|
@@ -352,9 +401,36 @@ RSpec.describe "Money" do
|
|
352
401
|
end
|
353
402
|
|
354
403
|
it "generates a true rational" do
|
355
|
-
expect(Money.rational(Money.new(10.0), Money.new(15.0))).to eq(Rational(2,3))
|
356
|
-
|
357
|
-
|
404
|
+
expect(Money.rational(Money.new(10.0, 'USD'), Money.new(15.0, 'USD'))).to eq(Rational(2,3))
|
405
|
+
|
406
|
+
configure(legacy_deprecations: true) do
|
407
|
+
expect(Money).to receive(:deprecate).once
|
408
|
+
expect(Money.rational(Money.new(10.0, 'USD'), Money.new(15.0, 'JPY'))).to eq(Rational(2,3))
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
it "does not allocate a new money object when multiplying by 1" do
|
413
|
+
expect((money * 1).object_id).to eq(money.object_id)
|
414
|
+
end
|
415
|
+
|
416
|
+
it "does not allocate a new money object when adding 0" do
|
417
|
+
expect((money + 0).object_id).to eq(money.object_id)
|
418
|
+
end
|
419
|
+
|
420
|
+
it "does not allocate a new money object when subtracting 0" do
|
421
|
+
expect((money - 0).object_id).to eq(money.object_id)
|
422
|
+
end
|
423
|
+
|
424
|
+
it "does not allocate when computing absolute value when already positive" do
|
425
|
+
expect((money.abs).object_id).to eq(money.object_id)
|
426
|
+
end
|
427
|
+
|
428
|
+
it "does not allocate when computing floor value when already floored" do
|
429
|
+
expect((money.floor).object_id).to eq(money.object_id)
|
430
|
+
end
|
431
|
+
|
432
|
+
it "does not allocate when computing floor value when already rounded" do
|
433
|
+
expect((money.round).object_id).to eq(money.object_id)
|
358
434
|
end
|
359
435
|
|
360
436
|
describe "frozen with amount of $1" do
|
@@ -413,9 +489,11 @@ RSpec.describe "Money" do
|
|
413
489
|
end
|
414
490
|
|
415
491
|
it "<=> issues deprecation warning when comparing incompatible currency" do
|
416
|
-
|
417
|
-
|
418
|
-
|
492
|
+
configure(legacy_deprecations: true) do
|
493
|
+
expect(Money).to receive(:deprecate).twice
|
494
|
+
expect(Money.new(1000, 'USD') <=> Money.new(2000, 'JPY')).to eq(-1)
|
495
|
+
expect(Money.new(2000, 'JPY') <=> Money.new(1000, 'USD')).to eq(1)
|
496
|
+
end
|
419
497
|
end
|
420
498
|
|
421
499
|
describe('same values') do
|
@@ -437,15 +515,22 @@ RSpec.describe "Money" do
|
|
437
515
|
it { expect(cad_10 < nil_10).to(eq(false)) }
|
438
516
|
end
|
439
517
|
|
440
|
-
describe('different currencies') do
|
518
|
+
describe('legacy different currencies') do
|
519
|
+
around(:each) do |test|
|
520
|
+
configure(legacy_deprecations: true) { test.run }
|
521
|
+
end
|
522
|
+
|
441
523
|
it { expect(Money).to(receive(:deprecate).once); expect(cad_10 <=> usd_10).to(eq(0)) }
|
442
524
|
it { expect(Money).to(receive(:deprecate).once); expect(cad_10 > usd_10).to(eq(false)) }
|
443
525
|
it { expect(Money).to(receive(:deprecate).once); expect(cad_10 >= usd_10).to(eq(true)) }
|
444
|
-
it { expect(cad_10 == usd_10).to(eq(false)) }
|
445
526
|
it { expect(Money).to(receive(:deprecate).once); expect(cad_10 <= usd_10).to(eq(true)) }
|
446
527
|
it { expect(Money).to(receive(:deprecate).once); expect(cad_10 < usd_10).to(eq(false)) }
|
447
528
|
end
|
448
529
|
|
530
|
+
describe('different currencies') do
|
531
|
+
it { expect(cad_10 == usd_10).to(eq(false)) }
|
532
|
+
end
|
533
|
+
|
449
534
|
describe('to_money types') do
|
450
535
|
it { expect(cad_10 <=> 10.00).to(eq(0)) }
|
451
536
|
it { expect(cad_10 > 10.00).to(eq(false)) }
|
@@ -709,23 +794,6 @@ RSpec.describe "Money" do
|
|
709
794
|
end
|
710
795
|
end
|
711
796
|
|
712
|
-
describe "parser dependency injection" do
|
713
|
-
before(:each) { Money.parser = AccountingMoneyParser }
|
714
|
-
after(:each) { Money.parser = MoneyParser }
|
715
|
-
|
716
|
-
it "keeps AccountingMoneyParser class on new money objects" do
|
717
|
-
expect(Money.new.class.parser).to eq(AccountingMoneyParser)
|
718
|
-
end
|
719
|
-
|
720
|
-
it "supports parenthesis from AccountingMoneyParser" do
|
721
|
-
expect(Money.parse("($5.00)")).to eq(Money.new(-5))
|
722
|
-
end
|
723
|
-
|
724
|
-
it "supports parenthesis from AccountingMoneyParser for .to_money" do
|
725
|
-
expect("($5.00)".to_money).to eq(Money.new(-5))
|
726
|
-
end
|
727
|
-
end
|
728
|
-
|
729
797
|
describe "round" do
|
730
798
|
|
731
799
|
it "rounds to 0 decimal places by default" do
|
@@ -875,8 +943,7 @@ RSpec.describe "Money" do
|
|
875
943
|
end
|
876
944
|
|
877
945
|
context "with .default_currency set" do
|
878
|
-
|
879
|
-
after(:each) { Money.default_currency = Money::NULL_CURRENCY }
|
946
|
+
around(:each) { |test| configure(default_currency: Money::Currency.new('EUR')) { test.run }}
|
880
947
|
|
881
948
|
it "can be nested and falls back to default_currency outside of the blocks" do
|
882
949
|
money2, money3 = nil
|