Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I strip dollar signs from a value before validation in Rails?

Here's what I'm using in my model:

before_validation :strip_dollar_sign

validates :amount_due,
          :format => { :with => /^\d+??(?:\.\d{0,2})?$/ }, 
          :numericality => {:greater_than => 0}

private

def strip_dollar_sign
  self.amount_due = self.amount_due.to_s.tr!('$,','').to_f
end

If I run the line from the strip_dollar_sign function by hand in the Rails Console I get exactly what I want (i.e. $400 ends up as 400.0) but when I use the actual form in my app the value always ends up as 0.0. Anybody catch what I'm doing wrong?

like image 685
richrad Avatar asked Jun 18 '12 14:06

richrad


1 Answers

Three problems here:

  • As pointed out by Stefan in his answer, you may want to remove the , in your tr! call, though it won't affect the replacement of a $.

  • You're using tr!, and are using its return value in an incorrect way. tr! (along with most of Ruby's ! method variants) mutates the string in-place and returns nil if no changes were made. Since nil.to_f is 0.0, that's why you're getting that (or maybe not, see below). You should instead use tr.

  • Rails automatically converts assignment arguments to the correct type for the database column associated with it, so even before validation your value is being converted to a float, and "$400".to_f is 0.0, and that's what your callback sees. The solution is to override amount_due= instead of using a callback:

    def amount_due=(value)
      value = value.to_s.tr('$', '').to_f
      write_attribute(:amount_due, value)
    end
    
like image 64
Andrew Marshall Avatar answered Oct 04 '22 00:10

Andrew Marshall