2012-03-13 4 views
10

그래서 사용자가 가격을 입력 할 수있는 양식이 있습니다. 나는 데이터를 정규화하는 before_validation을 만들려고하는데, 사용자가 넣으면 $가 클리핑됩니다. 사용자 입력은 50 $이 코드는 나에게 (50)를 제공하는 경우사용자 입력을 정수로 변환

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

사용자 입력 $ 50 경우이 코드는 내가 데이터 유형 내 before_validation 이전 .to_i 실행하고 모든 클리핑되는 레일의 정수이기 때문에 생각 날 0을주고있다 $ 후. 데이터 형식이 문자열 인 경우이 동일한 코드가 제대로 작동합니다.

누구나 정수 데이터 유형을 유지할 수있는 해결책이 있습니까? 당신이 @model.price = whatever을 수행 할 때

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

그래서, 대신 레일의 기본 속성 작가의이 방법으로 이동합니다

답변

20

한 가지 방법은 다음과 같이 가격을 설정하는 모델에 대한 메커니즘을 무시하는 것입니다. 그렇다면 숫자를 변환하고 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을 사용하는 것이 꽤 어색하다고 생각했다. 이것은 확실히 더 우아합니다. –

3

나는 가상 속성을 정의하고 포맷하고 마음대로 getter와 setter를 모두 수정할 수 있습니다 내 조작을 할 것입니다 :

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

고마워, 나는 이것도 시도해 볼게. 나는 그의 코멘트를 먼저 시험했기 때문에 다른 대답을했다. 또한 .00 캐치를 주셔서 감사 드리며, 정규 표현식을 업데이트하겠습니다. – Robert

+0

Np. 나는 컨트롤러에서 추가적인 로직 팬이 아니며 언뜻보기에는 db 필드와 일치해야하는 필드를 오버라이드하지 않으므로 명확성이 있기 때문에이 접근법을 제안했으며 문자열이 올바른 데이터 유형이 아닌 것으로 추측합니다.) – offbyjuan

+0

여기에 논리 서식 지정을위한 추가 발표자 클래스를 만들겠습니다. –

0
:

class Model < ActiveRecord::Base 

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

    def foo_price 
    "$#{price}" 
    end 

당신은 또한주의 할 수도 있습니다

내 soluch 소수 가격 형식 십진

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