Десятичные запятые и запятые при вводе числа в форму Ruby on Rails - PullRequest
14 голосов
/ 01 июля 2011

Какой лучший способ Ruby / Rails разрешить пользователям использовать десятичные или запятые при вводе числа в форму?Другими словами, я хотел бы, чтобы пользователь мог вводить 2 000,99, а не получать 2,00 в моей базе данных.

Есть ли лучший способ для этого?

- Обновление ---

Работает ли gsub с float или bigintegers?Или рельсы автоматически обрезают число при вводе чисел или чисел в форму?Я попытался использовать self.price.gsub (",", ""), но получил "неопределенный метод` gsub 'для 8: Fixnum ", где 8 - это любое число, которое я ввел в форму.

Ответы [ 6 ]

25 голосов
/ 19 февраля 2013

У меня была похожая проблема при попытке использовать локализованный контент внутри форм. Локализация вывода относительно проста с использованием 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.

8 голосов
/ 01 июля 2011

Вот код, который я скопировал у Грега Брауна (автора 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
2 голосов
/ 01 июля 2011

Вы можете попробовать убрать запятые до и после или до сохранения

Упс, вы хотите сделать это в текстовом поле, прежде чем оно будет конвертировано. Вы можете использовать виртуальный атрибут:

def price=(price)
   price = price.gsub(",", "")
   self[:price] = price  # or perhaps price.to_f
end
0 голосов
/ 07 сентября 2016

Посмотрите на камень i18n_alchemy для анализа и локализации даты и номера.

I18nAlchemy стремится обрабатывать анализ даты, времени и числана основе текущего формата локали I18n.Основная идея заключается в том, чтобы иметь ORM, такие как ActiveRecord, чтобы автоматически принимать даты / числа, указанные в текущем формате локали, и возвращать эти значения также локализованными.

0 голосов
/ 20 марта 2012

Вот что-то простое, что гарантирует, что ввод числа читается правильно.Выход будет по-прежнему с точкой вместо запятой.Это не красиво, но, по крайней мере, не критично в некоторых случаях.

Требуется один вызов метода в контроллере, где вы хотите включить разделитель запятых.Может быть, не идеально с точки зрения 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
0 голосов
/ 24 июля 2011

Мне не удалось реализовать более раннее предложение виртуального атрибута 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
...