Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions lib/money-rails/active_record/monetizable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ def monetize(*fields)
"Use :as option to explicitly specify the name or change the amount column postfix in the initializer."
end

# Assigns infinite_precision based on the field's column type, if available
options[:infinite_precision] = self.columns_hash[subunit_name].try(:type) == :decimal

# Optional accessor to be run on an instance to detect currency
instance_currency_name = options[:with_model_currency] ||
options[:model_currency] ||
Expand Down Expand Up @@ -194,14 +197,14 @@ def read_monetized(name, subunit_name, options = {}, *args)
if memoized.currency == attr_currency
result = memoized
else
memoized_amount = memoized.amount.to_money(attr_currency)
memoized_amount = memoized.amount.to_money(attr_currency, options.slice(:infinite_precision))
write_attribute subunit_name, memoized_amount.cents
# Cache the value (it may be nil)
result = instance_variable_set("@#{name}", memoized_amount)
end
elsif amount.present?
# If amount is NOT nil (or empty string) load the amount in a Money
amount = Money.new(amount, attr_currency)
amount = Money.new(amount, attr_currency, options.slice(:infinite_precision))

# Cache the value (it may be nil)
result = instance_variable_set("@#{name}", amount)
Expand Down Expand Up @@ -230,7 +233,7 @@ def write_monetized(name, subunit_name, value, validation_enabled, instance_curr
money = value
else
begin
money = value.to_money(public_send("currency_for_#{name}"))
money = value.to_money(public_send("currency_for_#{name}"), options.slice(:infinite_precision))
rescue NoMethodError
return nil
rescue Money::Currency::UnknownCurrency, Monetize::ParseError => e
Expand Down
14 changes: 13 additions & 1 deletion spec/active_record/monetizable_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ class Sub < Product; end
sale_price_amount: 1200, delivery_fee_cents: 100,
restock_fee_cents: 2000,
reduced_price_cents: 1500, reduced_price_currency: :lvl,
lambda_price_cents: 4000)
lambda_price_cents: 4000,
unit_cost_cents: 1234.8765
)
end

describe ".monetize" do
Expand Down Expand Up @@ -141,6 +143,16 @@ class SubProduct < Product
expect(product.discount_value).to eq(Money.new(150, "USD"))
end

it "assigns instance precision based on the column type of the attribute" do
expect(product.unit_cost.infinite_precision?).to eq(true)
expect(product.unit_cost).to eq(Money.new(1234.8765, "USD", infinite_precision: true))
expect(product.unit_cost.to_s).to eq("12.348765")

expect(product.price.infinite_precision?).to eq(false)
expect(product.price).to eq(Money.new(3000, "USD", infinite_precision: false))
expect(product.price.to_s).to eq("30.00")
end

it "uses numericality validation" do
product.price_cents = "foo"
expect(product.save).to be_falsey
Expand Down
3 changes: 3 additions & 0 deletions spec/dummy/app/models/product.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,7 @@ class Product < ActiveRecord::Base

# Using postfix to determine currency column (reduced_price_currency)
monetize :reduced_price_cents, allow_nil: true

# Enable infinite_precision on this attribute
monetize :unit_cost_cents, allow_nil: true
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddPrecisionUnitCostToProducts < (Rails::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[4.2] : ActiveRecord::Migration)
def change
add_column :products, :unit_cost_cents, :decimal
end
end
3 changes: 2 additions & 1 deletion spec/dummy/db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 20151026220420) do
ActiveRecord::Schema.define(version: 20190814150759) do

create_table "dummy_products", force: :cascade do |t|
t.string "currency"
Expand Down Expand Up @@ -39,6 +39,7 @@
t.integer "special_price_cents"
t.integer "lambda_price_cents"
t.string "skip_validation_price_cents"
t.decimal "unit_cost_cents"
end

create_table "services", force: :cascade do |t|
Expand Down