This blog has been archived. Our writing has moved to makandra cards.
The blog of , a Ruby on Rails development team

How to use the comma as decimal separator in ActiveRecord columns and text fields

In countries such as France, Germany and Italy, a comma is used to separate the integral and fractional parts of a float (2.99 becomes 2,99). Still Rails stubbornly uses a dot as the decimal separator when displaying and processing text fields for float values, and there is little in the I18n API to help.

Fortunately we discovered a small hack to make decimal columns of ActiveRecord models accept the comma as the separator. Copy the following as comma_as_decimal_separator.rb into the config/initializers folder of your Rails application:

ActiveRecord::Base.class_eval do

  def convert_number_column_value_with_comma_separator(value)
    value = convert_number_column_value_without_comma_separator(value)
    if value.is_a?(String)
      value = value.gsub(',', '.')
    end
    value
  end

  alias_method_chain :convert_number_column_value, :comma_separator

end

ActiveRecord::ConnectionAdapters::Column.class_eval do

  def type_cast_with_comma_separator(value)
    if type == :decimal && value.is_a?(String)
      value = value.gsub(',', '.')
    end
    type_cast_without_comma_separator(value)
  end

  alias_method_chain :type_cast, :comma_separator

end

Remember to restart your server so the initializer gets loaded.

Now any decimal column will accept a string with a comma as the separator. The string will then automagically be converted to the correct value:

>> article = Article.new
=> #<Article id: nil, price: nil>
>> article.price = "5,2"
=> "5,2"
>> article.price
=> #<BigDecimal:b6e9c4f4,'0.52E1',8(8)>
>> article.selling_price.to_s
=> "5.2"

Note that this only works for columns of type decimal, not float. Always use decimals and try to avoid floats, which have many issues.

Now that your model can deal with commas, you want your text fields to show decimal values with commas, too! Our favorite solution for this is to define an additional form helper number_field which can be used in lieu of text_field to show an input box for decimal values. Copy the following as number_field.rb into the config/initializers folder of your Rails application:

ActionView::Helpers::FormBuilder.class_eval do

  def number_field(field, options = {})
    value = object.send(field).to_s
    value.gsub!('.', ',') unless value.blank?
    options[:value] = value
    options[:class] = "#{options[:class]} number_field"
    text_field(field, options)
  end

end

Remember to restart your server so the initializer gets loaded.

Now you can have your views display a number field with commas:

<% form_for @article do |form| %>
  <%= form.number_field :price %>
  <%= form.submit %>
<% end %>

Because the number_field helper creates a text field with the CSS class number_field, you can style those inputs in your CSS stylesheet. We like to make number fields shorter than regular text fields and right-align its value:

input.number_field {
  width: 100px;
  text-align: right;
}

Was this post helpful to you? Then let us know!

Growing Rails Applications in Practice
Check out our e-book:
Learn to structure large Ruby on Rails codebases with the tools you already know and love.

Recent posts

Our address:
makandra GmbH
Werner-von-Siemens-Str. 6
86159 Augsburg
Germany
Contact us:
+49 821 58866 180
info@makandra.de
Commercial register court:
Augsburg Municipal Court
Register number:
HRB 24202
Sales tax identification number:
DE243555898
Chief executive officers:
Henning Koch
Thomas Eisenbarth