Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling international currency input in Ruby on Rails

I have an application that handles currency inputs. However, if you're in the US, you might enter a number as 12,345.67; in France, it might be 12.345,67.

Is there an easy way, in Rails, to adapt the currency entry to a locale?

Note that I'm not looking for display of the currency (ala number_to_currency), I'm looking to deal with someone typing in a currency string, and converting it into a decimal.

like image 271
Tim Sullivan Avatar asked Nov 03 '09 18:11

Tim Sullivan


2 Answers

You could give this a shot:

   def string_to_float(string)

      string.gsub!(/[^\d.,]/,'')          # Replace all Currency Symbols, Letters and -- from the string

      if string =~ /^.*[\.,]\d{1}$/       # If string ends in a single digit (e.g. ,2)
        string = string + "0"             # make it ,20 in order for the result to be in "cents"
      end

      unless string =~ /^.*[\.,]\d{2}$/   # If does not end in ,00 / .00 then
        string = string + "00"            # add trailing 00 to turn it into cents
      end

      string.gsub!(/[\.,]/,'')            # Replace all (.) and (,) so the string result becomes in "cents"  
      string.to_f / 100                   # Let to_float do the rest
   end

And the test Cases:

describe Currency do
  it "should mix and match" do
    Currency.string_to_float("$ 1,000.50").should eql(1000.50)
    Currency.string_to_float("€ 1.000,50").should eql(1000.50)
    Currency.string_to_float("€ 1.000,--").should eql(1000.to_f)
    Currency.string_to_float("$ 1,000.--").should eql(1000.to_f)    
  end     

  it "should strip the € sign" do
    Currency.string_to_float("€1").should eql(1.to_f)
  end

  it "should strip the $ sign" do
    Currency.string_to_float("$1").should eql(1.to_f)
  end

  it "should strip letter characters" do
    Currency.string_to_float("a123bc2").should eql(1232.to_f)
  end

  it "should strip - and --" do
    Currency.string_to_float("100,-").should eql(100.to_f)
    Currency.string_to_float("100,--").should eql(100.to_f)
  end

  it "should convert the , as delimitor to a ." do
    Currency.string_to_float("100,10").should eql(100.10)
  end

  it "should convert ignore , and . as separators" do
    Currency.string_to_float("1.000,10").should eql(1000.10)
    Currency.string_to_float("1,000.10").should eql(1000.10)
  end

  it "should be generous if you make a type in the last '0' digit" do
    Currency.string_to_float("123,2").should eql(123.2)
  end
like image 128
Wilco Avatar answered Sep 27 '22 22:09

Wilco


We wrote this:

class String
  def safe_parse
    self.gsub(I18n.t("number.currency.format.unit"), '').gsub(I18n.t("number.currency.format.delimiter"), '').gsub(I18n.t("number.currency.format.separator"), '.').to_f
  end
end

Of course, you will have to set the I18n.locale before using this. And it currently only converts the string to a float for the locale that was set. (In our case, if the user is on the french site, we expect the currency amount text to only have symbols and formatting pertaining to the french locale).

like image 29
Vijay Aravamudhan Avatar answered Sep 27 '22 23:09

Vijay Aravamudhan