2012-03-13 64 views
10

所以我有一个表单,用户可以输入价格。我试图做一个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和裁剪一切$之后。如果数据类型是字符串,这个相同的代码工作正常。

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

回答

20

的一种方法是重写,设置价格,这样对模型的机制:

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

所以当你做@model.price = whatever,它会去这个方法,而不是默认的轨道属性作家。然后你可以转换数字并使用write_attribute来做实际的写作(你必须这样做,因为标准price=现在是这种方法!)。

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

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

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

+0

谢谢。我一直认为使用before_validation非常笨拙。这绝对是更优雅。 – 2012-03-22 08:17:28

3

我会定义一个虚拟属性,做我的操作有让您格式化并随意修改这两个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 
+0

谢谢,我也会试试这个。我给出了其他答案,因为我首先尝试了他的评论。另外,感谢.00捕获,我会更新我的正则表达式。 – Robert 2012-03-13 09:09:40

+0

Np。我建议这种方法,因为我不是在控制器中的额外逻辑的粉丝,并且有清晰度,因为您不覆盖乍一看应匹配db字段的字段,而且我猜字符串不是正确的数据类型: ) – offbyjuan 2012-03-13 16:13:07

+0

我会在这里为格式化逻辑创建额外的演示者类 – 2016-07-23 11:08:22

0

我的答案 colum价格类型十进制

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