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

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
    

There's a comma after $ so you're removing $, instead of $.