350 Stimmen

Was ist die beste Methode für den Umgang mit Geld?

Ich arbeite an einem sehr einfachen Einkaufswagen-System.

Ich habe eine Tabelle items die eine Spalte hat price vom Typ integer .

Ich habe Probleme, den Preiswert in meinen Ansichten für Preise anzuzeigen, die sowohl Euro als auch Cent enthalten. Übersehe ich etwas Offensichtliches in Bezug auf die Handhabung von Währungen im Rails-Framework?

525voto

molf Punkte 70728

Sie werden wahrscheinlich eine DECIMAL Typ in Ihrer Datenbank. Gehen Sie bei Ihrer Migration etwa so vor:

# 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

In Rails wird die :decimal Typ wird zurückgegeben als BigDecimal was für die Preiskalkulation sehr hilfreich ist.

Wenn Sie darauf bestehen, Ganzzahlen zu verwenden, müssen Sie manuell in und aus BigDecimal s überall, was wahrscheinlich nur lästig werden wird.

Wie von mcl erwähnt, verwenden Sie zum Drucken des Preises:

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

123voto

Ken Mayer Punkte 1762

Hier ist ein feiner, einfacher Ansatz, der folgende Vorteile bietet composed_of (Teil von ActiveRecord, unter Verwendung des ValueObject-Musters) und das Money-Gem

Sie benötigen

  • En Geld-Edelstein (Version 4.1.0)
  • Ein Modell, zum Beispiel Product
  • En integer Spalte in Ihrem Modell (und Ihrer Datenbank), zum Beispiel :price

Schreiben Sie dies in Ihr product.rb Datei:

class Product > ActiveRecord::Base

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

Was du bekommst:

  • Ohne zusätzliche Änderungen werden alle Ihre Formulare Dollar und Cent anzeigen, aber die interne Darstellung ist immer noch nur Cent. Die Formulare akzeptieren Werte wie "$12.034,95" und wandeln sie für Sie um. Es ist nicht nötig, Ihrem Modell zusätzliche Handler oder Attribute hinzuzufügen, oder Helfer in Ihrer Ansicht.
  • product.price = "$12.00" konvertiert automatisch in die Klasse Money
  • product.price.to_s zeigt eine dezimal formatierte Zahl an ("1234.00")
  • product.price.format zeigt eine korrekt formatierte Zeichenfolge für die Währung an
  • Wenn Sie Centbeträge senden müssen (an ein Zahlungsportal, das Pfennige verlangt), product.price.cents.to_s
  • Kostenlose Währungsumrechnung

28voto

alex.zherdev Punkte 23460

Die übliche Praxis für die Handhabung von Währungen ist die Verwendung des Dezimaltyps. Hier ist ein einfaches Beispiel aus "Agile Webentwicklung mit Rails"

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

Damit können Sie Preise von -999.999,99 bis 999.999,99 verarbeiten.
Vielleicht möchten Sie auch eine Validierung in Ihre Artikel aufnehmen, wie

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

um Ihre Werte auf ihre Richtigkeit zu überprüfen.

22voto

Zalom Punkte 653

Nur ein kleines Update und eine Zusammenführung aller Antworten für einige aufstrebende Junioren/Anfänger in der RoR-Entwicklung, die sicherlich hierher kommen werden, um einige Erklärungen zu erhalten.

Arbeiten mit Geld

Utilice :decimal um Geld in der DB zu speichern, wie @molf vorschlug (und was meine Firma als goldenen Standard bei der Arbeit mit Geld verwendet).

# 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

Einige wenige Punkte:

  • :decimal wird verwendet als BigDecimal was eine Menge Probleme löst.

  • precision y scale sollte angepasst werden, je nachdem, was Sie darstellen wollen

    • Wenn Sie mit dem Empfang und Versand von Zahlungen arbeiten, precision: 8 y scale: 2 gibt Ihnen 999,999.99 als den höchsten Betrag, was in 90 % der Fälle in Ordnung ist.

    • Wenn Sie den Wert einer Immobilie oder eines seltenen Autos darstellen müssen, sollten Sie einen höheren precision .

    • Wenn Sie mit Koordinaten (Längen- und Breitengrad) arbeiten, benötigen Sie sicherlich eine höhere scale .

Wie man eine Migration erstellt

Um die Migration mit dem oben genannten Inhalt zu erstellen, führen Sie den Vorgang im Terminal aus:

bin/rails g migration AddPriceToItems price:decimal{8-2}

oder

bin/rails g migration AddPriceToItems 'price:decimal{5,2}'

wie in diesem Artikel erklärt ブログ Posten.

Formatierung der Währung

KISS die zusätzlichen Bibliotheken zu verabschieden und eingebaute Hilfsmittel zu verwenden. verwenden number_to_currency wie von @molf und @facundofarias vorgeschlagen.

Zum Spielen mit number_to_currency Helper in der Rails-Konsole einen Aufruf an die ActiveSupport 's NumberHelper Klasse, um auf den Helfer zugreifen zu können.

Zum Beispiel:

ActiveSupport::NumberHelper.number_to_currency(2_500_000.61, unit: '€', precision: 2, separator: ',', delimiter: '', format: "%n%u")

ergibt die folgende Ausgabe

2500000,61€

Prüfen Sie die anderen options von nummer_zu_währung Helfer.

Wohin damit?

Sie können es in eine Anwendungshilfe einfügen und innerhalb von Ansichten für jeden Betrag verwenden.

module ApplicationHelper    
  def format_currency(amount)
    number_to_currency(amount, unit: '€', precision: 2, separator: ',', delimiter: '', format: "%n%u")
  end
end

Oder Sie können es in den Item Modell als Instanzmethode und rufen Sie es dort auf, wo Sie den Preis formatieren müssen (in Ansichten oder Hilfsfunktionen).

class Item < ActiveRecord::Base
  def format_price
    number_to_currency(price, unit: '€', precision: 2, separator: ',', delimiter: '', format: "%n%u")
  end
end

Und, ein Beispiel, wie ich die number_to_currency innerhalb eines Controler (beachten Sie die negative_format Option, die zur Darstellung von Erstattungen verwendet wird)

def refund_information
  amount_formatted = 
    ActionController::Base.helpers.number_to_currency(@refund.amount, negative_format: '(%u%n)')
  {
    # ...
    amount_formatted: amount_formatted,
    # ...
  }
end

13voto

The Whiz of Oz Punkte 6415

Wenn Sie Postgres verwenden (und da wir uns jetzt im Jahr 2017 befinden), sollten Sie vielleicht deren :money Spaltentyp ausprobieren.

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X