私は非常に基本的なショッピングカートシステムに取り組んでいます。
タイプitems
がの列を持つテーブルがあります。price
integer
ユーロとセントの両方を含む価格のビューに価格値を表示するのに問題があります。Railsフレームワークでの通貨の処理に関する限り、明らかな何かが欠けていますか?
私は非常に基本的なショッピングカートシステムに取り組んでいます。
タイプitems
がの列を持つテーブルがあります。price
integer
ユーロとセントの両方を含む価格のビューに価格値を表示するのに問題があります。Railsフレームワークでの通貨の処理に関する限り、明らかな何かが欠けていますか?
DECIMAL
おそらく、データベースでタイプを使用したいと思うでしょう。移行では、次のようにします。
# 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
Rails では、:decimal
型は として返されBigDecimal
ます。これは、価格計算に最適です。
どうしても整数を使用する場合は、BigDecimal
あらゆる場所で s との間で手動で変換する必要があり、おそらく面倒になるだけです。
mcl が指摘したように、価格を出力するには、次を使用します。
number_to_currency(price, :unit => "€")
#=> €1,234.01
composed_of
(ValueObject パターンを使用した ActiveRecord の一部) と Money gemを活用する、優れたシンプルなアプローチを次に示します。
あなたは必要になるでしょう
Product
integer
たとえば、モデル (およびデータベース) 内の列:price
これをファイルに書きproduct.rb
ます:
class Product > ActiveRecord::Base
composed_of :price,
:class_name => 'Money',
:mapping => %w(price cents),
:converter => Proc.new { |value| Money.new(value) }
# ...
あなたが得るもの:
product.price = "$12.00"
自動的に Money クラスに変換されますproduct.price.to_s
10 進数形式の数値 ("1234.00") を表示しますproduct.price.format
通貨の適切な形式の文字列を表示しますproduct.price.cents.to_s
通貨を処理するための一般的な方法は、decimal 型を使用することです。「Rails を使用したアジャイル Web 開発」の簡単な例を次に示します。
add_column :products, :price, :decimal, :precision => 8, :scale => 2
これにより、-999,999.99 から 999,999.99 までの価格を処理できるようになり
ます。
def validate
errors.add(:price, "should be at least 0.01") if price.nil? || price < 0.01
end
あなたの価値観を健全にチェックします。
money-rails gemを使用します。モデル内のお金と通貨を適切に処理し、価格をフォーマットするためのヘルパーも多数備えています。
仮想属性 (改訂 (有料) Railscast へのリンク)を使用すると、price_in_cents を整数列に格納し、仮想属性 price_in_dollars をゲッターおよびセッターとして製品モデルに追加できます。
# 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
出典: RailsCasts #016:仮想属性:仮想属性は、データベースに直接マップされないフォーム フィールドを追加するクリーンな方法です。ここでは、検証、関連付けなどを処理する方法を示します。
間違いなく整数。
BigDecimal は技術的には存在し1.5
ますが、Ruby では純粋な Float が得られます。
私はこの方法でそれを使用しています:
number_to_currency(amount, unit: '€', precision: 2, format: "%u %n")
もちろん、通貨記号、精度、形式などは各通貨に依存します。
誰かが Sequel を使用している場合、移行は次のようになります。
add_column :products, :price, "decimal(8,2)"
どういうわけか Sequel は :precision と :scale を無視します
(続編:続編(3.39.0、3.38.0))
私の基盤となる API はすべて、お金を表すためにセントを使用していましたが、それを変更したくありませんでした。また、私は多額のお金を扱っていませんでした。だから私はこれをヘルパーメソッドに入れました:
sprintf("%03d", amount).insert(-3, ".")
これにより、整数が 3 桁以上の文字列に変換され (必要に応じて先行ゼロが追加されます)、最後の 2 桁の前に小数点が挿入されFloat
ます。そこから、ユースケースに適した通貨記号を追加できます。
それは間違いなく速くて汚いですが、時にはそれでいいのです!