Reputation: 229
I've already done this without any issue, but today I cannot get it working.
I have a migration as follows
class AddAmountToInvoices < ActiveRecord::Migration
def change
add_column :invoices, :amount, :decimal, :precision => 2
end
end
But then when I set a BigDecimal value the decimal part get the decimal part ignored.
By looking at the Invoice
model inside the rails console
I can see it is declaring :amount
as a integer
as you can see:
=> Invoice(id: integer, invoice_number: integer, brogliaccio_id: string, kind: string, tax_id: string, payment_method: string, openmanager_user_id: string, created_at: datetime, updated_at: datetime, event_id: integer, amount: integer)
This is the invoice.rb model:
# encoding: utf-8
class Invoice < ActiveRecord::Base
belongs_to :event
KINDS = ["Detrazione", "Non Detrazione"]
TAX_IDS = {"4%" => "004", "10%" => "010", "22%" => "022"}
PAYMENT_METHODS = {"Bonifico" => "BB", "Contanti" => "CO", "Finanziamento" => "FI", "Assegno" => "AS"}
attr_accessor :amount_string # we need this to handle custom number-format
attr_accessible :amount_string, :brogliaccio_id, :invoice_number, :kind, :openmanager_user_id, :payment_method, :tax_id, :amount
validates_presence_of :amount, :kind, :payment_method, :tax_id, :openmanager_user_id
validates_inclusion_of :kind, :in => Invoice::KINDS
validates_inclusion_of :tax_id, :in => Invoice::TAX_IDS.values()
validates_inclusion_of :payment_method, :in => Invoice::PAYMENT_METHODS.values()
validate :minimum_amount
# we get a string formatted as "10.000,50" that needs to be converted to "10000.50"
# to assure it will be correctly interpretated
def amount_string=(value)
value = value.gsub(/\./, '').gsub(/,/, '.')
self.amount = BigDecimal.new(value, 2)
end
def amount_string
self.amount
end
private
def minimum_amount
unless self.amount.blank?
if self.amount < BigDecimal.new("10.0")
errors.add(:base, "min invoice amount must be 10$")
end
end
end
end
What am I doing wrong here?
Upvotes: 0
Views: 152
Reputation: 480
As described here (link) you should use :scale
instead of :precision
(or both). Precision is for the number of relevant digits, so if you set it to 2 you have 2 relevant digits like 10 or 12 or 1.2 or 0.3 and so on.
"For clarity’s sake: the precision is the number of significant digits, while the scale is the number of digits that can be stored following the decimal point. For example, the number 123.45 has a precision of 5 and a scale of 2. A decimal with a precision of 5 and a scale of 2 can range from -999.99 to 999.99."
So if you want to have an Amount with two digits after the . the migration should look like the following:
class AddAmountToInvoices < ActiveRecord::Migration
def change
add_column :invoices, :amount, :decimal, :scale => 2
end
end
Upvotes: 1