Ruby on rails 将用户输入转换为整数

Ruby on rails 将用户输入转换为整数,ruby-on-rails,ruby,Ruby On Rails,Ruby,所以我有一个表单,用户可以输入一个价格。我正在尝试进行一次前验证,以规范化数据,如果用户将其放入,则剪裁$ 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\u验证之前,将所有内容剪

所以我有一个表单,用户可以输入一个价格。我正在尝试进行一次前验证,以规范化数据,如果用户将其放入,则剪裁$

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\u验证之前,将所有内容剪裁在$之后。如果数据类型是字符串,同样的代码也可以正常工作


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

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

def price=(val)
    write_attribute :price, val.to_s.gsub(/\D/, '').to_i
end
因此,当您执行
@model.price=which
时,它将转到这个方法,而不是rails的默认属性writer。然后您可以转换数字并使用
write\u属性
进行实际写入(您必须这样做,因为标准的
price=
现在就是这种方法!)

我最喜欢这种方法,但作为参考,另一种方法是在将其分配给模型之前在控制器中进行。参数作为字符串输入,但模型正在将该字符串转换为数字,因此直接使用参数。类似这样的内容(只需根据控制器代码进行调整):


对于任何一种解决方案,在验证之前删除该

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

class Model < ActiveRecord::Base

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

  def foo_price
    "$#{price}"
  end
我的解决方案 列价格类型十进制

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])

谢谢,我也来试试。我给出了另一个答案,因为我先尝试了他的评论。另外,感谢.00捕获,我将更新我的regex.Np。我建议采用这种方法是因为我不喜欢控制器中的其他逻辑,而且很清楚,因为您没有重写一个乍一看应该与db字段匹配的字段,并且我猜字符串不是正确的数据类型:)我将创建其他presenter类来格式化逻辑,谢谢。我一直认为使用before_验证是相当笨拙的。这肯定更优雅。
"$50.00".gsub(/\D/, '').to_i #=> 5000
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])