Price fields and cents separator - ruby-on-rails

In my application I have several price fields. In the model they are of type float and when I want to display them, I use the number_to_currency method provided by NumberHelper and this works fine. However, the input in the form is a problem. Here in The Netherlands, the divider for decimal amounts is a comma, but some people use a dot. Currently, only a decimal amount with a dot gets saved properly. When a decimal is used, only the whole amount gets saved.
So I probably need a before_save sanitizer which replaces a comma with a dot. But I need this for several models. What is the best way to do this?

As the api documentation describes the method number_to_currency has the option :separator you may use.
number_to_currency("1234567890,50", unit: "£", separator: ",", delimiter: "")
Maybe you can set the locale and get the same result.

I have that problem in Germany, too.
I've been using the delocalize gem to perform the "reverse localization", although it still has some problems with Rails 4. (It works, though)
PS: Don't use floating point types for representing currency, you'll get rounding problems. Use BigDecimal instead.

Related

Allow dot and comma in numbers, not only for decimal

I'm having a problem with localization. In Brazil, we use comma as a decimal separator, instead of dot. For example:
500,00
120,21
0,0001
I found the solution to this problem based on this answer: MVC 3 jQuery Validation/globalizing of number/decimal field
But here in Brazil, we also use "." in numbers, like:
100.000.000,00
11.125,23
And one more thing:
10.000 <> 10,000
The first one is ten thousand, and the second is simply ten.
Using the globalization plugin, when the user types the ".", it shows an validation error.
I tried using the data annotation DisplayFormat, but it didn't work as expected...
To "solve" this problems I'm using javascript to manually set and remove the "." from the numbers on the field, but this is very problematic when we need to change anything (and I'm sure this is one of the worst approaches I could use...). Do you guys have any idea of how to proceed in this case?
One more question: I can create a model binder (or modify the existing one) to accept this number format?
I just found this answer.
Fixing binding to decimals
It worked perfectly in my scenario. This guy solved the exactly same problem I was having!
I just had modify a few lines of code, but the most important part was this line:
ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
I modified it to accept nullable values.

How to strip commas from float input?

I have a field -
:Revenue
and it should accept values like 10,000.00, but if I input such value it stores 10 into database instead of 10000.00
What should I do to strip of commas before I save?
I've tried to find a few solutions online but wasn't able to implement them as I found them incomplete. If someone could help me I would really appreciate it.
**The problem now I am facing is that as soon as I enter the value rails converts string in to float value before it can run the gsub function, like if I enter 50,000.00 its converting into float 50.0 before calling the gsub, is there any way to over the to_f method which rails is calling on the string.
Removing commas is pretty simple:
value.gsub(/,/, '').to_f
Keep in mind that European formatting often uses comma as the decimal value separator so your results would be off by a factor of 100 if processing those sorts of numbers.
You can take a String#delete.
"10,000,000.00".delete(',').to_f
# => 10000000.0
I found the solution after looking at few places and combining few solutions, since I had to use gsub before the linking to model has to be done. so I created the method in my controller and called it before create and update action. and wrote the following code in the method
params[:record][:Revenue] = params[:record][:Revenue].gsub(/,/,"")

How do Europeans write a list of numbers with decimals?

