4

这是一个愚蠢的问题,我觉得我一定错过了一些简单的东西。我有一个带有quantity字段的表格。人们在输入数量时不断输入逗号(例如,他们输入12,000表示一万二千)所以我想在将数量(12000在示例中)保存到数据库中的整数列之前去掉逗号。

到目前为止,我已经尝试了两种方法。按照此 SO question中的建议覆盖 setter 方法

  def quantity=(num)
    num.gsub!(',', '') if num.is_a?(String)
    self[:quantity] = num.to_i
  end

这在某种意义上是有效的。如果我输入12,000数量字段并提交表单,我会12000进入数据库。问题是它也绕过了所有quantity验证。例如,我不再可以验证数量值的存在。不是很好。

我还尝试使用验证前回调(而不是覆盖设置器):

  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再一次,不好。

除了在客户端剥离逗号之外,我还能尝试什么?

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

4

3 回答 3

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
于 2012-07-20T19:08:30.943 回答
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 %>

现在验证是否存在 flexible_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
于 2012-07-20T18:56:53.837 回答
0

你会得到数量params[:quanity]。您可以调用一个辅助方法(例如,在您的控制器中定义)来修复字符串,然后将其传递给您的模型。

# 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

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

于 2012-07-20T18:45:44.193 回答