2010-01-25 30 views
2

En regardant SO, je vois que le moyen préféré de la monnaie en utilisant RoR est d'utiliser decimal (8,2) et de les sortir en utilisant number_to_currency();Ruby on Rails - Monnaie: virgules provoquant un problème

Je peux obtenir mes numéros de la DB, mais je vais avoir des questions sur les obtenir dans

Dans mon action de mise à jour je la ligne suivante:.

if @non_labor_expense.update_attributes(params[:non_labor_expense]) 
puts YAML::dump(params) 

La décharge de params montre la valeur correcte. xx, yyy.zz, mais ce qui est stocké dans la BD est seulement xx.00

Que dois-je faire pour tenir compte du fait qu'il peut y avoir des virgules et un utilisateur ne peut pas entrer .zz (les cents). Certains regex et pour la virgule? comment géreriez-vous la décimale si elle était .2 contre .20.

Il doit y avoir une version intégrée ou au moins une meilleure.

Ma migration (je ne sais pas si cela aide):

class ChangeExpenseToDec < ActiveRecord::Migration 
    def self.up 
     change_column :non_labor_expenses, :amount, :decimal, :precision => 8, :scale => 2 
    end 

    def self.down 
      change_column :non_labor_expenses, :amount, :integer 
    end 
end 
+0

.2 et .20 sont les mêmes numbe r, donc peu importe comment vous le stockez, juste comment vous l'affichez. –

+0

Droite. Le premier problème est que je perds les données après la virgule. Vous dites qu'une fois, je résous cela, le .2 et .20 va se résoudre sur la façon dont il est stocké dans la base de données? – easement

+0

Voir ma réponse; Fondamentalement, vous stockez le nombre dans la base de données en tant que nombre décimal droit (non formaté), puis le formater comme vous le souhaitez lorsque vous avez besoin de l'afficher. –

Répondre

5

Cela peut dépendre de ce que vous utilisez SGBD, mais pour autant que je sache, les champs décimaux ne seront pas accepter des virgules (au moins pas en tant que séparateurs, il pourrait y avoir un moyen pour que la base de données accepte une virgule comme point décimal plutôt qu'un point). Ce que vous devez faire est de retirer les virgules de vos numéros (dans un filtre before_save ou before_validation, peut-être), puis lorsque vous affichez le nombre, ajoutez les virgules avant.

before_validation :strip_commas_from_non_labor_expense 

def strip_commas_from_non_labor_expense 
    self.non_labor_expense = self.non_labor_expense.to_s.gsub(/,/, '').to_f 
end 

Ensuite, utilisez number_to_currency lorsque vous voulez afficher le montant des dépenses formatées avec des groupes séparés par des virgules et deux décimales, comme vous l'avez mentionné:

<% 
    non_labor_expense = ... # get value from your model 
    puts number_to_currency(non_labor_expense, :precision => 2, :separator => ',') 
%> 
+0

J'ai essayé votre before_validation et la fonction dans le modèle, et je mets YAML :: dump (self.amount) mais le montant est déjà tronqué. Je reçois l'erreur suivante: méthode privée 'gsub! ' appelé pour # quand je change votre code à: self.amount.gsub! ('/, /', '') Des idées? – easement

+0

Si je fais self.amount.to_s.gsub! ('/, /', '') Alors gsub! fonctionne, mais en effectuant un vidage avant que j'appelle cet appel, il semble que la valeur est déjà tronquée. des idées? – easement

+0

Désolé, j'ai mis à jour ma réponse. Les guillemets ne sont pas nécessaires autour de l'expression régulière (je suis en mode PHP aujourd'hui, heh) et 'gsub' devrait être utilisé plutôt que' gsub! 'Car ce dernier remplace la chaîne par' nil' si aucun remplacement n'a été fait. Aussi, j'ai ajouté 'to_f' à la fin pour le remettre dans un flotteur. –

7

J'ai essayé l'idée de before_validation de Daniel et je ne pouvais pas le faire fonctionner. Il semble que le moment où j'arrive à l'before_validation, l'entrée a déjà été convertie. La solution que je suis allé avec était de passer outre la méthode de la colonne, et dénuder les virgules là:

def profit=(num) 
    num.gsub!(',','') if num.is_a?(String) 
    self[:profit] = num 
end 
+0

Cela a fonctionné très bien pour moi, merci. – weston

+0

Fonctionne, mais la suggestion de Henning est DRY'er si vous avez l'intention de convertir, à. pour plusieurs entrées dans l'application. – Magne

+0

Merci, bonne solution! – ExiRe