2012-03-13 42 views
10

Kullanıcıların bir fiyat girebileceği bir form var. Verileri normalleştiren bir before_validation yapmaya çalışıyorum, eğer kullanıcı koyarsa $ değerini keser. kullanıcı girişi 50 $ Bu kod bana 50. verirseKullanıcı girdisini tamsayıya dönüştür

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

kullanıcı girişi $ 50 ise bu kod ben veri türü benim before_validation öncesinde .to_i çalışan ve her şeyi kırpma raylar tamsayı olduğundan düşünmek bana 0'a veriyor $ sonra. Aynı kod, veri türü bir dize ise iyi çalışır.

Tamsayı veri türü tutmama izin verecek bir çözüme sahip olan var mı? Eğer @model.price = whatever yaptığınızda

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

Yani, yerine raylar varsayılan özellik yazar bu yönteme gidecek:

cevap

20

bir yolu bu gibi fiyatı belirler modeline mekanizmasını geçersiz etmektir. Sonra sayıyı çevirebilir ve gerçek yazıyı yapmak için write_attribute'u kullanabilirsiniz (standart price= şimdi bu yöntem olduğu için bunu yapmanız gerekir!).

Bu yöntemi en çok beğeniyorum, ancak başvuru için başka bir yöntem de, modele atamadan önce denetleyicinizde. Parametre bir dize olarak gelir, ancak model bu dizeyi bir sayıya dönüştürür, bu nedenle doğrudan parametreyle çalışın. Böyle bir şey (sadece kontrolör koduna adapte):

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

ya çözümü için, o before_validation kaldırın.

+0

ondalık Benim soluction colum fiyat tipi teşekkür ederiz. Herzaman önce bir validasyon kullanmayı düşündüğüm için oldukça beceriksizdir. Bu kesinlikle daha zarif. –

3

Ben sanal bir özellik tanımlamak ve biçimlendirmek ve istediği anda alıcı ve ayarlayıcı hem değiştirmelerine olanak veren benim manipülasyon yapacağını:

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

Teşekkürler, bunu da deneyeceğim. Başka bir cevap verdim çünkü önce onun yorumunu denedim. Ayrıca, .00 yakalama için teşekkürler, regeximi güncelleyeceğim. – Robert

+0

Np. Bu yaklaşımı önerdim çünkü denetleyicideki ek mantıksal bir hayranı değilim ve ilk bakışta db alanıyla eşleşmesi gereken bir alanı geçersiz kılmadığınız için netlik var ve bir dizenin doğru veri türü olmadığını tahmin ediyorum:) – offbyjuan

+0

Burada formatlama mantığı için ek sunucu sınıfı oluştururdum –

0
:

class Model < ActiveRecord::Base 

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

    def foo_price 
    "$#{price}" 
    end 

Ayrıca dikkat isteyebilirsiniz

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]) 
İlgili konular