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

Jam*_*mes 15 ruby-on-rails decimal biginteger comma ruby-on-rails-3

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

这是最好的做法吗?

- 更新---

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

pan*_*teo 26

尝试在表单中使用本地化内容时,我遇到了类似的问题.使用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
Run Code Online (Sandbox Code Playgroud)

然后让我们添加一个类方法 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
Run Code Online (Sandbox Code Playgroud)

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

class Article < ActiveRecord::Base
  attr_localized :price
end
Run Code Online (Sandbox Code Playgroud)

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

  • 我喜欢意大利里拉到欧元的转换率引用...... :-) (2认同)

Jer*_*ers 8

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

class LineItem < ActiveRecord::Base
  humanized_integer_accessor :quantity
  humanized_money_accessor :price
end
Run Code Online (Sandbox Code Playgroud)

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

= form_for @line_item do |f|
  Price:
  = f.text_field :price_humanized
Run Code Online (Sandbox Code Playgroud)

这是由以下因素驱动的:

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
Run Code Online (Sandbox Code Playgroud)


Dex*_*Dex 2

您可以尝试去掉 before_validation 或 before_save 的逗号

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

def price=(price)
   price = price.gsub(",", "")
   self[:price] = price  # or perhaps price.to_f
end
Run Code Online (Sandbox Code Playgroud)