money-rails 1.10.0 → 1.11.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.
- 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
|