Estoy trabajando en un sistema de carrito de compras muy básico.
Tengo una tabla items
que tiene una columna price
de tipo integer
.
Estoy teniendo problemas para mostrar el valor del precio en mis puntos de vista para los precios que incluyen tanto euros y centavos. ¿Me estoy perdiendo algo obvio en lo que respecta al manejo de divisas en el framework Rails?
Probablemente querrá utilizar un tipo DECIMAL
en su base de datos. En su migración, haga algo como esto
# precision is the total number of digits
# scale is the number of digits to the right of the decimal point
add_column :items, :price, :decimal, :precision => 8, :scale => 2
En Rails, el tipo :decimal
se devuelve como BigDecimal
, que es genial para calcular precios.
Si insistes en usar enteros, tendrás que convertir manualmente a y desde BigDecimal
en todas partes, lo que probablemente se convierta en un engorro.
Como señala mcl, para imprimir el precio, utilice:
number_to_currency(price, :unit => "€")
#=> €1,234.01
He aquí un método sencillo que aprovecha composed_of
(parte de ActiveRecord, que utiliza el patrón ValueObject) y la gema Money
Necesitará
Producto
.integer
en su modelo (y base de datos), por ejemplo :price
.Escribe esto en tu fichero product.rb
:
class Product > ActiveRecord::Base
composed_of :price,
:class_name => 'Money',
:mapping => %w(price cents),
:converter => Proc.new { |value| Money.new(value) }
# ...
Lo que obtendrá:
product.price.format
muestra una cadena con el formato adecuado para la divisaproduct.price.cents.to_s
.La práctica común para el manejo de divisas es utilizar el tipo decimal. He aquí un ejemplo sencillo de "Agile Web Development with Rails"
add_column :products, :price, :decimal, :precision => 8, :scale => 2
Esto le permitirá manejar precios de -999,999.99 a 999,999.99 También puede incluir una validación en sus artículos como
def validate
errors.add(:price, "should be at least 0.01") if price.nil? || price < 0.01
end
para comprobar que los valores son correctos.