341

私は非常に基本的なショッピングカートシステムに取り組んでいます。

タイプitemsがの列を持つテーブルがあります。priceinteger

ユーロとセントの両方を含む価格のビューに価格値を表示するのに問題があります。Railsフレームワークでの通貨の処理に関する限り、明らかな何かが欠けていますか?

4

13 に答える 13

511

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
于 2009-06-19T20:48:57.167 に答える
119

composed_of(ValueObject パターンを使用した ActiveRecord の一部) と Money gemを活用する、優れたシンプルなアプローチを次に示します。

あなたは必要になるでしょう

  • Money gem (バージョン 4.1.0)
  • たとえば、モデル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) }
  # ...

あなたが得るもの:

  • 追加の変更を行わなければ、すべてのフォームにドルとセントが表示されますが、内部表現は依然としてセントです。フォームは「$12,034.95」などの値を受け入れて変換します。モデルにハンドラーや属性を追加したり、ビューにヘルパーを追加したりする必要はありません。
  • product.price = "$12.00"自動的に Money クラスに変換されます
  • product.price.to_s10 進数形式の数値 ("1234.00") を表示します
  • product.price.format通貨の適切な形式の文字列を表示します
  • セントを (ペニーを必要とする支払いゲートウェイに) 送信する必要がある場合は、product.price.cents.to_s
  • 無料で通貨換算
于 2010-10-02T00:15:14.620 に答える
28

通貨を処理するための一般的な方法は、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 

あなたの価値観を健全にチェックします。

于 2009-06-19T20:48:39.260 に答える
9

money-rails gemを使用します。モデル内のお金と通貨を適切に処理し、価格をフォーマットするためのヘルパーも多数備えています。

于 2014-12-30T00:38:26.910 に答える
5

仮想属性 (改訂 (有料) 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:仮想属性:仮想属性は、データベースに直接マップされないフォーム フィールドを追加するクリーンな方法です。ここでは、検証、関連付けなどを処理する方法を示します。

于 2012-09-22T21:08:45.360 に答える
2

間違いなく整数

BigDecimal は技術的には存在し1.5ますが、Ruby では純粋な Float が得られます。

于 2012-09-06T09:45:11.663 に答える
2

私はこの方法でそれを使用しています:

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

もちろん、通貨記号、精度、形式などは各通貨に依存します。

于 2015-02-17T17:34:18.083 に答える
2

誰かが Sequel を使用している場合、移行は次のようになります。

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

どういうわけか Sequel は :precision と :scale を無視します

(続編:続編(3.39.0、3.38.0))

于 2012-10-17T10:35:51.260 に答える
2

私の基盤となる API はすべて、お金を表すためにセントを使用していましたが、それを変更したくありませんでした。また、私は多額のお金を扱っていませんでした。だから私はこれをヘルパーメソッドに入れました:

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

これにより、整数が 3 桁以上の文字列に変換され (必要に応じて先行ゼロが追加されます)、最後の 2 桁の前に小数点が挿入されFloatます。そこから、ユースケースに適した通貨記号を追加できます。

それは間違いなく速くて汚いですが、時にはそれでいいのです!

于 2015-02-10T01:42:20.650 に答える