【问题标题】:Convert User input to integer将用户输入转换为整数
【发布时间】:2017-10-22 05:14:42
【问题描述】:

所以我有一个用户可以输入价格的表单。我正在尝试制作一个对数据进行规范化的 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 并在 $ 之后剪切所有内容。如果数据类型是字符串,同样的代码可以正常工作。

谁有让我保留整数数据类型的解决方案?

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

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

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

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

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

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

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

    【讨论】:

    • 谢谢。我一直认为使用 before_validation 非常笨拙。这肯定更优雅。
    【解决方案2】:

    我将定义一个虚拟属性并在那里进行操作,让您可以随意格式化和修改 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
    

    【讨论】:

    • 谢谢,我也试试。我给出了其他答案,因为我先尝试了他的评论。另外,感谢 .00 的捕获,我将更新我的正则表达式。
    • Np。我建议采用这种方法,因为我不喜欢控制器中的附加逻辑,并且由于您没有覆盖乍一看应该与 db 字段匹配的字段并且我猜字符串不是正确的数据类型,因此很清楚: )
    • 我会在这里创建额外的演示者类来格式化逻辑
    【解决方案3】:

    我的解决方案 列价格类型小数

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-15
      • 1970-01-01
      • 2013-09-28
      相关资源
      最近更新 更多