2012-06-18 150 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(」$,「,'')'。引用文檔:「將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'。但是,如果我創建一個對象並嘗試爲'.amount_due'值賦予相同的'$ 400',我仍然會得到'0.0'。 – richrad

3

$之後有一個逗號,因此您要刪除$,而不是$

+0

好抓!但它仍然吐出0.0。 – richrad

-2

我建議在JavaScript這樣做。 Rails似乎在表單助手中做了一些神奇的事情,它會將由數字數據庫類型支持的字段中的任何非數字值轉換爲0.0。愚蠢的,我知道。

+0

OP是在Rails中尋求解決方案(因爲你可能會看到標籤),所以JS不是他的問題的答案。 –