Care este cea mai bună metodă de manipulare valută/bani?

Am'm de lucru pe o bază foarte cosul de cumparaturi sistem.

Am o tabela produse care are o coloana "preț" de tip "întreg".

Am'm probleme cu afișarea prețului valoare în vedere pentru prețuri care includ atat de Euro și cenți. Am pierdut ceva evident cât de manipulare valută în Șine cadru este în cauză?

Comentarii la întrebare (1)
Soluția

Te'll, probabil, doriți să utilizați un ZECIMAL tip în baza de date. În migrație, face ceva de genul asta:

# 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

În Șine,: zecimal tip este returnat ca BigDecimal, care este mare pentru calcul pret.

Daca insisti sa folosesti numere întregi, va trebui să manual converti la și de la `BigDecimal e peste tot, care, probabil, va deveni doar o durere.

După cum a subliniat de către mcl, pentru a imprima preț, utilizați:

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

Aici's o amendă, simplă abordare care foloseste composed_of (parte din ActiveRecord, folosind ValueObject model) și Banii gem

Te'll nevoie

  • A Bani gem (versiunea 4.1.0)
  • Un model, de exemplu "Produs"
  • Un "întreg" coloana în modelul dumneavoastră (și date), de exemplu :pret

Scrie asta în produs.rb` fișier:

class Product > ActiveRecord::Base

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

Ce-ai'll obține:

  • Fără modificări suplimentare, toate formele tale vor arăta dolari și cenți, dar reprezentarea internă este încă doar de cenți. Formularele vor accepta valori, cum ar fi "$12,034.95" și de a converti pentru tine. Nu's nu este nevoie pentru a adăuga un plus de stivuitoare sau atribute pentru modelul tau, sau ajutoare din punctul dumneavoastră de vedere.
  • produs.pret = "$12.00"` convertește automat la Banii clasa
  • produs.preț.to_s` afișează o zecimală formatat numărul ("1234.00")
  • produs.preț.format` afișează un string formatat corect pentru moneda
  • Dacă aveți nevoie pentru a trimite cenți (de la un gateway de plată care vrea bani), produs.preț.de cenți.to_s
  • Conversie valutară pentru gratuit
Comentarii (9)

O practică comună pentru manipularea valută este de a folosi tip zecimal. Aici este un exemplu simplu de la "Agile de Dezvoltare Web cu Șine"

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

Acest lucru vă va permite să se ocupe de preturi de la -999,999.99 999,999.99 De asemenea, poate doriți să includă o validare în elemente cum ar fi

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

de bun-simț verifica valorile tale.

Comentarii (2)

Dacă utilizați Postgres (și când ne-am're în 2017 acum), ați putea dori să dea lor `:banii tip coloană o încercați.

add_column :products, :price, :money, default: 0
Comentarii (0)

Folosi de bani șine gem. Frumos se ocupă de bani și monede în modelul dvs. și, de asemenea, are o multime de ajutoare pentru a formata prețurile.

Comentarii (2)

Folosind Virtual Atribute (Link-ul de la revizuită(plătit) Railscast), puteți stoca price_in_cents într-un număr întreg de coloană și se adaugă un atribut virtuală price_in_dollars în model produs ca un getter si 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

Sursa: RailsCasts #016: Virtual Atribute: Virtual atribute sunt un mod curat de a adăuga câmpuri de formular care nu harta direct la baza de date. Aici voi arăta cum să se ocupe de validări, asociații, și mai mult.

Comentarii (1)

Dacă cineva este folosind Continuarea migrației ar arata ceva de genul:

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

cumva Continuare ignoră :precizie și :scara

(Continuare Versiune: sequel (3.39.0, 3.38.0))

Comentarii (0)

Eu sunt, folosind-o pe acest drum:

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

Desigur că moneda simbol, de precizie, format și așa mai departe depinde de fiecare monedă.

Comentarii (0)

Cu siguranta integer.

Și chiar dacă BigDecimal din punct de vedere tehnic există 1.5 va da un pur Plutesc în Ruby.

Comentarii (0)

Doar un pic de actualizare și de coeziune din toate răspunsurile pentru unii aspiranți juniori/incepatori in RoR dezvoltare, care va veni cu siguranță aici pentru niște explicații.

De lucru cu banii

Folosesc:zecimal` pentru a stoca bani în DB, ca @molf sugerat (și de ce compania mea foloseste ca un standard de aur atunci când se lucrează cu bani).

# 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

Câteva puncte:

  • :zecimal va fi folosit caBigDecimal` care rezolvă o mulțime de probleme.

  • "precizie" și "scara" ar trebui să fie ajustate, în funcție de ceea ce te reprezintă

  • Dacă lucrați cu primirea și trimiterea de plăți, precizie: 8 " și " scara: 2999,999.99 ca cea mai mare sumă, care este bine în 90% din cazuri.

  • Dacă trebuie să reprezinte valoarea de la o proprietate sau o masina rara, ar trebui să utilizați un mai mare "precizie".

  • Dacă lucrați cu coordonate (latitudine și longitudine), cu siguranta veti avea nevoie de o mai mare "scara".

Cum de a genera o migrare

Pentru a genera migrarea cu conținutul de mai sus, executați în terminal:

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

sau

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

așa cum sa explicat în acest blog post.

Valută formatare

KISS suplimentar biblioteci la revedere și de a folosi built-in de ajutoare. Folosesc number_to_currency` ca @molf și @facundofarias sugerat.

Pentru a juca cu number_to_currencyhelper în Șine consola, trimite un apel laActiveSupport&#39;sNumberHelper clasa pentru a avea acces la helper.

De exemplu:

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

dă următoarea ieșire

2500000,61€

Verificați alte "opțiuni" de number_to_currency helper.

În cazul în care pentru a pune

Puteți să-l pune într-o cerere de ajutor și să-l utilizați în interiorul punctele de vedere pentru orice sumă.

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

Sau puteți pune-l în "Articol" model ca o metodă de exemplu, și spune în cazul în care aveți nevoie pentru a formata preț (în vedere sau ajutoare).

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

Și, un exemplu cum folosesc number_to_currency în interiorul unui contrroler (observa negative_format opțiune, utilizate pentru a reprezenta restituiri)

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

Puteți trece unele opțiuni să number_to_currency (un standard Șine 4 vizualiza helper):

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

Ca postat de Dylan Tables

Comentarii (0)

Mea de fond al sistemului APIs au folosit de cenți pentru a reprezenta bani, iar eu am't vreau pentru a schimba asta. Nici eu nu am fost de lucru cu sume mari de bani. Așa că am pus asta o metoda de ajutor:

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

Care convertește întreg la un șir cu cel puțin trei cifre (adăugarea de zerouri inițiale, dacă este necesar), apoi introduce o virgulă, înainte de ultimele două cifre nu au folosit niciodată un "Float". De acolo, puteți adăuga orice valută simboluri sunt adecvate pentru cazul dumneavoastră de utilizare.

L's siguranță rapid și murdar, dar, uneori, ca's bine!

Comentarii (1)

Cod simplu pentru Ruby & Șine



OUT PUT => $1,234,567,890.50
Comentarii (0)