2012-03-13 41 views
10

Vì vậy, tôi có một biểu mẫu nơi người dùng có thể nhập giá. Tôi đang cố gắng thực hiện một before_validation bình thường hóa dữ liệu, cắt bớt $ nếu người dùng đặt nó.Chuyển đổi đầu vào của Người dùng thành số nguyên

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

Nếu người dùng đóng góp $ 50 Mã này được đem lại cho tôi 0. Nếu người dùng đóng góp 50 $ mã này mang lại cho tôi 50. Tôi nghĩ rằng kể từ khi kiểu dữ liệu là số nguyên ray đang chạy .to_i trước before_validation của tôi và cắt tất cả mọi thứ sau $. Mã này hoạt động tốt nếu kiểu dữ liệu là một chuỗi.

Bất kỳ ai có giải pháp cho phép tôi giữ nguyên kiểu dữ liệu số nguyên?

Trả lời

20

Một cách là để ghi đè lên các cơ chế trên mô hình đó đặt giá, như thế này:

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

Vì vậy, khi bạn làm @model.price = whatever, nó sẽ đi đến phương pháp này thay vì các nhà văn thuộc tính đường ray mặc định. Sau đó, bạn có thể chuyển đổi số và sử dụng write_attribute để thực hiện việc viết thực tế (bạn phải làm theo cách này bởi vì tiêu chuẩn price= bây giờ là phương pháp này!).

Tôi thích phương pháp này tốt nhất, nhưng để tham khảo, cách khác để thực hiện điều đó là trong bộ điều khiển của bạn trước khi gán nó cho mô hình. Tham số xuất hiện dưới dạng một chuỗi, nhưng mô hình đang chuyển đổi chuỗi đó thành một số, vì vậy hãy làm việc trực tiếp với tham số. Một cái gì đó như thế này (chỉ cần thích ứng với nó để mã điều khiển của bạn):

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

Đối với cả hai giải pháp, loại bỏ before_validation.

+0

Cảm ơn bạn. Tôi luôn nghĩ rằng việc sử dụng before_validation là khá vụng về. Điều này chắc chắn là thanh lịch hơn. –

3

tôi sẽ xác định một thuộc tính ảo và làm thao tác của tôi ở đó cho phép bạn định dạng và chỉnh sửa tất cả các phương thức getter và setter theo ý muốn:

class Model < ActiveRecord::Base 

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

    def foo_price 
    "$#{price}" 
    end 

Bạn cũng có thể muốn lưu ý rằng:

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

Cảm ơn, tôi cũng sẽ thử. Tôi đưa ra câu trả lời khác vì trước tiên tôi đã cố gắng bình luận của anh ấy. Ngoài ra, cảm ơn cho .00 bắt, tôi sẽ cập nhật regex của tôi. – Robert

+0

Np. Tôi đề nghị cách tiếp cận đó bởi vì tôi không phải là một fan hâm mộ của logic bổ sung trong bộ điều khiển và có sự rõ ràng vì bạn không ghi đè một trường mà ở cái nhìn đầu tiên phải khớp với trường db và tôi đoán một chuỗi không phải là kiểu dữ liệu chính xác:) – offbyjuan

+0

Tôi sẽ tạo thêm lớp trình bày để định dạng logic tại đây –

0

Cách ly của tôi loại giá colum thập phân

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]) 
Các vấn đề liên quan