2012-06-18 3 views
5

は、ここで私は私のモデルに使用しているものです:Railsで検証する前に値からドル記号を削除するにはどうすればよいですか?

before_validation :strip_dollar_sign 

validates :amount_due, 
      :format => { :with => /^\d+??(?:\.\d{0,2})?$/ }, 
      :numericality => {:greater_than => 0} 

private 

def strip_dollar_sign 
    self.amount_due = self.amount_due.to_s.tr!('$,','').to_f 
end 

私は私がしたい正確に何を得るのRailsコンソールに手でstrip_dollar_sign機能から行を実行する場合(つまり、$ 400が400.0として終わる)が、とき私は私のアプリで実際のフォームを使用して値は常に0.0として終了します。誰かが私が間違っていることをキャッチする?

+3

金額は浮動小数点数として保存するのではなく、データベースの小数点以下の桁数とルビのBigDecimalとして保存してください。浮動小数点数には丸め誤差があり、予期しない結果が生じる可能性があります。 – DGM

答えて

14

三つの問題:his answerにステファンが指摘したよう

  • は、あなたはそれが$の交換には影響しませんが、あなたのtr!呼び出しで,を削除することがあります。

  • tr!を使用していますが、戻り値が不正な方法で使用されています。 tr!(ほとんどのRubyの!メソッドの亜種)は、元の文字列に変更が加えられていない場合nilを返します。 nil.to_f0.0なので、それはあなたがそれを取得している理由です(または、以下を参照してください)。代わりにtrを使用してください。

  • Railsは自動的にそれに関連付けられているデータベースのカラムの正しい型に代入引数を変換し、そうであっても検証する前に、値がfloat型に変換され、そして"$400".to_f0.0あり、そしてそれはあなたのコールバックが見ているものです。解決策ではなく、コールバックを使用してのamount_due=を上書きすることです:

    def amount_due=(value) 
        value = value.to_s.tr('$', '').to_f 
        write_attribute(:amount_due, value) 
    end 
    
+1

実際には 'tr'コールのカンマは大丈夫です。' $ 500 ".tr(" $、 "、 '')'。 docsを引用するには:from_strの文字をto_strの対応する文字に置き換えたstrのコピーを返します。to_strがfrom_strより短い場合は、対応を維持するために最後の文字が埋め込まれます。 –

+0

@MichaelKohl良い点は、 '$'の置換には影響しないことに注意してください。ただし、カンマが一部のロケールの区切り文字であるため、依然として望ましくないかもしれません(そしてOPはStefanの答えに暗示しているようですは誤りでした)。 –

+0

あなたはここに何かあると思いますが、それ以外のものはまだ壊れています。私がコンソールにいて、 'amount_due =" $ 400 "'と次に 'amount_due.to_s.tr( '$'、 '').to_f'を実行すると、出力は' 400.0'になります。しかし、私がオブジェクトを作成し、同じ '$ 400 'を' .amount_due'の値に代入しようとすると、私は '0.0'を得ます。 – richrad

3

$の代わりに$,を削除するので、$の後にコンマがあります。ここ

+0

いいキャッチ!しかし、それはまだ0.0を吐き出す。 – richrad

-2

私はJavaScriptでこれを行うことをお勧めします。 Railsはフォームヘルパーでいくつかの魔法をやっているようですが、これは数値データベース型を基にしたフィールドの非数値値を0.0に変換します。愚か、私は知っている。

+0

OPはRailsのソリューションを求めています(タグが表示される可能性があります)ので、JSは彼の質問に対する答えではありません。 –

関連する問題