允许在数字字段中使用逗号

时间:2012-07-20 18:34:51

标签: ruby-on-rails ruby ruby-on-rails-3 ruby-on-rails-3.1

这是一个如此愚蠢的问题,我觉得我必须错过一些简单的事情。我有一个带有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。再一次,不好。

除了在客户端删除逗号外,我还能尝试哪些其他内容?

作为最后一点,我知道这实际上是一件愚蠢的事情,因为某些国家以不同的方式使用句号和逗号。无论如何我仍然需要这样做。

3 个答案:

答案 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

所以你在之前对它进行消毒它会转到你的模型,所以它仍然可以对它进行验证。