2010-05-04 3 views
5

Ich versuche, einen Dollar-Betrag mit einem regex zu überprüfen: ^[0-9]+\.[0-9]{2}$Gleitkommagenauigkeit in Ruby on Rails Modellvalidierungen

Dies funktioniert gut, aber wenn ein Benutzer das Formular abschickt und der Dollar-Betrag endet in 0 (Null), Rubin (oder Schienen?) hackt die 0 aus. 500.00 wird also zu 500.0, wodurch die Regex-Validierung fehlschlägt.

Gibt es eine Möglichkeit, Ruby/Rails das vom Benutzer eingegebene Format beizubehalten, unabhängig von nachfolgenden Nullen?

+1

Gibt es einen Grund, warum Sie 'validates_numericality_of' anstelle von Regex verwenden? –

+0

Wie würde ich 'validates_numericality_of' verwenden, um sicherzustellen, dass 500.001 fehlschlägt? Ich möchte nur, speziell formatiert, '[jede Zahl von 0 bis 9 Ziffern]. [2 von 0 bis 9 Ziffern]' - also mit 'validates_format_of: menge,: mit =>/^ [0-9] + \.[0-9] {2} $ /,: message => "muss Dollar und Cents enthalten, getrennt durch einen Zeitraum" ' –

Antwort

8

Ich nehme an, dass Ihr Dollar-Betrag vom Dezimaltyp ist. Jeder Wert, den der Benutzer in das Feld eingibt, wird vor dem Speichern in die Datenbank von String in den entsprechenden Typ umgewandelt. Die Validierung gilt für die Werte, die bereits in numerische Typen konvertiert wurden. Daher ist Regex in Ihrem Fall kein geeigneter Validierungsfilter.

Sie haben mehrere Möglichkeiten, dies zu lösen, aber:

  1. Verwendung validates_numericality_of. Auf diese Weise verlassen Sie die Konvertierung komplett auf Rails und prüfen einfach, ob der Betrag in einem bestimmten Bereich liegt.
  2. Verwenden Sie validate_each Methode und Code Ihre Validierungslogik selbst (z. B. prüfen, ob der Wert mehr als 2 Dezimalstellen hat).
  3. Validate die attribute before it's been typecasted:

Dies ist besonders nützlich in Validierung Situationen, in denen der Benutzer könnte eine Zeichenfolge für eine ganze Zahl Feld liefern und Ihnen die Original-String zurück in einem Fehler angezeigt werden soll Botschaft. Der Zugriff auf das Attribut würde normalerweise den String auf 0 typisieren, was nicht das ist, was Sie wollen.

also in Ihrem Fall sollten Sie in der Lage sein zu verwenden:

validates_format_of :amount_before_type_cast, :with => /^[0-9]+\.[0-9]{2}$/, :message => "must contain dollars and cents, seperated by a period" 

Beachten Sie jedoch, dass Benutzer könnte es langweilig finden Ihre starren Eingaberegeln zu folgen (ich würde wirklich in der Lage, am liebsten Geben Sie 500 stattdessen 500.00, zum Beispiel), und dass in einigen Ländern Zeitraum keine Dezimaltrennzeichen (wenn Sie Ihre App internationalisieren möchten).

+0

Würde ... ': amount_before_type_cast' ... trotzdem noch" 500.0 "in die DB einfügen? Validieren ist eine Sache, aber die Manager könnten immer noch die Zahlungsaufzeichnung hochziehen und sie würden "500.0" lesen, trotz der korrekten Eingabe der Benutzer? Siehe Antwort auf Arkku, die Starrheit/Strenge ist auf Anfrage. –

+0

Sie (und besonders die Manager) sollten sich nicht darum kümmern, wie ein Wert in der Datenbank gespeichert wird. Es ist eine Nummer, sie sollte als Zahl gespeichert werden (es gibt jedoch zahlreiche Zahlenformate in verschiedenen Datenbanken). Die Anzahl der Dezimalstellen sollte nur beim Formatieren der Ausgabe angegeben werden, d. H. In Ihrer Datenbankansicht. –

+1

Oh, und, bitte, niemals _ever_ in Betracht ziehen, diesen DB-Spaltentyp in String zu ändern. –

2

Im Allgemeinen, wenn Sie die Dezimalgenauigkeit eines Gleitkommawerts "merken" möchten, sollten Sie einen dezimalen Typ verwenden, kein binärer Gleitkommawert.

Auf der anderen Seite bin ich nicht sicher, warum Sie die String-Darstellung auf eine so strenge Art und Weise erzwingen möchten ... Wie wäre es mit der Annahme einer Zahl und Formatierung mit z. number_to_currency?

+0

Die Starrheit wurde vom CFO der Buchhaltung, für die diese App bestimmt ist, angefordert. Er möchte eigentlich, dass die Leute genau in diesem Format in die Form tippen. '@payment.amount = Zahl_zur_Währung (@ payment.amount,: unit => '') 'bevor' @ payment.save' (via Controller) die gleichen Ergebnisse liefert ... mache ich es falsch? –

+0

Ich fürchte, Sie sind ... number_to_currency ist für Präsentationszwecke gedacht, d. H. Zu verwenden, wenn die Menge in der Ansicht ausgegeben wird. Übrigens, wenn die Regeln so streng sind, könnten Sie eine clientseitige Validierung in Erwägung ziehen, ich bin mir sicher, dass es dafür eine Menge jQuery- und prototypbasierter Lösungen gibt. –

0

Normalerweise mit Geld ist es am besten, es als eine ganze Zahl in Cents (500 Cent ist 5,00 $) zu speichern. Ich benutze die Money gem, um damit umzugehen.