如何在Rails中validation前从值中删除美元符号?

这是我在我的模型中使用的内容:

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。 有人抓到我做错了吗?

这里有三个问题:

  • 正如Stefan在他的回答中指出的那样,你可能想要删除你的tr! 打电话,虽然它不会影响$的更换。

  • 你正在使用tr! ,并以不正确的方式使用其返回值。 tr! (以及大多数Ruby的!方法变体)如果没有对原始字符串进行任何更改,则返回nil 。 由于nil.to_f0.0 ,这就是你得到它的原因(或者可能没有,见下文)。 你应该改用tr

  • Rails会自动将赋值参数转换为与其关联的数据库列的正确类型,因此即使在validation之前,您的值也会转换为float,并且"$400".to_f0.0 ,这就是您的回调所看到的。 解决方案是覆盖amount_due=而不是使用回调:

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

$之后有一个逗号,所以你要删除$,而不是$

我推荐在javascript中这样做。 Rails似乎对表单助手有些神奇,它会将数字数据库类型支持的字段中的任何非数字值转换为0.0。 愚蠢,我知道。