Soy nuevo en Ruby on Rails y estoy trabajando en un sistema comercial muy básico del carro. Tengo una tabla items
que tiene una columna price
de tipo integer
. Me cuesta visualizar el valor del precio en mi punto de vista de los precios que incluyen Euros y centavos. ¿Me estoy perdiendo algo obvio en cuanto se refiere a manejo de divisas en el marco de los carriles?
Respuestas
¿Demasiados anuncios?Usted probablemente quiera usar un DECIMAL
tipo en su base de datos. En su migración, hacer algo como esto:
# precision is the total amount of digits
# scale is the number of digits right of the decimal point
add_column :items, :price, :decimal, :precision => 8, :scale => 2
En Rails, la :decimal
tipo se devuelve como BigDecimal
, lo cual es genial para el cálculo de precio.
Si usted insiste en el uso de números enteros, de forma manual convertir a y desde BigDecimal
s en todas partes, que probablemente va a convertirse en un dolor.
Como se ha señalado por el mcl, para imprimir el precio, utilice:
number_to_currency(price, :unit => "€")
#=> €1,234.01
He aquí un buen enfoque, sencillo que aprovecha composed_of
(parte de ActiveRecord, el uso de la ValueObject patrón) y el Dinero de la gema
Usted necesitará
- El Dinero de la gema (la versión 4.1.0)
- Un modelo, por ejemplo,
Product
- Un
integer
de columna en el modelo (y base de datos), por ejemplo,:price
Escribe esto en tu product.rb
archivo:
class Product > ActiveRecord::Base
composed_of :price,
:class_name => 'Money',
:mapping => %w(price cents),
:converter => Proc.new { |value| value.respond_to?(:to_money) ? value.to_money : Money.empty }
# ...
Lo que usted obtendrá:
- Sin ningún extra cambios, en todas sus formas se muestran en dólares y centavos, pero la representación interna es todavía sólo centavos. Los formularios se aceptan valores como "$12,034 .95" y convertirlo para usted. No hay necesidad de añadir los controladores o los atributos de su modelo, o ayudantes, en su opinión.
-
product.price = "$12.00"
convierte automáticamente el Dinero de la clase -
product.price.to_s
muestra un decimal formato de número ("1234.00") -
product.price.format
muestra correctamente el formato de cadena de la moneda - Si usted necesita enviar centavos (a una pasarela de pago que quiere centavos),
product.price.cents.to_s
- Conversión de moneda gratis
Práctica común para la manipulación de divisas es usar el tipo decimal. Aquí hay un ejemplo simple de "Desarrollo Web ágil con rieles"
add_column :products, :price, :decimal, :precision => 8, :scale => 2
Esto permitirá que te encargues de precios de-999,999.99 a 999,999.99
Quizá desee también 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
cordura-Compruebe sus valores.
El uso de Atributos Virtuales (Enlace revisado(de pago) Railscast) puede almacenar sus price_in_cents en una columna de tipo entero y añadir un atributo virtual price_in_dollars en el modelo de su producto como un getter y setter.
# Add a price_in_cents integer column
$ rails g migration add_price_in_cents_to_products price_in_cents:integer
# Use virtual attributes in your Product model
# app/models/product.rb
def price_in_dollars
price_in_cents.to_d/100 if price_in_cents
end
def price_in_dollars=(dollars)
self.price_in_cents = dollars.to_d*100 if dollars.present?
end
Fuente: RailsCasts #016: Virtual Atributos: atributos Virtuales son una manera limpia para agregar campos de formulario que no se asignan directamente a la base de datos. Aquí te muestro cómo manejar las validaciones, asociaciones, y más.