在Ruby on Rails表单中输入数字时的小数和逗号

在表单中输入数字时,允许用户使用小数或逗号的最佳Ruby / Rails方法是什么? 换句话说,我希望用户能够在我的数据库中输入2,000.99而不是2.00。

这是最好的做法吗?

– 更新—

gsub可以与浮点数或大整数一起使用吗? 或者,当将浮动或整体输入表格时,轨道会自动切断数字吗? 我尝试使用self.price.gsub(“,”,“”)但得到“未定义的方法`gsub’为8:Fixnum”,其中8是我在表单中输入的任何数字。

尝试在表单中使用本地化内容时遇到了类似的问题。 使用ActionView::Helpers::NumberHelper内置方法本地化输出相对简单,但解析本地化输入ActiveRecord不支持它。

这是我的解决方案,请告诉我,如果我做错了什么。 在我看来,这太简单了,不能成为正确的解决方案。 谢谢! 🙂

首先,让我们为String添加一个方法。

 class String def to_delocalized_decimal delimiter = I18n::t('number.format.delimiter') separator = I18n::t('number.format.separator') self.gsub(/[#{delimiter}#{separator}]/, delimiter => '', separator => '.') end end 

然后让我们为ActiveRecord::Base添加一个类方法

 class ActiveRecord::Base def self.attr_localized(*fields) fields.each do |field| define_method("#{field}=") do |value| self[field] = value.is_a?(String) ? value.to_delocalized_decimal : value end end end end 

最后,让我们声明哪些字段应该有一个本地化的输入。

 class Article < ActiveRecord::Base attr_localized :price end 

现在,在您的表单中,您可以输入“1.936,27”, ActiveRecord不会引发无效号码的错误,因为它变为1936.27。

这是几年前我从Greg Brown( Ruby Best Practices的作者)复制的一些代码。 在您的模型中,您可以确定哪些项目是“人性化的”。

 class LineItem < ActiveRecord::Base humanized_integer_accessor :quantity humanized_money_accessor :price end 

在视图模板中,您需要引用人性化的字段:

 = form_for @line_item do |f| Price: = f.text_field :price_humanized 

这是由以下因素驱动的:

 class ActiveRecord::Base def self.humanized_integer_accessor(*fields) fields.each do |f| define_method("#{f}_humanized") do val = read_attribute(f) val ? val.to_i.with_commas : nil end define_method("#{f}_humanized=") do |e| write_attribute(f,e.to_s.delete(",")) end end end def self.humanized_float_accessor(*fields) fields.each do |f| define_method("#{f}_humanized") do val = read_attribute(f) val ? val.to_f.with_commas : nil end define_method("#{f}_humanized=") do |e| write_attribute(f,e.to_s.delete(",")) end end end def self.humanized_money_accessor(*fields) fields.each do |f| define_method("#{f}_humanized") do val = read_attribute(f) val ? ("$" + val.to_f.with_commas) : nil end define_method("#{f}_humanized=") do |e| write_attribute(f,e.to_s.delete(",$")) end end end end 

您可以尝试删除逗号before_validation或before_save

糟糕,您希望在转换之前在文本字段上执行此操作。 您可以使用虚拟属性:

 def price=(price) price = price.gsub(",", "") self[:price] = price # or perhaps price.to_f end 

看一下i18n_alchemy gem的日期和数字解析和本地化。

I18nAlchemy旨在根据当前的I18n语言环境格式处理日期,时间和数字解析。 主要思想是让ORM(例如ActiveRecord)自动接受以当前语言环境格式给出的日期/数字,并返回这些本地化的值。

我无法实现早期的def price=(price)虚拟属性建议,因为该方法似乎递归调用自身。

我最终从属性哈希中删除了逗号,因为你怀疑ActiveRecord似乎用逗号截断输入并插入到DECIMAL字段中。

在我的模型中:

 before_validation :remove_comma def remove_comma @attributes["current_balance"].gsub!(',', '') # current_balance here corresponds to the text field input in the form view logger.debug "WAS COMMA REMOVED? ==> #{self.current_balance}" end 

这里有一些简单的方法可以确保正确读取数字输入。 输出仍然是一个点而不是逗号。 这不是很美,但至少在某些情况下并不重要。

它需要在控制器中调用一个方法来启用逗号分隔符。 在MVC方面可能并不完美但很简单,例如:

 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 

想法是修改参数字符串,例如:

 class ApplicationController < ActionController::Base def allow_comma(number_string) number_string.sub!(".", "").sub!(",", ".") end end