Как я могу отформатировать значение, отображаемое в поле редактирования Rails?

Я хотел бы сделать поля формы редактирования максимально удобными для пользователя. Например, для числовых значений я хотел бы, чтобы поле отображалось с запятыми (например, number_with_precision ).

Со стороны дисплея это достаточно просто, но как насчет редактирования? Есть хороший способ сделать это?

Я использую Rails FormBuilder. Проведя расследование, я обнаружил, что он использует InstanceTag, который получает значения для полей, используя <attribute>_value_before_type_cast что означает, что переопределение <attribute> не вызывается.

Ответов (6)

Решение

Лучшее, что я придумал до сих пор, выглядит примерно так:

<%= f.text_field :my_attribute, :value => number_with_precision(f.object.my_attribute) %>

Или my_attribute может вернуть форматированное значение, например:

def my_attribute
  ApplicationController.helpers.number_with_precision(read_attribute(:my_attribute))
end

Но вам все равно придется использовать :value

<%= f.text_field :my_attribute, :value => f.object.my_attribute %>

Похоже, это большая работа.

Если вы хотите, чтобы формат создавался или поддерживался во время редактирования, вам нужно будет добавить Javascript для реализации «масок». Вот демо.

Это было первое попадание в такие результаты .

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

<%= f.text_field :my_number, :value => number_to_human(f.object.my_number, :separator => '', :unit => '', :delimiter => '', :precision => 0) %>

Доступны и другие атрибуты: http://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html

Я предпочитаю ваш первый ответ с форматированием, выполняемым в представлении. Однако, если вы хотите выполнить форматирование в модели, вы можете использовать методы оболочки для получателя и установщика и избежать необходимости полностью использовать параметр: value.

У вас получится что-то вроде этого.

def my_attribute_string
  foo_formatter(myattribute)
end

def my_attribute_string=(s)
  # Parse "s" or do whatever you need to with it, then set your real attribute.
end

<%= f.text_field :my_attribute_string %>

Railscasts покрыли это объектом Time в текстовом поле в эпизоде ​​# 32 . Действительно умная часть этого - то, как они обрабатывают ошибки валидации. Отдельно стоит посмотреть серию.

Я сделал нечто подобное. Мы форматируем время и длину с помощью специального конструктора форм. Он использует существующее текстовое поле, но обертывает его, чтобы значение можно было настроить:

class SuperFormBuilder < ActionView::Helpers::FormBuilder
  include ApplicationHelper
  include FormHelper
  include ActionView::Helpers::TagHelper
  include ActionView::Helpers::FormTagHelper

  def length_field(label,*args)
    scale = 'medium'
    args.each do |v|
      if v.has_key?(:scale)
        scale = v[:scale]
        v.delete(:scale)
      end
    end
  value = length_conversion(@object.send(label.to_sym),scale)
  options = (args.length > 0) ? args.pop : {}
  return has_error(label, text_field_tag(field_name(label),value,*args) + ' ' +  length_unit(scale))
end

private
def field_name(label)
  return @object_name + "[#{label}]"
end

def has_error(label, output)
  return    "<div class='fieldWithErrors'>#{output}</div>" if @object.errors[label]
  return output
end

И используется он так:

<%= form_for( @section, {:action => 'save', :id => @section.id}, :builder => SuperFormBuilder) do |sf| %> 
   <%= sf.length_field :feed_size_min_w, :size => 3, :scale => 'small'  %>
<% end %>

Конечным результатом является значение в соответствующих единицах измерения, основанное на их выборе системы (метрическая, британская) и шкалы IE small = дюймы или миллиметры.

Я в основном скопировал метод text_field из существующего конструктора форм, который использует сам text_field_tag.

Есть два подводных камня: 1) Знание имени поля объекта и того, как получить доступ к объекту, чтобы получить значение, которое вы хотите отформатировать. 2) Получение правильного имени, чтобы при отправке формы она была частью правильного хэша params.

Конструктору форм предоставляется переменная класса @object. Вы можете получить значение поля с помощью метода .send. В моем случае я отправляю метку: feed_size_min_w в @object и получаю обратно его длину. Затем я конвертирую его в желаемый формат и передаю в text_field_tag.

Имя поля является ключом к тому, чтобы оно попало в хеш params, в моем случае params [: section] один. Я создал небольшую вспомогательную функцию field_name, которая позаботится об этом.

Наконец, has_error заключает поле в div с ошибкой, если на этой метке есть ошибки.

Вы можете использовать плагин number_format . Если указать a number_format для существующего числового атрибута внутри вашей модели, атрибут теперь будет отображаться в формате Rails во всех формах и представлениях. Он также будет проанализирован из этого формата (при назначении через формы) перед вставкой в ​​базу данных. (Плагин также создает чисто числовые средства unformatted_<attribute-name> доступа, которые можно продолжать использовать для арифметики или для прямого числового присвоения или извлечения вами для бесшовной интеграции.)

class MyModel < ActiveRecord::Base
  # this model has the balance attribute, which we
  #  want to display using formatting in views,
  #  although it is stored as a numeric in the database
  number_format :balance, 
                :precision => 2,
                :delimiter => ',',
                :strip_trailing_zeros => false

  def increment_balance
    unformatted_balance += 10
  end

Вы также можете объединить вышеперечисленное с решением Javascript, которое может заставить пользователя сохранять десятичную точку и разделители тысяч на месте во время редактирования, хотя на самом деле это не обязательно.