money-rails 1.10.0 → 1.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +33 -26
- data/Rakefile +6 -6
- data/lib/generators/templates/money.rb +12 -12
- data/lib/money-rails/active_model/validator.rb +11 -6
- data/lib/money-rails/active_record/monetizable.rb +12 -12
- data/lib/money-rails/configuration.rb +2 -2
- data/lib/money-rails/helpers/action_view_extension.rb +12 -12
- data/lib/money-rails/money.rb +14 -16
- data/lib/money-rails/mongoid/money.rb +2 -2
- data/lib/money-rails/mongoid/two.rb +2 -2
- data/lib/money-rails/test_helpers.rb +20 -6
- data/lib/money-rails/version.rb +1 -1
- data/money-rails.gemspec +1 -1
- data/spec/active_record/monetizable_spec.rb +46 -40
- data/spec/configuration_spec.rb +2 -2
- data/spec/dummy/app/models/dummy_product.rb +1 -1
- data/spec/dummy/app/models/priceable.rb +2 -2
- data/spec/dummy/app/models/product.rb +24 -22
- data/spec/dummy/app/models/service.rb +1 -1
- data/spec/dummy/app/models/transaction.rb +4 -4
- data/spec/dummy/app/views/layouts/application.html.erb +1 -1
- data/spec/dummy/config/initializers/money.rb +9 -9
- data/spec/dummy/config/initializers/session_store.rb +1 -1
- data/spec/dummy/config/initializers/wrap_parameters.rb +1 -1
- data/spec/dummy/db/migrate/20120712202655_add_sale_price_cents_to_product.rb +1 -1
- data/spec/helpers/action_view_extension_spec.rb +4 -4
- data/spec/helpers/form_helper_spec.rb +4 -4
- data/spec/mongoid/five_spec.rb +13 -13
- data/spec/mongoid/four_spec.rb +14 -14
- data/spec/mongoid/three_spec.rb +14 -14
- data/spec/mongoid/two_spec.rb +7 -7
- data/spec/test_helpers_spec.rb +11 -3
- metadata +4 -4
@@ -18,8 +18,8 @@ class Money
|
|
18
18
|
case
|
19
19
|
when object.is_a?(Money)
|
20
20
|
{
|
21
|
-
:
|
22
|
-
:
|
21
|
+
cents: object.cents.is_a?(BigDecimal) ? object.cents.to_s : object.cents,
|
22
|
+
currency_iso: object.currency.iso_code
|
23
23
|
}
|
24
24
|
when object.nil? then nil
|
25
25
|
when object.respond_to?(:to_money)
|
@@ -16,6 +16,11 @@ module MoneyRails
|
|
16
16
|
self
|
17
17
|
end
|
18
18
|
|
19
|
+
def with_model_currency(attribute)
|
20
|
+
@currency_attribute = attribute
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
19
24
|
def as(virt_attr)
|
20
25
|
@as = virt_attr
|
21
26
|
self
|
@@ -39,7 +44,8 @@ module MoneyRails
|
|
39
44
|
object_responds_to_attributes? &&
|
40
45
|
test_allow_nil &&
|
41
46
|
is_monetized? &&
|
42
|
-
test_currency_iso
|
47
|
+
test_currency_iso &&
|
48
|
+
test_currency_attribute
|
43
49
|
end
|
44
50
|
|
45
51
|
|
@@ -75,21 +81,29 @@ module MoneyRails
|
|
75
81
|
|
76
82
|
def test_allow_nil
|
77
83
|
if @allow_nil
|
78
|
-
@actual.
|
79
|
-
@actual.
|
84
|
+
@actual.public_send(@money_attribute_setter, "")
|
85
|
+
@actual.public_send(@money_attribute).nil?
|
80
86
|
else
|
81
87
|
true
|
82
88
|
end
|
83
89
|
end
|
84
90
|
|
85
91
|
def is_monetized?
|
86
|
-
@actual.
|
87
|
-
@actual.
|
92
|
+
@actual.public_send(@money_attribute_setter, 1)
|
93
|
+
@actual.public_send(@money_attribute).instance_of?(Money)
|
88
94
|
end
|
89
95
|
|
90
96
|
def test_currency_iso
|
91
97
|
if @currency_iso
|
92
|
-
@actual.
|
98
|
+
@actual.public_send(@money_attribute).currency.id == @currency_iso
|
99
|
+
else
|
100
|
+
true
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_currency_attribute
|
105
|
+
if @currency_attribute
|
106
|
+
@actual.public_send(@money_attribute).currency == @actual.public_send(@currency_attribute)
|
93
107
|
else
|
94
108
|
true
|
95
109
|
end
|
data/lib/money-rails/version.rb
CHANGED
data/money-rails.gemspec
CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |s|
|
|
26
26
|
|
27
27
|
s.require_path = "lib"
|
28
28
|
|
29
|
-
s.add_dependency "money", "~> 6.
|
29
|
+
s.add_dependency "money", "~> 6.11.0"
|
30
30
|
s.add_dependency "monetize", "~> 1.7.0"
|
31
31
|
s.add_dependency "activesupport", ">= 3.0"
|
32
32
|
s.add_dependency "railties", ">= 3.0"
|
@@ -7,17 +7,17 @@ class Sub < Product; end
|
|
7
7
|
if defined? ActiveRecord
|
8
8
|
describe MoneyRails::ActiveRecord::Monetizable do
|
9
9
|
let(:product) do
|
10
|
-
Product.create(:
|
11
|
-
:
|
12
|
-
:
|
13
|
-
:
|
14
|
-
:
|
15
|
-
:
|
10
|
+
Product.create(price_cents: 3000, discount: 150,
|
11
|
+
bonus_cents: 200, optional_price: 100,
|
12
|
+
sale_price_amount: 1200, delivery_fee_cents: 100,
|
13
|
+
restock_fee_cents: 2000,
|
14
|
+
reduced_price_cents: 1500, reduced_price_currency: :lvl,
|
15
|
+
lambda_price_cents: 4000)
|
16
16
|
end
|
17
17
|
|
18
18
|
describe ".monetize" do
|
19
19
|
let(:service) do
|
20
|
-
Service.create(:
|
20
|
+
Service.create(charge_cents: 2000, discount_cents: 120)
|
21
21
|
end
|
22
22
|
|
23
23
|
context ".monetized_attributes" do
|
@@ -66,14 +66,14 @@ if defined? ActiveRecord
|
|
66
66
|
end
|
67
67
|
|
68
68
|
it "assigns the correct value from a Money object using create" do
|
69
|
-
product = Product.create(:
|
70
|
-
:
|
69
|
+
product = Product.create(price: Money.new(3210, "USD"), discount: 150,
|
70
|
+
bonus_cents: 200, optional_price: 100)
|
71
71
|
expect(product.valid?).to be_truthy
|
72
72
|
expect(product.price_cents).to eq(3210)
|
73
73
|
end
|
74
74
|
|
75
75
|
it "correctly updates from a Money object using update_attributes" do
|
76
|
-
expect(product.update_attributes(:
|
76
|
+
expect(product.update_attributes(price: Money.new(215, "USD"))).to be_truthy
|
77
77
|
expect(product.price_cents).to eq(215)
|
78
78
|
end
|
79
79
|
|
@@ -187,8 +187,8 @@ if defined? ActiveRecord
|
|
187
187
|
end
|
188
188
|
|
189
189
|
it "respects numericality validation when using update_attributes" do
|
190
|
-
expect(product.update_attributes(:
|
191
|
-
expect(product.update_attributes(:
|
190
|
+
expect(product.update_attributes(price_cents: "some text")).to be_falsey
|
191
|
+
expect(product.update_attributes(price_cents: 2000)).to be_truthy
|
192
192
|
end
|
193
193
|
|
194
194
|
it "uses numericality validation on money attribute" do
|
@@ -213,6 +213,12 @@ if defined? ActiveRecord
|
|
213
213
|
expect(product.save).to be_truthy
|
214
214
|
end
|
215
215
|
|
216
|
+
it "shouldn't init empty key in errors" do
|
217
|
+
product.price = Money.new(320, "USD")
|
218
|
+
product.valid?
|
219
|
+
expect(product.errors.has_key?(:price)).to be_falsey
|
220
|
+
end
|
221
|
+
|
216
222
|
it "fails validation with the proper error message if money value is invalid decimal" do
|
217
223
|
product.price = "12.23.24"
|
218
224
|
expect(product.save).to be_falsey
|
@@ -303,9 +309,9 @@ if defined? ActiveRecord
|
|
303
309
|
end
|
304
310
|
|
305
311
|
it "fails validation if linked attribute changed" do
|
306
|
-
product = Product.create(:
|
307
|
-
:
|
308
|
-
:
|
312
|
+
product = Product.create(price: Money.new(3210, "USD"), discount: 150,
|
313
|
+
validates_method_amount: 100,
|
314
|
+
bonus_cents: 200, optional_price: 100)
|
309
315
|
expect(product.valid?).to be_truthy
|
310
316
|
product.optional_price = 50
|
311
317
|
expect(product.valid?).to be_falsey
|
@@ -365,22 +371,22 @@ if defined? ActiveRecord
|
|
365
371
|
end
|
366
372
|
|
367
373
|
it "fails validation when a non number string is given" do
|
368
|
-
product = Product.create(:
|
374
|
+
product = Product.create(price_in_a_range: "asd")
|
369
375
|
expect(product.valid?).to be_falsey
|
370
376
|
expect(product.errors[:price_in_a_range].size).to eq(1)
|
371
377
|
expect(product.errors[:price_in_a_range].first).to match(/greater than zero/)
|
372
378
|
|
373
|
-
product = Product.create(:
|
379
|
+
product = Product.create(price_in_a_range: "asd23")
|
374
380
|
expect(product.valid?).to be_falsey
|
375
381
|
expect(product.errors[:price_in_a_range].size).to eq(1)
|
376
382
|
expect(product.errors[:price_in_a_range].first).to match(/greater than zero/)
|
377
383
|
|
378
|
-
product = Product.create(:
|
384
|
+
product = Product.create(price: "asd")
|
379
385
|
expect(product.valid?).to be_falsey
|
380
386
|
expect(product.errors[:price].size).to eq(1)
|
381
387
|
expect(product.errors[:price].first).to match(/is not a number/)
|
382
388
|
|
383
|
-
product = Product.create(:
|
389
|
+
product = Product.create(price: "asd23")
|
384
390
|
expect(product.valid?).to be_falsey
|
385
391
|
expect(product.errors[:price].size).to eq(1)
|
386
392
|
expect(product.errors[:price].first).to match(/is not a number/)
|
@@ -409,8 +415,8 @@ if defined? ActiveRecord
|
|
409
415
|
end
|
410
416
|
|
411
417
|
it "respects numericality validation when using update_attributes on money attribute" do
|
412
|
-
expect(product.update_attributes(:
|
413
|
-
expect(product.update_attributes(:
|
418
|
+
expect(product.update_attributes(price: "some text")).to be_falsey
|
419
|
+
expect(product.update_attributes(price: Money.new(320, 'USD'))).to be_truthy
|
414
420
|
end
|
415
421
|
|
416
422
|
it "uses i18n currency format when validating" do
|
@@ -586,8 +592,8 @@ if defined? ActiveRecord
|
|
586
592
|
end
|
587
593
|
|
588
594
|
it "sets field to nil, in instantiation if allow_nil is set" do
|
589
|
-
pr = Product.new(:
|
590
|
-
:
|
595
|
+
pr = Product.new(optional_price: nil, price_cents: 5320,
|
596
|
+
discount: 350, bonus_cents: 320)
|
591
597
|
expect(pr.optional_price).to be_nil
|
592
598
|
expect(pr.save).to be_truthy
|
593
599
|
expect(pr.optional_price).to be_nil
|
@@ -609,23 +615,23 @@ if defined? ActiveRecord
|
|
609
615
|
|
610
616
|
context "for column with model currency:" do
|
611
617
|
it "has default currency if not specified" do
|
612
|
-
product = Product.create(:
|
618
|
+
product = Product.create(sale_price_amount: 1234)
|
613
619
|
product.sale_price.currency_as_string == 'USD'
|
614
620
|
end
|
615
621
|
|
616
622
|
it "is overridden by instance currency column" do
|
617
|
-
product = Product.create(:
|
618
|
-
:
|
623
|
+
product = Product.create(sale_price_amount: 1234,
|
624
|
+
sale_price_currency_code: 'CAD')
|
619
625
|
expect(product.sale_price.currency_as_string).to eq('CAD')
|
620
626
|
end
|
621
627
|
|
622
628
|
it 'can change currency of custom column' do
|
623
629
|
product = Product.create!(
|
624
|
-
:
|
625
|
-
:
|
626
|
-
:
|
627
|
-
:
|
628
|
-
:
|
630
|
+
price: Money.new(10,'USD'),
|
631
|
+
bonus: Money.new(10,'GBP'),
|
632
|
+
discount: 10,
|
633
|
+
sale_price_amount: 1234,
|
634
|
+
sale_price_currency_code: 'USD'
|
629
635
|
)
|
630
636
|
|
631
637
|
expect(product.sale_price.currency_as_string).to eq('USD')
|
@@ -641,21 +647,21 @@ if defined? ActiveRecord
|
|
641
647
|
|
642
648
|
context "for model with currency column:" do
|
643
649
|
let(:transaction) do
|
644
|
-
Transaction.create(:
|
645
|
-
:
|
650
|
+
Transaction.create(amount_cents: 2400, tax_cents: 600,
|
651
|
+
currency: :usd)
|
646
652
|
end
|
647
653
|
|
648
654
|
let(:dummy_product) do
|
649
|
-
DummyProduct.create(:
|
655
|
+
DummyProduct.create(price_cents: 2400, currency: :usd)
|
650
656
|
end
|
651
657
|
|
652
658
|
let(:dummy_product_with_nil_currency) do
|
653
|
-
DummyProduct.create(:
|
659
|
+
DummyProduct.create(price_cents: 2600) # nil currency
|
654
660
|
end
|
655
661
|
|
656
662
|
let(:dummy_product_with_invalid_currency) do
|
657
663
|
# invalid currency
|
658
|
-
DummyProduct.create(:
|
664
|
+
DummyProduct.create(price_cents: 2600, currency: :foo)
|
659
665
|
end
|
660
666
|
|
661
667
|
it "correctly serializes the currency to a new instance of model" do
|
@@ -691,7 +697,7 @@ if defined? ActiveRecord
|
|
691
697
|
end
|
692
698
|
|
693
699
|
it "correctly instantiates Money objects from the mapped attributes" do
|
694
|
-
t = Transaction.new(:
|
700
|
+
t = Transaction.new(amount_cents: 2500, currency: "CAD")
|
695
701
|
expect(t.amount).to eq(Money.new(2500, "CAD"))
|
696
702
|
end
|
697
703
|
|
@@ -726,7 +732,7 @@ if defined? ActiveRecord
|
|
726
732
|
|
727
733
|
context "and field with allow_nil: true" do
|
728
734
|
it "doesn't set currency to nil when setting the field to nil" do
|
729
|
-
t = Transaction.new(:
|
735
|
+
t = Transaction.new(amount_cents: 2500, currency: "CAD")
|
730
736
|
t.optional_amount = nil
|
731
737
|
expect(t.currency).to eq("CAD")
|
732
738
|
end
|
@@ -907,7 +913,7 @@ if defined? ActiveRecord
|
|
907
913
|
end
|
908
914
|
|
909
915
|
it "resets monetized attribute when given blank input" do
|
910
|
-
product.write_monetized :price, :price_cents, nil, false, nil, { :
|
916
|
+
product.write_monetized :price, :price_cents, nil, false, nil, { allow_nil: true }
|
911
917
|
|
912
918
|
expect(product.price).to eq(nil)
|
913
919
|
end
|
@@ -1005,7 +1011,7 @@ if defined? ActiveRecord
|
|
1005
1011
|
|
1006
1012
|
describe "#currency_for" do
|
1007
1013
|
it "detects currency based on instance currency name" do
|
1008
|
-
product = Product.new(:
|
1014
|
+
product = Product.new(sale_price_currency_code: 'CAD')
|
1009
1015
|
currency = product.send(:currency_for, :sale_price, :sale_price_currency_code, nil)
|
1010
1016
|
|
1011
1017
|
expect(currency).to be_an_instance_of(Money::Currency)
|
data/spec/configuration_spec.rb
CHANGED
@@ -76,11 +76,11 @@ describe "configuration" do
|
|
76
76
|
value = Money.new(-12345600, "EUR")
|
77
77
|
symbol = Money::Currency.find(:eur).symbol
|
78
78
|
|
79
|
-
MoneyRails.default_format = {:
|
79
|
+
MoneyRails.default_format = {symbol_position: :after}
|
80
80
|
expect(value.format).to match(/#{symbol}\z/)
|
81
81
|
|
82
82
|
# Override with "classic" format options for backward compatibility
|
83
|
-
MoneyRails.default_format = {:
|
83
|
+
MoneyRails.default_format = {sign_before_symbol: :false}
|
84
84
|
MoneyRails.sign_before_symbol = true
|
85
85
|
expect(value.format).to match(/-#{symbol}/)
|
86
86
|
|
@@ -6,30 +6,31 @@ class Product < ActiveRecord::Base
|
|
6
6
|
monetize :price_cents
|
7
7
|
|
8
8
|
# Use money-rails macro with multiple fields
|
9
|
-
monetize :delivery_fee_cents, :restock_fee_cents, :
|
9
|
+
monetize :delivery_fee_cents, :restock_fee_cents, allow_nil: true
|
10
10
|
|
11
11
|
# Use a custom name for the Money attribute
|
12
|
-
monetize :discount, :
|
12
|
+
monetize :discount, as: "discount_value"
|
13
13
|
|
14
14
|
# Allow nil
|
15
|
-
monetize :optional_price_cents, :
|
15
|
+
monetize :optional_price_cents, allow_nil: true
|
16
16
|
|
17
17
|
# Override default currency (EUR) with a specific one (GBP) for this field only
|
18
|
-
monetize :bonus_cents, :
|
18
|
+
monetize :bonus_cents, with_currency: :gbp
|
19
19
|
|
20
20
|
# Use currency column to determine currency for this field only
|
21
|
-
monetize :sale_price_amount, :
|
22
|
-
:
|
23
|
-
|
24
|
-
monetize :price_in_a_range_cents, :
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
21
|
+
monetize :sale_price_amount, as: :sale_price,
|
22
|
+
with_model_currency: :sale_price_currency_code
|
23
|
+
|
24
|
+
monetize :price_in_a_range_cents, allow_nil: true,
|
25
|
+
subunit_numericality: {
|
26
|
+
greater_than: 0,
|
27
|
+
less_than_or_equal_to: 10000
|
28
|
+
},
|
29
|
+
numericality: {
|
30
|
+
greater_than: 0,
|
31
|
+
less_than_or_equal_to: 100,
|
32
|
+
message: "must be greater than zero and less than $100"
|
33
|
+
}
|
33
34
|
|
34
35
|
# Skip validations separately from each other
|
35
36
|
monetize :skip_validation_price_cents, subunit_numericality: false, numericality: false, allow_nil: true
|
@@ -42,16 +43,17 @@ class Product < ActiveRecord::Base
|
|
42
43
|
|
43
44
|
monetize :validates_method_amount_cents, allow_nil: true
|
44
45
|
|
45
|
-
validates :validates_method_amount, :
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
46
|
+
validates :validates_method_amount, money: {
|
47
|
+
greater_than: 0,
|
48
|
+
less_than_or_equal_to: ->(product) { product.optional_price.to_f },
|
49
|
+
message: 'must be greater than zero and less than $100',
|
50
|
+
},
|
51
|
+
allow_nil: true
|
50
52
|
|
51
53
|
alias_attribute :renamed_cents, :aliased_cents
|
52
54
|
|
53
55
|
monetize :renamed_cents, allow_nil: true
|
54
56
|
|
55
57
|
# Using postfix to determine currency column (reduced_price_currency)
|
56
|
-
monetize :reduced_price_cents, :
|
58
|
+
monetize :reduced_price_cents, allow_nil: true
|
57
59
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
class Transaction < ActiveRecord::Base
|
2
|
-
monetize :amount_cents, :
|
2
|
+
monetize :amount_cents, with_model_currency: :currency
|
3
3
|
|
4
|
-
monetize :tax_cents, :
|
4
|
+
monetize :tax_cents, with_model_currency: :currency
|
5
5
|
|
6
|
-
monetize :total_cents, :
|
6
|
+
monetize :total_cents, with_model_currency: :currency
|
7
7
|
|
8
|
-
monetize :optional_amount_cents, :
|
8
|
+
monetize :optional_amount_cents, with_model_currency: :currency, allow_nil: true
|
9
9
|
|
10
10
|
def total_cents
|
11
11
|
return amount_cents + tax_cents
|
@@ -18,14 +18,14 @@ MoneyRails.configure do |config|
|
|
18
18
|
# Register a custom currency
|
19
19
|
#
|
20
20
|
config.register_currency = {
|
21
|
-
:
|
22
|
-
:
|
23
|
-
:
|
24
|
-
:
|
25
|
-
:
|
26
|
-
:
|
27
|
-
:
|
28
|
-
:
|
29
|
-
:
|
21
|
+
priority: 1,
|
22
|
+
iso_code: "EU4",
|
23
|
+
name: "Euro with subunit of 4 digits",
|
24
|
+
symbol: "€",
|
25
|
+
symbol_first: true,
|
26
|
+
subunit: "Subcent",
|
27
|
+
subunit_to_unit: 10000,
|
28
|
+
thousands_separator: ".",
|
29
|
+
decimal_mark: ","
|
30
30
|
}
|
31
31
|
end
|