Ask A Question

Notifications

You’re not receiving notifications from this thread.

Thousand separator and Number formating

Aaron Xavier asked in General

Something as simple as formatting a number in form field with thousand separators and currency symbol is driving me crazy! Something that should be simple to do and more importantly should be part of rails to organically (I mean we in the twenty-first century {does_this_guy_sound_frustred: :true})

I know there are several JS library that I can use for the front-end/form-side. I decided to go with Cleave (https://github.com/nosir/cleave.js) because I didn't wanted a jQuery dependancy.

Form submits: "three_mile_population"=>"422,334" but when rails is updating, it is truncating at the commas

UPDATE "properties" SET "three_mile_population" = $1, "updated_at" = $2 WHERE "properties"."id" = $3  [["three_mile_population", 422], ["updated_at", "2020-08-24 21:12:48.827993"], ["id", 131]]

Yes I can go with a gem like Money. But the idea is I really don't need it because in my case, my values are in Millions and my users don't care for decimal fields for some of these fields (few other fields do have decimal.) I don't feel like loading up my app with another Gem and having to run migration on the database to create additional columns that the gem Money demands.

I tried using https://github.com/rmm5t/strip_attributes to remove any $ commas but that is not working either (not sure why.)

Does anyone else has any better solution for thousand separators. Can StimulusJS cleanup the format before submitting (should that be the route I should take?)

Reply

Rails has several helpers for numbers.

number_with_delimiter(population) # outputs 422,334
number_with_precision
number_to_currency

All part of the NumberHelper: https://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html

Numbers should always be saved without formatting in the database and then you'll use a helper like the above to format it.

Reply

Hi Chris, I know those are great for displaying the numbers in proper format. I was looking for a formatter that works with form field. So when a user is filling up lets say _________________ (3 mile radius population) the form field would automatically thousand separate as he is typing. Which I am using Cleave.js to accomplish that.

"Numbers should always be saved without formatting in the database and then you'll use a helper like the above to format it." I agree and that is the part I am having issues when. When users submit the form that has as number field with comma in them, rails only takes the first few numbers until the comma character. So form submission looks like this:

Processing by Crm::PropertiesController#update as HTML
  Parameters: {"authenticity_token"=>"1s5U4Dtoi6d8ELOdiJ4SOM6N3qn8qgCv9nRfKXWCKcTGOFfHjSb+MgkJ77BPysiy4FOJ6j6AuWWgHSV2cjfN9w==", "property"=>{"property_name"=>"[FILTERED]", "investment_profile_attributes"=>{"deal_stage_id"=>"3", "id"=>"129", "deal_priority_id"=>"3", "three_mile_population"=>"422,334"}, "commit"=>"Update Property", "id"=>"131"}

Then rail updates the record as below:

UPDATE "properties" SET "three_mile_population" = $1, "updated_at" = $2 WHERE "properties"."id" = $3  [["three_mile_population", 422], ["updated_at", "2020-08-24 21:12:48.827993"], ["id", 131]]

Reply

Fake form fields can accomplish what you want.

You can use formatting in the visible form field, but convert to the number in a hidden field. The visible field is not given a name field which means the browser does not submit them to the server.

The hidden field will be what's submitted to the server. You'll use some Javascript to make sure the field continues formatting as the user changes the value.

This is how date selectors that use a Javascript calendar popup work a lot of times. Same for credit card fields. 👍

Make sense?

Reply

@Chris Oliver it absolutely does. I guess I was avoiding going in that route because now I have to create fake input for each of the fields. My app is pretty big and there are like 90 fields that are number fields (some dollar figures, some decimal, some percentile and so on.)

Yes I can absolutely do that, but I was hoping that at the model level, the model would sanitize all the number fields before inserting. In that way, it doesn't matter what the front-end looks like or if someone is injecting dirty fields, the model would take care of just taking the numbers (and in sanitizing I mean at-least be somewhat intelligent that in 21st century a number field might have commas which is still a valid entry and so I will remove the commas or any currency characters before entering into the database.)

I suppose, I will bite the bullet and go in that route.

Reply

You can definitely strip out the commas or periods when the user submits the data if you want by overriding the setter methods. That would let any value be submitted and cleaned up before storing it in the model.

def population=(value)
  super(value.gsub(/[.,]/, '')
end

Something like that should do the trick.

Since it's just formatting, it's usually best if that just happens on the client side. That becomes even more useful in other languages that might use a period as thousands separators instead of commas. They can change their locale and the backend data would not have to change for that. Plus, the backend doesn't have to worry about modifying the formatting, just validating it.

Either way will probably work fine though.

Reply

Also for the frontend, I usually build my own helpers to generate the two fields for me. Saves a lot of time and I can just make a small change to each field with a find & replace to call the new helper instead of having to edit each one.

This would make a great screencast talking about the tradeoffs of both approaches.

Reply

IT ABSOLUTELY will be a great ScreenCast. The whole dealing with numbers from front-end and back-end doesn't either exist, or scattered or I haven't found/be satisfied with it. You should absolutely address this issue because let's face it, number fields are very common in many if not all applications and someone needs to lay the proper foundation on how to address it from a user experience to backend handling. Let me put it this way, if you as a developer are creating forms that has number fields, it should have at-least have thousand separators for better user experience, period. (now I sound like Andrew Mason)

Also, thank you again for the advise, I will take the route of creating a helper method, even though filtering in the model seems like the easy route.

Reply

Another vote for a screencast on input field formatting! I feel like I'm constantly looking for better ways to handle that.

Reply

What about using the rails attirbutes API for this problem: https://api.rubyonrails.org/classes/ActiveRecord/Attributes/ClassMethods.html? As of 2022-10-03 - there is a money example there (just search for: "Creating Custom Types").

Is it any different from submitting a form with a date input, and then magically getting a date time object back when using an active record object?

post_params(:created_at)  # => some string
post.created_at # => DateTime object

Money example:

car.price = "$ 100,000,000" # a string
car.price # => 10e8 # wow: we get it turned into a number, automatically!
Reply

Enclose the thousands separator in double quotes in your custom number format: #","##0","000

I'm unfortunately not aware of a way to include these in a TEXT() function, but it works fine when just using the cell's format.

Edit: Actually, adding an extra double quote to each of them worked. Example:
=TEXT(A1; "#"",""##0"",""000")

Reply
Join the discussion
Create an account Log in

Want to stay up-to-date with Ruby on Rails?

Join 87,265+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.