As I understand it, Europeans(*) write numbers with a comma for a decimal separator, so one-and-a-quarter is written as 1,25
Europeans also use commas to separate lists, so how do you write a list of decimal numbers? I, as an Englishman, would write one-and-a-quarter, one-and-a-half, one-and-three-quarters like this:
1.25, 1.5, 1.75
How do you do that in Europe?
(Why is this a programming question? Because I'm writing a program that will ask European users for a list of numbers!)
* For the purposes of this question, there are no English-speaking countries in Europe. :-)
I'm European (french), and in almost all programs here we have to use semicolons ';' as a separator, even if the numbers are only integers because the comma doesn't look like a separator for us. In mathematics, semicolons are the only right way here to separate a list of numbers.
The most common example is when we have to enter the page numbers we want to print on a PDF, all programs ask for a semicolon-separated list and I clearly found it intuitive. I think they would have changed it if it was uncomfortable for some.
This varies by culture, and within a culture. The CLDR data contains the “list” element that specifies the list separator character, and it is the semicolon for most cultures, see the chart of number symbols (element “list”). The definition is very implicit though, and there is variation inside locales. Some people regard 1,25, 1,5, 1,75 as acceptable, while others prefer 1,25; 1,5; 1,75. There are also people who seriously think that in a strongly mathematical or numeric context, one should deviate from the locale practices and use the Anglo-Saxon notation with decimal point, hence with comma as separator.
On the practical side, I think it would not be very wrong to use ”;” as number list separator when decimal comma is used, or even when decimal point is used. So you might even consider using ”;” in all locales.
But when it comes to user input, it’s trickier. In principle, you be liberal in what you accept, but since the comma can be meant to be a decimal comma, a thousands separator, or a list item separator, there is such a thing as being too liberal.
If possible, prompt for each number separately, avoiding the separator issue. If this is not possible, the crucial thing is to make it very, very clear to the use which separator is expected. I would go as far as saying that requiring for the semicolon ”;” is the most reliable thing to do.
Why ask about Europeans in general ? I don't think there is one European way of doing so, and if it happens to be the case then it would be sheer luck. Europe is comprised of different cultures and each has its own rules.
You don't mention what platform you are using but you might be able to rely on your plaform to get this information. In the case of .NET, you can get this information through Textinfo.ListSeparator. For example this would give you the French one (result: a semicolon):
string listSeparator = new CultureInfo("fr-FR").TextInfo.ListSeparator;
I don't think there is one way to do it. White space separating the numbers would works just the same, or you could use a semicolon (';') to separate the numbers

Rails 3. Why do my decimal value rows are values such as #<BigDecimal:5003750,'0.1E2',9(18)>>?

Why do my decimal value rows are values such as #> instead of just a regular decimal number?
I have a cost column and I get weird values. Is that ok? If so why?
That's just how Ruby prints out BigDecimal objects by default. Not sure why they chose such an ugly format, but hey - maybe some of the extra information can be useful.
Anyway, you should still be able to use them as you expect - it's just a bit of display weirdness. If you want to print a BigDecimal in a more normal format, call to_s on it first, or use puts, which calls to_s for you.
Hope that helps!
Rails automatically casts the "row" decimal value into the Ruby object that it most resembles. In this case, a BigDecimal.
To print it out in a nice way, you can use "to_s" eg:
puts my_decimal.to_s
=> "3000000000000000000.0"
which should print it out nicer than the ugly class-named version you are seeing now.

floating point precision in ruby on rails model validations

I am trying to validate a dollar amount using a regex:
^[0-9]+\.[0-9]{2}$
This works fine, but whenever a user submits the form and the dollar amount ends in 0(zero), ruby(or rails?) chops the 0 off.
So 500.00 turns into 500.0 thus failing the regex validation.
Is there any way to make ruby/rails keep the format entered by the user, regardless of trailing zeros?
I presume your dollar amount is of decimal type. So, any value user enters in the field is being cast from string to appropriate type before saving to the database. Validation applies to the values already converted to numeric types, so regex is not really a suitable validation filter in your case.
You have couple of possibilities to solve this, though:
Use validates_numericality_of. That way you leave the conversion completely to Rails, and just check whether the amount is within a given range.
Use validate_each method and code your validation logic yourself (e.g. check whether the value has more than 2 decimal digits).
Validate the attribute before it's been typecasted:
This is especially useful in
validation situations where the user
might supply a string for an integer
field and you want to display the
original string back in an error
message. Accessing the attribute
normally would typecast the string to
0, which isn‘t what you want.
So, in your case, you should be able to use:
validates_format_of :amount_before_type_cast, :with => /^[0-9]+\.[0-9]{2}$/, :message => "must contain dollars and cents, seperated by a period"
Note, however, that users might find it tedious to follow your rigid entry rules (I would really prefer being able to type 500 instead 500.00, for example), and that in some locales period is not a decimal separator (if you ever plan to internationalize your app).
In general if you wish to “remember” the decimal precision of a floating point value, you should use a decimal type, not a binary float.
On the other hand, I'm not certain why you would wish to force the string representation in such a strict manner… How about accepting any number and formatting it with e.g. number_to_currency?
Usually with money it's best to store it as an integer in cents (500 cents is $5.00). I use the Money gem to handle this.

Resources