Quelle est la meilleure méthode de gestion de la monnaie / de l’argent?

Je travaille sur un système de panier d’achat très basique.

J’ai un items table qui a un price de colonne de type integer .

J’ai du mal à afficher la valeur du prix dans mes vues pour des prix qui incluent à la fois des euros et des centimes. Est-ce que quelque chose d’évident est manquant en ce qui concerne la gestion des devises dans le cadre de Rails?

Vous voudrez probablement utiliser un type DECIMAL dans votre firebase database. Dans votre migration, faites quelque chose comme ceci:

 # 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 

Dans Rails, le type :decimal est renvoyé sous la forme BigDecimal , ce qui est idéal pour le calcul du prix.

Si vous insistez sur l’utilisation d’entiers, vous devrez convertir manuellement depuis et vers BigDecimal partout dans le monde, ce qui deviendra probablement difficile.

Comme le souligne mcl, pour imprimer le prix, utilisez:

 number_to_currency(price, :unit => "€") #=> €1,234.01 

Voici une approche simple et fine qui tire parti de compose_of (partie d’ActiveRecord, en utilisant le modèle ValueObject) et du joyau de Money

Tu auras besoin

  • Le joyau de l’argent (version 4.1.0)
  • Un modèle, par exemple Product
  • Une colonne integer dans votre modèle (et firebase database), par exemple :price

Ecrivez ceci dans votre fichier product.rb :

 class Product > ActiveRecord::Base composed_of :price, :class_name => 'Money', :mapping => %w(price cents), :converter => Proc.new { |value| Money.new(value) } # ... 

Qu’est-ce que vous aurez:

  • Sans aucune modification supplémentaire, tous vos formulaires afficheront des dollars et des cents, mais la représentation interne ne représente que des cents. Les formulaires accepteront des valeurs comme “$ 12,034.95” et les convertiront pour vous. Il n’est pas nécessaire d’append des gestionnaires ou des atsortingbuts supplémentaires à votre modèle ou à vos assistants à votre avis.
  • product.price = "$12.00" convertit automatiquement dans la classe Money
  • product.price.to_s affiche un nombre décimal (“1234.00”)
  • product.price.format affiche une chaîne correctement formatée pour la devise
  • Si vous devez envoyer des centimes (à une passerelle de paiement qui veut des sous), product.price.cents.to_s
  • Conversion de devises gratuite

La pratique courante du traitement de la devise consiste à utiliser le type décimal. Voici un exemple simple de “Développement Web Agile avec Rails”

 add_column :products, :price, :decimal, :precision => 8, :scale => 2 

Cela vous permettra de gérer les prix de -999 999,99 à 999 999,99
Vous pouvez également vouloir inclure une validation dans vos articles comme

 def validate errors.add(:price, "should be at least 0.01") if price.nil? || price < 0.01 end 

pour vérifier la validité de vos valeurs.

Utilisez un bijou de rails d’argent . Il gère bien l’argent et les devises dans votre modèle et dispose également d’un grand nombre d’aides pour formater vos prix.

À l’aide d’ atsortingbuts virtuels (lien vers la diffusion en direct révisée (payante)), vous pouvez stocker vos prix dans une colonne entière et append un atsortingbut virtuel price_in_dollars dans votre modèle de produit en tant que getter et setter.

 # Add a price_in_cents integer column $ rails g migration add_price_in_cents_to_products price_in_cents:integer # Use virtual atsortingbutes 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 

Source: RailsCasts # 016: Atsortingbuts virtuels : les atsortingbuts virtuels sont un moyen propre d’append des champs de formulaire qui ne sont pas directement mappés à la firebase database. Ici, je montre comment gérer les validations, les associations, etc.

Si vous utilisez Postgres (et que nous sums en 2017 maintenant), vous voudrez peut-être essayer leur type de colonne :money .

 add_column :products, :price, :money, default: 0 

Certainement des entiers .

Et même si BigDecimal existe techniquement, 1.5 vous donnera toujours un Float pur en Ruby.

Si quelqu’un utilise Sequel, la migration ressemblerait à ceci:

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

en quelque sorte Sequel ignore: la précision et: l’échelle

(Sequel Version: suite (3.39.0, 3.38.0))

Je l’utilise de cette façon:

 number_to_currency(amount, unit: '€', precision: 2, format: "%u %n") 

Bien sûr, le symbole monétaire, la précision, le format, etc. dépendent de chaque devise.

Vous pouvez passer certaines options à number_to_currency (un assistant de vue Rails 4 standard):

 number_to_currency(12.0, :precision => 2) # => "$12.00" 

Publié par Dylan Markow

Mes API sous-jacentes utilisaient toutes des cents pour représenter l’argent, et je ne voulais pas changer cela. Je ne travaillais pas non plus avec de grosses sums d’argent. Donc, je viens de mettre cela dans une méthode d’assistance:

 sprintf("%03d", amount).insert(-3, ".") 

Cela convertit le nombre entier en une chaîne d’au moins trois chiffres (en ajoutant des zéros en tête si nécessaire), puis insère un point décimal avant les deux derniers chiffres, sans jamais utiliser de Float . De là, vous pouvez append les symboles de devise appropriés à votre cas d’utilisation.

C’est vraiment rapide et sale, mais parfois ça va!

Code simple pour Ruby & Rails

 < %= number_to_currency(1234567890.50) %> OUT PUT => $1,234,567,890.50