11

How can I convert user number input from something like 11,5 to 11.5?

I have tried the following as callback:

before_validation :comma_to_delimiter

def comma_to_delimiter
  self.price.to_s.gsub(',', '.').to_f
end

But this doesn't work. I want the user to be able to type in whatever he wants as delimiter - currently, the app throws an error when the user uses a comma instead of a point.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
Dennis Hackethal
  • 13,662
  • 12
  • 66
  • 115
  • Can you explain what type of value self.price is? – Slicedpan Jul 15 '13 at 10:46
  • You want to change this for display in rails app, right? – Mike Szyndel Jul 15 '13 at 10:51
  • No, I don't care about how it is displayed. I have taken of that through locales. Price is a float value that should be stored as float with point as delimiter. The issue is that in Germany, people type in commas rather than points as delimiter. So even if a German person types in "5,5", it should still be stored as "5.5". And if someone types it in correctly in the first place, such as "5.5", nothing has to be changed. Any idea how to do this? – Dennis Hackethal Jul 19 '13 at 22:34

2 Answers2

18

What you're doing may not be the best way, so perhaps someone can answer with a better approach. But to get your line working you need to make it actually persist the change.

self.price.to_s.gsub(',', '.').to_f

Will just return the change, but that doesn't go anywhere in a callback!

self.price = self.price.to_s.gsub(',', '.').to_f
# OR
self.price.to_s.gsub!(',', '.').to_f

Will persist the change within the object.

Matt
  • 13,948
  • 6
  • 44
  • 68
  • The second version will not change the value of self.price – Slicedpan Jul 15 '13 at 10:45
  • I've run the code locally and it most certainly does, have you tried it? Tested and works exactly as described in Rails 3. – Matt Jul 15 '13 at 13:05
  • Yes just realised, if self.price is already a string, then it will change. I was going on the assumption that it was a floating point number (may have misunderstood the question!) – Slicedpan Jul 15 '13 at 13:24
  • 3
    It doesn't save numbers after comma. If `5,75`, saves `5.00`. Or is it just for me? Thanks! – Gediminas Šukys Apr 29 '14 at 08:24
  • same problem as @Gediminas I can't do it in the model. The number is truncated. This is probably due because the number is entered in a form and appears as a string. When it reaches the model the conversion is done like `"5,5".to_f` which truncates the number decimal part. Seems like the hooks (`before_validation`..) all happen after the type of the field is applied. Then I have done the change in controller.. – Maxence Feb 22 '21 at 22:50
14

In some countries comma is the standard currency delimiter and if a user types "19,99" into a form it will be saved as "19.00" unless you handle the delimiter conversion manually. I think the right way to solve this is to write custom attribute setters.

class Product < ActiveRecord::Base
  def price=(val)
    val.sub!(',', '.') if val.is_a?(String)
    self['price'] = val
  end
end
Arctodus
  • 5,743
  • 3
  • 32
  • 44
  • 3
    Would be nice to handle this globally for all float attributes. – Vassilis Dec 16 '14 at 20:36
  • @Vassilis any idea on how to handle that globally? – Benjamin J. Benoudis Mar 13 '19 at 14:39
  • @BenjaminJ.Benoudis I think the most proper way is to use a helper... number_to_currency(1234567890.50, separator: ".", delimiter: ",") – Vassilis Mar 13 '19 at 18:20
  • @BenjaminJ.Benoudis number_to_currency also supports i18n which means that you can setup the format globally in a yml file. See this: https://stackoverflow.com/questions/7237592/number-to-currency-locale-converting – Vassilis Mar 13 '19 at 18:24
  • @Vassilis thanks, but it's not for displaying, but for accepting numbers with comma, and numbers with dot in an input form. I don't find any global easy solution. – Benjamin J. Benoudis Mar 15 '19 at 10:35