2010-05-04 68 views
5

我試圖用一個正則表達式來驗證金額: ^[0-9]+\.[0-9]{2}$浮點精度在Ruby on Rails的模型驗證

這工作得很好,但只要用戶提交表單和0的金額結束(零),紅寶石(或導軌?)將0關閉。 因此500.00會變成500.0,從而導致正則表達式驗證失敗。

有沒有辦法讓ruby/rails保持用戶輸入的格式,而不管尾隨零?

+1

爲什麼你不使用'validates_numericality_of'而不是正則表達式? – 2010-05-04 16:15:01

+0

如何使用'validates_numericality_of'確保500.001會失敗?我只想要,特別是格式化,'[任意0到9位數字]。[2到9位數]' - 因此使用'validates_format_of:amount,:with =>/^ [0-9] + \。[0-9] {2} $ /,:message =>「必須包含美元和美分,並用句點分隔」' – 2010-05-04 16:51:04

回答

8

我假設你的美元金額是十進制類型。因此,在保存到數據庫之前,用戶在字段中輸入的任何值都將從字符串轉換爲適當的類型。驗證適用於已經轉換爲數值類型的值,因此正則表達式在您的情況下並不是真正合適的驗證過濾器。

你有幾個可能的解決這個問題,雖然:

  1. 使用validates_numericality_of。通過這種方式,您完全可以將轉換完成到Rails,並檢查該金額是否在給定範圍內。
  2. 使用validate_each方法並自己對驗證邏輯進行編碼(例如,檢查值是否超過2位十進制數字)。
  3. 驗證attribute before it's been typecasted

這是在用戶 可能會提供一個字符串整數 場 驗證的情況下尤其有用,要在一個錯誤 顯示 初始字符串信息。訪問屬性 通常會將字符串轉換爲 0,這不是您想要的。

所以,你的情況,你應該能夠使用:

validates_format_of :amount_before_type_cast, :with => /^[0-9]+\.[0-9]{2}$/, :message => "must contain dollars and cents, seperated by a period" 

注意,但是,用戶可能會發現它乏味按照你的硬性輸入規則(我真的喜歡能夠例如,輸入500而不是500.00),並且在某些語言環境期間不是小數點分隔符(如果您計劃將應用程序國際化)。

+0

會......':amount_before_type_cast' ...仍導致在數據庫中插入「500.0」?通過驗證是一回事,但管理員仍然可以提取付款記錄,儘管用戶有正確的輸入,他們仍會讀取「500.0」。請參閱答覆Arkku,剛性/嚴格性請求。 – 2010-05-04 17:57:57

+0

您(特別是經理)不應該關心數據庫中的值是如何存儲的。它是一個數字,它應該被存儲爲一個數字(但是,在不同數據庫中有很多數字格式)。只有格式化輸出時,即在數據庫視圖中,才應指定小數位數。 – 2010-05-04 18:03:38

+1

哦,請永遠不要考慮將該數據庫列類型更改爲字符串。 – 2010-05-04 18:05:04

2

一般情況下,如果您希望「記住」浮點值的小數精度,則應該使用十進制類型,而不是二進制浮點數。另一方面,我不確定爲什麼你希望以這種嚴格的方式強制字符串表示法......如何接受任何數字並用例如格式化它number_to_currency

+0

剛性是該應用程序會計部門首席財務官要求的。他實際上希望人們將這種格式完全輸入到表單中。 '@ payment.save'(通過控制器)產生相同的結果之前'@payment.amount = number_to_currency(@ payment.amount,:unit =>'')'...我做錯了嗎? – 2010-05-04 17:41:29

+0

恐怕你是... number_to_currency是爲了表達目的,即在輸出視圖中的金額時使用。順便說一句,如果規則如此僵化,你可能會考慮做一些客戶端驗證,我確信有很多基於jQuery和原型的解決方案。 – 2010-05-04 17:47:14

0

通常用錢最好把它作爲一個整數以仙爲單位(500美分是$ 5.00)。我使用Money gem來解決這個問題。