249 votos

Ruby on Rails: el mejor método de manejo de moneda / dinero

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?

372voto

molf Puntos 34978

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 BigDecimals 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

92voto

Ken Mayer Puntos 793

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

20voto

neutrino Puntos 11643

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.

3voto

Thomas Klemm Puntos 4335

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.

2voto

jethroo Puntos 839

Si alguien está usando secuela la migración se vería algo así como:

add_column :products, :price, "decimal(8,2)"

de alguna manera secuela ignora: precisión y: escala

(Versión de secuela: secuela (3.39.0, 3.38.0))

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X