Ruby on rails 在Rails中进行验证之前,如何从值中剥离美元符号?
以下是我在模型中使用的内容:Ruby on rails 在Rails中进行验证之前,如何从值中剥离美元符号?,ruby-on-rails,ruby,Ruby On Rails,Ruby,以下是我在模型中使用的内容: 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 = se
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 in所指出的,您可能需要删除
tr中的,
代码>调用,但不会影响$
的替换
- 您正在使用
tr代码>,并且以不正确的方式使用其返回值<代码>tr
(以及Ruby的大多数!
方法变体)对字符串进行适当的变异,如果未进行任何更改,则返回nil
。由于nil.to_f
是0.0
,这就是为什么您会得到它(或者可能不是,请参见下文)。您应该改为使用tr
- Rails会自动将赋值参数转换为与之关联的数据库列的正确类型,因此即使在验证之前,您的值也会被转换为浮点值,
“$400”。to_f
是0.0
,这就是回调所看到的。解决方案是覆盖amount\u due=
,而不是使用回调:
def amount_due=(value)
value = value.to_s.tr('$', '').to_f
write_attribute(:amount_due, value)
end
我建议使用javascript执行此操作。Rails似乎在表单帮助器方面发挥了一些作用,它可以将数字数据库类型支持的字段中的任何非数字值转换为0.0。愚蠢,我知道。抓得好!实际上,tr
调用中的逗号很好(如果可能不需要的话):“$500”。tr(“$,”,”)
。引用文档:“返回str副本,其中from_str中的字符替换为To_str中的相应字符。如果To_str比from_str短,则会用其最后一个字符填充,以保持对应关系。”@MichaelKohl Good point,经过编辑以注意它不会影响$
的替换,虽然它可能仍然不需要,因为逗号在某些地区是一个分隔符(加上Stefan的回答中似乎暗示了OP是一个错误)。我认为您在这里了解到了一些东西,但其他一些东西仍然被破坏。如果我进入控制台并运行amount\u due=“$400”
,然后运行amount\u due.to_.tr('$','')。to _f
输出为400.0
。但是,如果我创建一个对象并尝试将相同的$400
分配给.amount\u due
值,我仍然会得到0.0
@richrad啊,我想我知道发生了什么,请查看我更新的答案。就是这样@richrad您应该将该列保存为具有固定精度和比例的Decimal
。货币不应存储为浮点数,而应存储为数据库中的Decimal和ruby中的BigDecimal。浮动可能有舍入错误,这可能会导致意外的结果。OP正在Rails中寻求解决方案(正如您可能看到的标记),因此JS不是他的问题的答案。