質問

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

integer 型の列 price を持つテーブル items があります。

ユーロとセントの両方を含む価格のビューで価格値を表示するのに問題があります。 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 との間で手動で変換する必要があり、これはおそらく苦痛になります。

mclが指摘したように、価格を印刷するには、次を使用します。

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

他のヒント

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_s は10進形式の数値(" 1234.00")を表示します
  • product.price.format は、通貨に対して適切にフォーマットされた文字列を表示します
  • セント(ペニーが必要な支払いゲートウェイに)を送信する必要がある場合、 product.price.cents.to_s
  • 無料の通貨変換

通貨を処理する一般的な方法は、小数型を使用することです。 「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 を使用します。それはあなたのモデルのお金と通貨をうまく処理し、価格をフォーマットするためのたくさんのヘルパーも持っています。

Postgresを使用している場合(そして2017年になりましたので)、:money 列のタイプを試してください。

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

仮想属性(改訂済み(有料)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で純粋なフロートを提供します。

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

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

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

(Sequelバージョン:sequel(3.39.0、3.38.0))

この方法で使用しています:

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

もちろん、通貨記号、精度、形式などは各通貨によって異なります。

number_to_currency (標準のRails 4ビューヘルパー)にいくつかのオプションを渡すことができます:

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

Dylan Markow

による投稿

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

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

整数を少なくとも3桁の文字列に変換し(必要に応じて先行ゼロを追加)、最後の2桁の前に小数点を挿入します。 Float は使用しません。そこから、ユースケースに適した通貨記号を追加できます。

それは間違いなく迅速で汚れていますが、時にはそれで十分です!

Ruby&amp;のシンプルなコードレール

<%= number_to_currency(1234567890.50) %>

OUT PUT => $1,234,567,890.50

ほんの少しの更新と、RoR開発の意欲的な後輩/初心者向けのすべての回答のまとまり。説明のために必ずここに来ます。

お金を扱う

:decimal を使用して、@ molfが示唆したように、DBにお金を保存します(そして、私の会社がお金を扱う際に黄金の基準として使用するもの)。

# 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

いくつかのポイント:

  • :decimal は、多くの問題を解決する BigDecimal として使用されます。

  • precision および scale は、表現する内容に応じて調整する必要があります

    • 支払いの受け取りと送信を行う場合、 precision:8 および scale:2 により、最高額として 999,999.99 が得られます、90%のケースで問題ありません。

    • プロパティまたは希少車の値を表す必要がある場合は、より高い precision を使用する必要があります。

    • 座標(経度と緯度)を使用する場合は、より高い scale が必要になります。

移行を生成する方法

上記のコンテンツを使用して移行を生成するには、ターミナルで実行します:

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

または

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

こので説明されているとおりブログ投稿。

通貨のフォーマット

KISS 余分なライブラリをさようならし、組み込みのヘルパーを使用します。 @molfおよび@facundofariasが推奨するように、 number_to_currency を使用します。

Railsコンソールで number_to_currency ヘルパーを操作するには、ヘルパーにアクセスするために ActiveSupport NumberHelper クラスに呼び出しを送信します。

例:

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

次の出力を提供します

2500000,61€

number_to_currency の他のオプションを確認します。ヘルパー。

配置場所

アプリケーションヘルパーに配置して、ビュー内で任意の量で使用できます。

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

または、インスタンスメソッドとして Item モデルに配置し、価格をフォーマットする必要がある場所(ビューまたはヘルパー)で呼び出すことができます。

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

そして、コントローラー内で number_to_currency を使用する例(払い戻しを表すために使用される negative_format オプションに注意してください)

def refund_information
  amount_formatted = 
    ActionController::Base.helpers.number_to_currency(@refund.amount, negative_format: '(%u%n)')
  {
    # ...
    amount_formatted: amount_formatted,
    # ...
  }
end
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top