这是一个如此愚蠢的问题,我觉得我必须错过一些简单的事情。我有一个带有quantity
字段的表单。人们在输入数量时会继续输入逗号(例如,他们键入12,000
表示一万二千),所以我想在保存数量(示例中为12000
)之前删除逗号。数据库中的整数列。
到目前为止,我尝试了两种方法。按照建议的in this SO question
覆盖setter方法 def quantity=(num)
num.gsub!(',', '') if num.is_a?(String)
self[:quantity] = num.to_i
end
这在某种意义上是有效的。如果我在数量字段中输入12,000
并提交表单,我会在数据库中获得12000
。问题是它还绕过了所有quantity
验证。例如,我不再可以验证数量值的存在。这不好。
我还尝试使用before验证回调(而不是覆盖setter):
before_validation :sanitize_quantity
def sanitize_quantity
# Doesn't wok because quantity.to_i already called by this point.
end
这不起作用,因为当数量到达回调方法时,Rails已经在其上调用了to_i
。这意味着12,000
在到达回调时将被截断为12
。再一次,不好。
除了在客户端删除逗号外,我还能尝试哪些其他内容?
作为最后一点,我知道这实际上是一件愚蠢的事情,因为某些国家以不同的方式使用句号和逗号。无论如何我仍然需要这样做。
答案 0 :(得分:10)
如果我正确理解你的问题,那你就是想把字符串强制转换为数字。如果是这样,您可以像这样使用显式转换:
validates :quantity, presence: true, numericality: true
def quantity=(num)
self[:quantity] = num.to_s.scan(/\b-?[\d.]+/).join.to_f
end
请参阅查看其工作原理,您可以在控制台上尝试以下操作。
# String as input.
number = '12,956.05'
number.to_s.scan(/\b-?[\d.]+/).join.to_f
=> 12956.05
# Float as input.
number = 12956.05
number.to_s.scan(/\b-?[\d.]+/).join.to_f
=> 12956.05
# Using an ActiveRecord object.
q = Quantity.new quantity: '12,956.05'
=> #<Quantity id: nil, quantity: 12956.05, created_at: nil, updated_at: nil>
q.save
=> true
答案 1 :(得分:9)
当我正在阅读我的问题时,我确实想到了这一点。
关键是使用虚拟属性。
class Job < ActiveRecord::Base
def flexible_quantity
quantity
end
def flexible_quantity=(quantity)
self.quantity = quantity.gsub(',', '') unless quantity.blank?
end
end
然后在表单中,使用虚拟属性。
<%= f.text_field :flexible_quantity %>
现在验证flex_quantity值的存在。
class Job < ActiveRecord::Base
validates :flexible_quantity, presence: true
# The cool this is that we can leave the numericality validation on the quantity field.
validates :quantity, presence: true, numericality: { only_integer: true }
end
答案 2 :(得分:0)
您将获得params[:quanity]
中的数量。您可以调用辅助方法(例如在控制器中定义)来修复String,然后将其传递给模型。
# YourController.rb
def create # or whatever
quantity = sanitize_quantity(params[:quantity])
YourModel.create!(:quantity => quantity)
end
private
def sanitize_quantity(num)
num.gsub!(',', '') if num.is_a?(String)
return num.to_i
end
所以你在之前对它进行消毒它会转到你的模型,所以它仍然可以对它进行验证。