Decimals and commas when entering a number into a Ruby on Rails form

Viewed 15834

What's the best Ruby/Rails way to allow users to use decimals or commas when entering a number into a form? In other words, I would like the user be able to enter 2,000.99 and not get 2.00 in my database.

Is there a best practice for this?

Does gsub work with floats or bigintegers? Or does rails automatically cut the number off at the , when entering floats or ints into a form? I tried using self.price.gsub(",", "") but get "undefined method `gsub' for 8:Fixnum" where 8 is whatever number I entered in the form.

8 Answers

I have written following code in my project. This solved all of my problems.

config/initializers/decimal_with_comma.rb

# frozen_string_literal: true

module ActiveRecord
  module Type
    class Decimal
      private

      alias_method :cast_value_without_comma_separator, :cast_value

      def cast_value(value)
        value = value.gsub(',', '') if value.is_a?(::String)
        cast_value_without_comma_separator(value)
      end
    end

    class Float
      private

      alias_method :cast_value_without_comma_separator, :cast_value

      def cast_value(value)
        value = value.gsub(',', '') if value.is_a?(::String)
        cast_value_without_comma_separator(value)
      end
    end

    class Integer
      private

      alias_method :cast_value_without_comma_separator, :cast_value

      def cast_value(value)
        value = value.gsub(',', '') if value.is_a?(::String)
        cast_value_without_comma_separator(value)
      end
    end
  end
end

module ActiveModel
  module Validations
    class NumericalityValidator
      protected

        def parse_raw_value_as_a_number(raw_value)
          raw_value = raw_value.gsub(',', '') if raw_value.is_a?(::String)
          Kernel.Float(raw_value) if raw_value !~ /\A0[xX]/
        end
    end
  end
end

Here's something simple that makes sure that number input is read correctly. The output will still be with a point instead of a comma. That's not beautiful, but at least not critical in some cases.

It requires one method call in the controller where you want to enable the comma delimiter. Maybe not perfect in terms of MVC but pretty simple, e.g.:

class ProductsController < ApplicationController

  def create
    # correct the comma separation:
    allow_comma(params[:product][:gross_price])

    @product = Product.new(params[:product])

    if @product.save
      redirect_to @product, :notice => 'Product was successfully created.'
    else
      render :action => "new"
    end
  end

end

The idea is to modify the parameter string, e.g.:

class ApplicationController < ActionController::Base

  def allow_comma(number_string)
    number_string.sub!(".", "").sub!(",", ".")
  end

end

You can try this:

def price=(val)
  val = val.gsub(',', '')
  super
end
Related