将用户输入转换为整数

时间:2012-03-13 07:27:04

标签: ruby-on-rails ruby

所以我有一个用户可以输入价格的表格。我正在尝试使用before_validation来规范化数据,如果用户放置了$,则剪切$。

before_validation do
 unless self.price.blank? then self.price= self.price.to_s.gsub(/\D/, '').to_i end
end

如果用户输入$ 50这段代码给我0.如果用户输入50 $,这段代码给了我50.我认为因为数据类型是整数,因此rails在我的before_validation之前运行.to_i并且在$之后剪切所有内容。如果数据类型是字符串,则相同的代码可以正常工作。

任何人都有一个让我保留整数数据类型的解决方案吗?

3 个答案:

答案 0 :(得分:21)

一种方法是覆盖设定价格的模型上的机制,如下所示:

def price=(val)
    write_attribute :price, val.to_s.gsub(/\D/, '').to_i
end

因此当你执行@model.price = whatever时,它将转到此方法而不是rails默认属性writer。然后你可以转换数字并使用write_attribute进行实际的写作(你必须这样做,因为标准的price=现在是这个方法!)。

我最喜欢这种方法,但作为参考,在将其分配给模型之前,另一种方法是在控制器中。该参数以字符串形式出现,但模型正在将该字符串转换为数字,因此请直接使用该参数。像这样的东西(只是适应你的控制器代码):

def create
    @model = Model.new(params[:model])
    @model.price = params[:model][:price].gsub(/\D/, '').to_i
    @model.save
end

对于任一解决方案,请删除before_validation

答案 1 :(得分:4)

我会定义一个虚拟属性并在那里进行操作,允许您随意格式化和修改getter和setter:

class Model < ActiveRecord::Base

  def foo_price=(price)
    self.price = price... #=> Mods to string here
  end

  def foo_price
    "$#{price}"
  end

您可能还需要注意:

"$50.00".gsub(/\D/, '').to_i #=> 5000

答案 2 :(得分:0)

我的解决方案 colum price type decimal

t.decimal :price, precision: 12, scale: 6

# app/concern/sanitize_fields.rb
    module SanitizeFields
      extend ActiveSupport::Concern

      def clear_decimal(field)
        return (field.to_s.gsub(/[^\d]/, '').to_d / 100.to_d) unless field.blank?

      end

      def clear_integer(field)
        field.to_s.strip.gsub(/[^\d]/, '') unless field.blank?
      end

      # module ClassMethods
      #   def filter(filtering_params)
      #     results = self.where(nil)
      #     filtering_params.each do |key, value|
      #       results = results.public_send(key, value) if value.present?
      #     end
      #     results
      #   end
      #
      #   #use
      #   #def index
      #   #  @products = Product.filter(params.slice(:status, :location, :starts_with))
      #   #end
      #
      # end

    end

#app/controllers/products_controller.rb

include SanitizeFields

params[:product][:price] = clear_decimal(params[:product][:price])