Spec-Zone.ru › Ruby on Rails 8.1

class ActionView::Helpers::FormBuilder

Родительский класс:
Object

Построитель форм Action View

Объект FormBuilder связан с определённым объектом модели и позволяет создавать поля, связанные с этим объектом модели. Объект FormBuilder передаётся в блок при использовании form_with или fields_for. Например:

<%= form_with model: @person do |person_form| %>
  Name: <%= person_form.text_field :name %>
  Admin: <%= person_form.checkbox :admin %>
<% end %>

В приведённом выше блоке объект FormBuilder передаётся как переменная person_form. Это позволяет создавать поля text_field и checkbox, указывая соответствующие методы, которые изменяют базовый шаблон и связывают объект модели @person с формой.

Объект FormBuilder можно считать прокси для методов модуля FormHelper. Однако этот класс позволяет вызывать методы с объектом модели, для которого вы создаёте форму.

Вы можете создавать собственные шаблоны FormBuilder, наследуя этот класс. Например:

class MyFormBuilder < ActionView::Helpers::FormBuilder
  def div_radio_button(method, tag_value, options = {})
    @template.content_tag(:div,
      @template.radio_button(
        @object_name, method, tag_value, objectify_options(options)
      )
    )
  end
end

Приведённый выше код создаёт новый метод div_radio_button, который помещает новую радиокнопку в div. Обратите внимание: если передаются параметры, необходимо вызвать objectify_options, чтобы объект модели был корректно передан методу. Если objectify_options не вызван, новый вспомогательный метод не будет связан с моделью.

Код div_radio_button, приведённый выше, теперь можно использовать следующим образом:

<%= form_with model: @person, :builder => MyFormBuilder do |f| %>
  I am a child: <%= f.div_radio_button(:admin, "child") %>
  I am an adult: <%= f.div_radio_button(:admin, "adult") %>
<% end -%>

Стандартный набор вспомогательных методов для построения форм находится в атрибуте класса field_helpers.

Атрибуты

index [R]
multipart [R]
multipart? [R]
object [RW]
object_name [RW]
options [RW]

Общедоступные методы класса

_to_partial_path () Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1708
def self._to_partial_path
  @_to_partial_path ||= name.demodulize.underscore.sub!(/_builder$/, "")
end
new (object_name, object, template, options) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1720
def initialize(object_name, object, template, options)
  @nested_child_index = {}
  @object_name, @object, @template, @options = object_name, object, template, options
  @default_options = @options ? @options.slice(:index, :namespace, :skip_default_ids, :allow_method_names_outside_object) : {}
  @default_html_options = @default_options.except(:skip_default_ids, :allow_method_names_outside_object)

  convert_to_legacy_options(@options)

  if @object_name&.end_with?("[]")
    if (object ||= @template.instance_variable_get("@#{@object_name[0..-3]}")) && object.respond_to?(:to_param)
      @auto_index = object.to_param
    else
      raise ArgumentError, "object[] naming but object param and @object var don't exist or don't respond to to_param: #{object.inspect}"
    end
  end

  @multipart = nil
  @index = options[:index] || options[:child_index]
end

Открытые методы экземпляра

button (value = nil, options = {}) { |value| ... } Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 2649
def button(value = nil, options = {}, &block)
  case value
  when Hash
    value, options = nil, value
  when Symbol
    value, options = nil, { name: field_name(value), id: field_id(value) }.merge!(options.to_h)
  end
  value ||= submit_default_value

  if block_given?
    value = @template.capture { yield(value) }
  end

  formmethod = options[:formmethod]
  if formmethod.present? && !/post|get/i.match?(formmethod) && !options.key?(:name) && !options.key?(:value)
    options.merge! formmethod: :post, name: "_method", value: formmethod
  end

  @template.button_tag(value, options)
end

Добавляет кнопку отправки для указанной формы. Если значение не задано, проверяется, является ли объект новым ресурсом, чтобы выбрать подходящую подпись:

<%= form_with model: @article do |f| %>
  <%= f.button %>
<% end %>

В примере выше, если @article является новой записью, в качестве подписи кнопки будет использоваться «Create Article»; в противном случае — «Update Article».

Эти подписи можно настроить с помощью I18n под ключом helpers.submit (так же, как и для хелпера submit), а также с помощью %{model} для подстановки перевода:

en:
  helpers:
    submit:
      create: "Create a %{model}"
      update: "Confirm changes to %{model}"

Также выполняется поиск ключа, специфичного для указанного объекта:

en:
  helpers:
    submit:
      article:
        create: "Add %{model}"

Примеры

button("Create article")
# => <button name='button' type='submit'>Create article</button>

button(:draft, value: true)
# => <button id="article_draft" name="article[draft]" value="true" type="submit">Create article</button>

button do
  content_tag(:strong, 'Ask me!')
end
# => <button name='button' type='submit'>
#      <strong>Ask me!</strong>
#    </button>

button do |text|
  content_tag(:strong, text)
end
# => <button name='button' type='submit'>
#      <strong>Create article</strong>
#    </button>

button(:draft, value: true) do
  content_tag(:strong, "Save as draft")
end
# =>  <button id="article_draft" name="article[draft]" value="true" type="submit">
#       <strong>Save as draft</strong>
#     </button>
check_box (method, options = {}, checked_value = "1", unchecked_value = "0")
Псевдоним для: checkbox
checkbox (method, options = {}, checked_value = "1", unchecked_value = "0") Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 2473
def checkbox(method, options = {}, checked_value = "1", unchecked_value = "0")
  @template.checkbox(@object_name, method, objectify_options(options), checked_value, unchecked_value)
end

Возвращает тег флажка, настроенный для доступа к указанному атрибуту (определяемому с помощью method) объекта, назначенного шаблону (определяемого с помощью object). Этот объект должен быть объектом экземпляра (@object), а не локальным объектом. Предполагается, что method возвращает целое число, и если это число больше нуля, флажок установлен. Дополнительные параметры тега input можно передать в виде хэша с помощью options. По умолчанию checked_value равен 1, а unchecked_value равен 0, что удобно для логических значений.

Параметры

  • Можно передать любые стандартные атрибуты HTML для тега, например :class.

  • :checked — true или false принудительно задаёт, установлен флажок или нет.

  • :include_hidden — если задано значение false, описанное ниже вспомогательное скрытое поле создаваться не будет.

Особенность

Согласно спецификации HTML, неустановленные флажки не считаются успешными элементами, поэтому веб-браузеры не отправляют их. К сожалению, это приводит к следующей особенности: если у модели Invoice есть флаг paid, и пользователь снимает флажок в форме редактирования оплаченного счёта, параметр paid не отправляется. Поэтому идиома массового присваивания, например

@invoice.update(params[:invoice])

не обновит этот флаг.

Чтобы избежать этого, хелпер создаёт вспомогательное скрытое поле перед каждым флажком. У скрытого поля такое же имя, а его атрибуты имитируют неустановленный флажок.

Таким образом, клиент отправляет либо только скрытое поле (что означает, что флажок не установлен), либо оба поля. Поскольку спецификация HTML требует отправлять пары ключ/значение в том же порядке, в котором они расположены в форме, а при извлечении параметров из строки запроса выбирается последнее вхождение повторяющегося ключа, для обычных форм это работает.

К сожалению, этот обходной путь не работает, если флажок находится внутри параметра, похожего на массив, как в примере

<%= fields_for "project[invoice_attributes][]", invoice, index: nil do |form| %>
  <%= form.checkbox :paid %>
  ...
<% end %>

поскольку Rails использует именно повторение имён параметров, чтобы различать элементы массива. Для каждого элемента с установленным флажком появляется дополнительный фиктивный элемент, содержащий только этот атрибут со значением «0».

В этом случае предпочтительнее использовать либо FormTagHelper#checkbox_tag, либо хэши вместо массивов.

Примеры

# Let's say that @article.validated? is 1:
checkbox("validated")
# => <input name="article[validated]" type="hidden" value="0" />
#    <input checked="checked" type="checkbox" id="article_validated" name="article[validated]" value="1" />

# Let's say that @puppy.gooddog is "no":
checkbox("gooddog", {}, "yes", "no")
# => <input name="puppy[gooddog]" type="hidden" value="no" />
#    <input type="checkbox" id="puppy_gooddog" name="puppy[gooddog]" value="yes" />

# Let's say that @eula.accepted is "no":
checkbox("accepted", { class: 'eula_check' }, "yes", "no")
# => <input name="eula[accepted]" type="hidden" value="no" />
#    <input type="checkbox" class="eula_check" id="eula_accepted" name="eula[accepted]" value="yes" />
Также имеет псевдоним: check_box
collection_check_boxes (method, collection, value_method, text_method, options = {}, html_options = {}, &block)
Псевдоним для: collection_checkboxes
collection_checkboxes (method, collection, value_method, text_method, options = {}, html_options = {}, &block) Показать исходный код
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 911
def collection_checkboxes(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
  @template.collection_checkboxes(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_html_options.merge(html_options), &block)
end

Оборачивает ActionView::Helpers::FormOptionsHelper#collection_checkboxes для построителей форм:

<%= form_with model: @post do |f| %>
  <%= f.collection_checkboxes :author_ids, Author.all, :id, :name_with_initial %>
  <%= f.submit %>
<% end %>

Подробности см. в документации базового хелпера.

Также имеет псевдоним: collection_check_boxes
collection_radio_buttons (method, collection, value_method, text_method, options = {}, html_options = {}, &block) Показать исходный код
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 924
def collection_radio_buttons(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
  @template.collection_radio_buttons(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_html_options.merge(html_options), &block)
end

Оборачивает ActionView::Helpers::FormOptionsHelper#collection_radio_buttons для построителей форм:

<%= form_with model: @post do |f| %>
  <%= f.collection_radio_buttons :author_id, Author.all, :id, :name_with_initial %>
  <%= f.submit %>
<% end %>

Подробности см. в документации базового хелпера.

collection_select (method, collection, value_method, text_method, options = {}, html_options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 863
def collection_select(method, collection, value_method, text_method, options = {}, html_options = {})
  @template.collection_select(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_html_options.merge(html_options))
end

Оборачивает ActionView::Helpers::FormOptionsHelper#collection_select для построителей форм:

<%= form_with model: @post do |f| %>
  <%= f.collection_select :person_id, Author.all, :id, :name_with_initial, prompt: true %>
  <%= f.submit %>
<% end %>

Подробности см. в документации базового хелпера.

color_field(method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1843
      

Оборачивает ActionView::Helpers::FormHelper#color_field для построителей форм:

<%= form_with model: @user do |f| %>
  <%= f.color_field :favorite_color %>
<% end %>

Подробности см. в документации базового хелпера.

date_field(method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1895
      

Оборачивает ActionView::Helpers::FormHelper#date_field для построителей форм:

<%= form_with model: @user do |f| %>
  <%= f.date_field :born_on %>
<% end %>

Подробности см. в документации базового хелпера.

date_select (method, options = {}, html_options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/date_helper.rb, line 1261
def date_select(method, options = {}, html_options = {})
  @template.date_select(@object_name, method, objectify_options(options), html_options)
end

Оборачивает ActionView::Helpers::DateHelper#date_select для построителей форм:

<%= form_with model: @person do |f| %>
  <%= f.date_select :birth_date %>
  <%= f.submit %>
<% end %>

Подробности см. в документации базового хелпера.

datetime_field(method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1921
      

Оборачивает ActionView::Helpers::FormHelper#datetime_field для построителей форм:

<%= form_with model: @user do |f| %>
  <%= f.datetime_field :graduation_day %>
<% end %>

Подробности см. в документации базового хелпера.

datetime_local_field(method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1934
      

Оборачивает ActionView::Helpers::FormHelper#datetime_local_field для построителей форм:

<%= form_with model: @user do |f| %>
  <%= f.datetime_local_field :graduation_day %>
<% end %>

Подробности см. в документации базового хелпера.

datetime_select (method, options = {}, html_options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/date_helper.rb, line 1285
def datetime_select(method, options = {}, html_options = {})
  @template.datetime_select(@object_name, method, objectify_options(options), html_options)
end

Оборачивает ActionView::Helpers::DateHelper#datetime_select для построителей форм:

<%= form_with model: @person do |f| %>
  <%= f.datetime_select :last_request_at %>
  <%= f.submit %>
<% end %>

Подробности см. в документации базового хелпера.

email_field(method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1986
      

Оборачивает ActionView::Helpers::FormHelper#email_field для построителей форм:

<%= form_with model: @user do |f| %>
  <%= f.email_field :address %>
<% end %>

Подробности см. в документации базового хелпера.

field_id (method, *suffixes, namespace: @options[:namespace], index: @options[:index]) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1777
def field_id(method, *suffixes, namespace: @options[:namespace], index: @options[:index])
  @template.field_id(@object_name, method, *suffixes, namespace: namespace, index: index)
end

Создаёт значение атрибута HTML id для указанного поля

Возвращает значение, сформированное FormBuilder для указанного имени атрибута.

<%= form_with model: @article do |f| %>
  <%= f.label :title %>
  <%= f.text_field :title, aria: { describedby: f.field_id(:title, :error) } %>
  <%= tag.span("is blank", id: f.field_id(:title, :error) %>
<% end %>

В примере выше элемент <input type="text">, созданный вызовом text_field, объявляет атрибут aria-describedby, ссылающийся на элемент <span> и имеющий общий корневой элемент id (в данном случае — article_title).

field_name (method, *methods, multiple: false, index: @options[:index]) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1797
def field_name(method, *methods, multiple: false, index: @options[:index])
  object_name = @options.fetch(:as) { @object_name }

  @template.field_name(object_name, method, *methods, index: index, multiple: multiple)
end

Создаёт значение атрибута HTML name для указанного сочетания имени и поля

Возвращает значение, сформированное FormBuilder для указанного имени атрибута.

<%= form_with model: @article do |f| %>
  <%= f.text_field :title, name: f.field_name(:title, :subtitle) %>
  <%# => <input type="text" name="article[title][subtitle]"> %>
<% end %>

<%= form_with model: @article do |f| %>
  <%= f.text_field :tag, name: f.field_name(:tag, multiple: true) %>
  <%# => <input type="text" name="article[tag][]"> %>
<% end %>
fields (scope = nil, model: nil, **options, &block) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 2327
def fields(scope = nil, model: nil, **options, &block)
  options[:allow_method_names_outside_object] = true
  options[:skip_default_ids] = !FormHelper.form_with_generates_ids

  convert_to_legacy_options(options)

  fields_for(scope || model, model, options, &block)
end

См. документацию по методу-хелперу ActionView::Helpers::FormHelper#fields.

fields_for (record_name, record_object = nil, fields_options = nil, &block) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 2289
def fields_for(record_name, record_object = nil, fields_options = nil, &block)
  fields_options, record_object = record_object, nil if fields_options.nil? && record_object.is_a?(Hash) && record_object.extractable_options?
  fields_options ||= {}
  fields_options[:builder] ||= options[:builder]
  fields_options[:namespace] = options[:namespace]
  fields_options[:parent_builder] = self

  case record_name
  when String, Symbol
    if nested_attributes_association?(record_name)
      return fields_for_with_nested_attributes(record_name, record_object, fields_options, block)
    end
  else
    record_object = @template._object_for_form_builder(record_name)
    record_name   = model_name_from_record_or_class(record_object).param_key
  end

  object_name = @object_name
  index = if options.has_key?(:index)
    options[:index]
  elsif defined?(@auto_index)
    object_name = object_name.to_s.delete_suffix("[]")
    @auto_index
  end

  record_name = if index
    "#{object_name}[#{index}][#{record_name}]"
  elsif record_name.end_with?("[]")
    "#{object_name}[#{record_name[0..-3]}][#{record_object.id}]"
  else
    "#{object_name}[#{record_name}]"
  end
  fields_options[:child_index] = index

  @template.fields_for(record_name, record_object, fields_options, &block)
end

Создаёт область действия для конкретного объекта модели, подобно form_with, но не создаёт сами теги формы. Благодаря этому fields_for подходит для указания дополнительных объектов модели в той же форме.

Хотя назначение и использование fields_for похожи на form_with, сигнатура метода немного отличается. Как и form_with, он передаёт блоку объект FormBuilder, связанный с определённым объектом модели, и внутри блока позволяет вызывать методы построителя для создания полей, связанных с этим объектом модели. Поля могут отражать объект модели двумя способами: способом именования (а значит, и тем, как отправленные значения представлены в хэше params в контроллере) и значениями по умолчанию, отображаемыми при первом показе полей формы. Чтобы задавать эти возможности независимо друг от друга, методу можно отдельно передать имя объекта (в виде символа или строки) и сам объект —

<%= form_with model: @person do |person_form| %>
  First name: <%= person_form.text_field :first_name %>
  Last name : <%= person_form.text_field :last_name %>

  <%= fields_for :permission, @person.permission do |permission_fields| %>
    Admin?  : <%= permission_fields.checkbox :admin %>
  <% end %>

  <%= person_form.submit %>
<% end %>

В этом случае поле-флажок будет представлено тегом HTML input с атрибутом name со значением permission[admin], а отправленное значение появится в контроллере как params[:permission][:admin]. Если @person.permission — существующая запись с атрибутом admin, исходное состояние флажка при первом отображении будет соответствовать значению @person.permission.admin.

Часто это можно упростить, передав в fields_for только имя объекта модели —

<%= fields_for :permission do |permission_fields| %>
  Admin?: <%= permission_fields.checkbox :admin %>
<% end %>

…в этом случае, если :permission также является именем переменной экземпляра @permission, исходное состояние поля ввода будет соответствовать значению атрибута @permission.admin этой переменной.

Также можно передать только сам объект модели (если первый аргумент не является строкой или символом, fields_for поймёт, что имя не указано) —

<%= fields_for @person.permission do |permission_fields| %>
  Admin?: <%= permission_fields.checkbox :admin %>
<% end %>

и fields_for определит требуемое имя поля по классу объекта модели. Например, если @person.permission принадлежит классу Permission, поле по-прежнему будет называться permission[admin].

Примечание: это также работает для методов из FormOptionsHelper и DateHelper, рассчитанных на работу с объектом в качестве основы, например FormOptionsHelper#collection_select и DateHelper#datetime_select.

fields_for старается правильно обрабатывать параметры, но может ошибиться, если переданы параметры и имени, и значения, а переданное значение имеет структуру хэша параметров Hash. Чтобы избежать неоднозначности, явно передайте хэш параметров Hash, даже если он пуст.

<%= form_with model: @person do |person_form| %>
  ...
  <%= fields_for :permission, @person.permission, {} do |permission_fields| %>
    Admin?: <%= checkbox_tag permission_fields.field_name(:admin), @person.permission[:admin] %>
  <% end %>
  ...
<% end %>

Примеры вложенных атрибутов

Если у объекта, принадлежащего текущей области действия, есть метод записи вложенного атрибута для определённого атрибута, fields_for создаст новую область действия для этого атрибута. Это позволяет создавать формы, которые за один раз задают или изменяют атрибуты родительского объекта и его ассоциаций.

Методы записи вложенных атрибутов — это обычные методы-сеттеры, названные по ассоциации. Чаще всего такие методы определяют с помощью accepts_nested_attributes_for в определении модели либо создают метод с подходящим именем. Например, метод записи для ассоциации :address называется address_attributes=.

Будет создан построитель формы для отношения «один к одному» или «один ко многим» — зависит от того, возвращает ли обычный метод чтения один объект или массив объектов.

Один к одному

Рассмотрим класс Person, метод чтения address которого возвращает один объект Address, а также реализует метод записи address_attributes=:

class Person
  def address
    @address
  end

  def address_attributes=(attributes)
    # Process the attributes hash
  end
end

Теперь эту модель можно использовать с вложенным fields_for, например так:

<%= form_with model: @person do |person_form| %>
  ...
  <%= person_form.fields_for :address do |address_fields| %>
    Street  : <%= address_fields.text_field :street %>
    Zip code: <%= address_fields.text_field :zip_code %>
  <% end %>
  ...
<% end %>

Если address уже является ассоциацией Person, можно использовать accepts_nested_attributes_for, чтобы определить метод записи автоматически:

class Person < ActiveRecord::Base
  has_one :address
  accepts_nested_attributes_for :address
end

Чтобы удалить связанную модель через форму, сначала нужно включить эту возможность с помощью параметра :allow_destroy для accepts_nested_attributes_for:

class Person < ActiveRecord::Base
  has_one :address
  accepts_nested_attributes_for :address, allow_destroy: true
end

Теперь, если использовать элемент формы с параметром _destroy, значение которого вычисляется как true, связанная модель будет удалена (например, при значении 1, ‘1’, true или ‘true’):

<%= form_with model: @person do |person_form| %>
  ...
  <%= person_form.fields_for :address do |address_fields| %>
    ...
    Delete: <%= address_fields.checkbox :_destroy %>
  <% end %>
  ...
<% end %>

Один ко многим

Рассмотрим класс Person, метод чтения projects которого возвращает массив экземпляров Project, а также реализует метод записи projects_attributes=:

class Person
  def projects
    [@project1, @project2]
  end

  def projects_attributes=(attributes)
    # Process the attributes hash
  end
end

Обратите внимание, что метод записи projects_attributes= действительно необходим, чтобы fields_for правильно распознал :projects как коллекцию и установил правильные индексы в разметке формы.

Если projects уже является ассоциацией Person, можно использовать accepts_nested_attributes_for, чтобы определить метод записи автоматически:

class Person < ActiveRecord::Base
  has_many :projects
  accepts_nested_attributes_for :projects
end

Теперь эту модель можно использовать с вложенным fields_for. Блок, переданный вложенному вызову fields_for, будет повторён для каждого экземпляра коллекции:

<%= form_with model: @person do |person_form| %>
  ...
  <%= person_form.fields_for :projects do |project_fields| %>
    <% if project_fields.object.active? %>
      Name: <%= project_fields.text_field :name %>
    <% end %>
  <% end %>
  ...
<% end %>

Также можно указать используемый экземпляр:

<%= form_with model: @person do |person_form| %>
  ...
  <% @person.projects.each do |project| %>
    <% if project.active? %>
      <%= person_form.fields_for :projects, project do |project_fields| %>
        Name: <%= project_fields.text_field :name %>
      <% end %>
    <% end %>
  <% end %>
  ...
<% end %>

Или используемую коллекцию:

<%= form_with model: @person do |person_form| %>
  ...
  <%= person_form.fields_for :projects, @active_projects do |project_fields| %>
    Name: <%= project_fields.text_field :name %>
  <% end %>
  ...
<% end %>

Чтобы удалить любую из связанных моделей через форму, сначала нужно включить эту возможность с помощью параметра :allow_destroy для accepts_nested_attributes_for:

class Person < ActiveRecord::Base
  has_many :projects
  accepts_nested_attributes_for :projects, allow_destroy: true
end

Это позволит указать в хэше атрибутов модели для удаления, добавив элемент формы для параметра _destroy со значением, которое вычисляется как true (например, 1, ‘1’, true или ‘true’):

<%= form_with model: @person do |person_form| %>
  ...
  <%= person_form.fields_for :projects do |project_fields| %>
    Delete: <%= project_fields.checkbox :_destroy %>
  <% end %>
  ...
<% end %>

При использовании коллекции может потребоваться узнать индекс каждого объекта в массиве. Для этого в объекте FormBuilder доступен метод index.

<%= form_with model: @person do |person_form| %>
  ...
  <%= person_form.fields_for :projects do |project_fields| %>
    Project #<%= project_fields.index %>
    ...
  <% end %>
  ...
<% end %>

Обратите внимание, что fields_for автоматически создаст скрытое поле для хранения ID записи. В некоторых случаях это скрытое поле не нужно; можно передать include_id: false, чтобы fields_for не создавал его автоматически.

file_field (method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 2557
def file_field(method, options = {})
  self.multipart = true
  @template.file_field(@object_name, method, objectify_options(options))
end

Возвращает тег поля загрузки файла, настроенный для доступа к указанному атрибуту (определяемому с помощью method) объекта, назначенного шаблону (определяемого с помощью object). Дополнительные параметры тега input можно передать в виде хэша с помощью options. Как показано в примере, эти параметры будут добавлены в HTML в качестве атрибутов HTML-элемента.

При использовании этого метода внутри блока form_with кодировка внешней формы устанавливается в multipart/form-data.

Параметры

  • Создаёт стандартные атрибуты HTML для тега.

  • :disabled — если задано значение true, пользователь не сможет использовать это поле ввода.

  • :multiple — если задано значение true, пользователь сможет выбрать несколько файлов *в большинстве актуальных браузеров*.

  • :include_hidden — если заданы multiple: true и include_hidden: true, перед полем будет добавлено поле <input type="hidden"> с пустым значением, чтобы поддержать отправку пустой коллекции файлов. Поскольку include_hidden по умолчанию принимает значение config.active_storage.multiple_file_field_include_hidden, если не указать include_hidden, необходимо передать include_hidden: false, чтобы при передаче multiple: true не отправлялась пустая коллекция файлов.

  • :accept — если указать один или несколько MIME-типов, пользователю будет предложен фильтр при выборе файла. Проверки модели всё равно необходимо настроить.

Примеры

# Let's say that @user has avatar:
file_field(:avatar)
# => <input type="file" id="user_avatar" name="user[avatar]" />

# Let's say that @article has image:
file_field(:image, :multiple => true)
# => <input type="file" id="article_image" name="article[image][]" multiple="multiple" />

# Let's say that @article has attached:
file_field(:attached, accept: 'text/html')
# => <input accept="text/html" type="file" id="article_attached" name="article[attached]" />

# Let's say that @article has image:
file_field(:image, accept: 'image/png,image/gif,image/jpeg')
# => <input type="file" id="article_image" name="article[image]" accept="image/png,image/gif,image/jpeg" />

# Let's say that @attachment has file:
file_field(:file, class: 'file_input')
# => <input type="file" id="attachment_file" name="attachment[file]" class="file_input" />
grouped_collection_select (method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 875
def grouped_collection_select(method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})
  @template.grouped_collection_select(@object_name, method, collection, group_method, group_label_method, option_key_method, option_value_method, objectify_options(options), @default_html_options.merge(html_options))
end

Оборачивает ActionView::Helpers::FormOptionsHelper#grouped_collection_select для построителей форм:

<%= form_with model: @city do |f| %>
  <%= f.grouped_collection_select :country_id, @continents, :countries, :name, :id, :name %>
  <%= f.submit %>
<% end %>

Подробности см. в документации базового хелпера.

hidden_field (method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 2518
def hidden_field(method, options = {})
  @emitted_hidden_id = true if method == :id
  @template.hidden_field(@object_name, method, objectify_options(options))
end

Возвращает тег скрытого поля ввода, настроенный для доступа к указанному атрибуту (определяемому с помощью method) объекта, назначенного шаблону (определяемого с помощью object). Дополнительные параметры тега input можно передать в виде хэша с помощью options. Как показано в примере, эти параметры будут добавлены в HTML в качестве атрибутов HTML-элемента.

Примеры

# Let's say that @signup.pass_confirm returns true:
hidden_field(:pass_confirm)
# => <input type="hidden" id="signup_pass_confirm" name="signup[pass_confirm]" value="true" />

# Let's say that @article.tag_list returns "blog, ruby":
hidden_field(:tag_list)
# => <input type="hidden" id="article_tag_list" name="article[tag_list]" value="blog, ruby" />

# Let's say that @user.token returns "abcde":
hidden_field(:token)
# => <input type="hidden" id="user_token" name="user[token]" value="abcde" />
id () Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1757
def id
  options.dig(:html, :id) || options[:id]
end

Создаёт значение атрибута HTML id.

возвращает атрибут id элемента <form>.

<%= form_with model: @article do |f| %>
  <%# ... %>

  <% content_for :sticky_footer do %>
    <%= form.button(form: f.id) %>
  <% end %>
<% end %>

В примере выше область содержимого :sticky_footer будет находиться за пределами элемента <form>. Объявляя атрибут HTML form, мы сообщаем браузеру, что созданный элемент <button> следует считать кнопкой отправки элемента <form>, независимо от того, где он расположен в DOM.

label (method, text = nil, options = {}, &block) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 2404
def label(method, text = nil, options = {}, &block)
  @template.label(@object_name, method, text, objectify_options(options), &block)
end

Возвращает тег подписи, предназначенный для поля ввода указанного атрибута (определяемого с помощью method) объекта, назначенного шаблону (определяемого с помощью object). Текст подписи по умолчанию совпадает с именем атрибута, если только перевод не найден в текущей локали I18n (с помощью helpers.label.<modelname>.<attribute>) или не задан явно. Дополнительные параметры тега подписи можно передать в виде хэша с помощью options. Как показано в примере, эти параметры будут добавлены в HTML в качестве атрибутов HTML-элемента, за исключением параметра :value, предназначенного для настройки подписей тегов radio_button (его значение используется в идентификаторе тега input).

Примеры

label(:title)
# => <label for="article_title">Title</label>

Можно локализовать подписи на основе имён модели и атрибута. Например, в файле локали (например, en.yml) можно определить следующее:

helpers:
  label:
    article:
      body: "Write your entire text here"

В результате получится:

label(:body)
# => <label for="article_body">Write your entire text here</label>

Локализация также может основываться только на переводе имени атрибута (если используется ActiveRecord):

activerecord:
  attributes:
    article:
      cost: "Total cost"
label(:cost)
# => <label for="article_cost">Total cost</label>

label(:title, "A short title")
# => <label for="article_title">A short title</label>

label(:title, "A short title", class: "title_label")
# => <label for="article_title" class="title_label">A short title</label>

label(:privacy, "Public Article", value: "public")
# => <label for="article_privacy_public">Public Article</label>

label(:cost) do |translation|
  content_tag(:span, translation, class: "cost_label")
end
# => <label for="article_cost"><span class="cost_label">Total cost</span></label>

label(:cost) do |builder|
  content_tag(:span, builder.translation, class: "cost_label")
end
# => <label for="article_cost"><span class="cost_label">Total cost</span></label>

label(:cost) do |builder|
  content_tag(:span, builder.translation, class: [
    "cost_label",
    ("error_label" if builder.object.errors.include?(:cost))
  ])
end
# => <label for="article_cost"><span class="cost_label error_label">Total cost</span></label>

label(:terms) do
  raw('Accept <a href="/terms">Terms</a>.')
end
# => <label for="article_terms">Accept <a href="/terms">Terms</a>.</label>
month_field(method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1947
      

Оборачивает ActionView::Helpers::FormHelper#month_field для построителей форм:

<%= form_with model: @user do |f| %>
  <%= f.month_field :birthday_month %>
<% end %>

Подробности см. в документации базового хелпера.

multipart= (multipart) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1700
def multipart=(multipart)
  @multipart = multipart

  if parent_builder = @options[:parent_builder]
    parent_builder.multipart = multipart
  end
end
number_field(method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1999
      

Оборачивает ActionView::Helpers::FormHelper#number_field для построителей форм:

<%= form_with model: @user do |f| %>
  <%= f.number_field :age %>
<% end %>

Подробности см. в документации базового хелпера.

password_field(method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1817
      

Оборачивает ActionView::Helpers::FormHelper#password_field для построителей форм:

<%= form_with model: @user do |f| %>
  <%= f.password_field :password %>
<% end %>

Подробности см. в документации базового хелпера.

phone_field(method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1882
      

Оборачивает ActionView::Helpers::FormHelper#phone_field для построителей форм:

<%= form_with model: @user do |f| %>
  <%= f.phone_field :phone %>
<% end %>

Подробности см. в документации базового хелпера.

radio_button (method, tag_value, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 2496
def radio_button(method, tag_value, options = {})
  @template.radio_button(@object_name, method, tag_value, objectify_options(options))
end

Возвращает тег переключателя для доступа к указанному атрибуту (определяемому method) объекта, присвоенного шаблону (определяемого object). Если текущее значение method равно tag_value, переключатель будет отмечен.

Чтобы принудительно отметить переключатель, передайте checked: true в хеше options. Там также можно передать параметры HTML.

# Let's say that @article.category returns "rails":
radio_button("category", "rails")
radio_button("category", "java")
# => <input type="radio" id="article_category_rails" name="article[category]" value="rails" checked="checked" />
#    <input type="radio" id="article_category_java" name="article[category]" value="java" />

# Let's say that @user.receive_newsletter returns "no":
radio_button("receive_newsletter", "yes")
radio_button("receive_newsletter", "no")
# => <input type="radio" id="user_receive_newsletter_yes" name="user[receive_newsletter]" value="yes" />
#    <input type="radio" id="user_receive_newsletter_no" name="user[receive_newsletter]" value="no" checked="checked" />
range_field(method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 2012
      

Оборачивает ActionView::Helpers::FormHelper#range_field для построителей форм:

<%= form_with model: @user do |f| %>
  <%= f.range_field :age %>
<% end %>

Подробности см. в документации базового хелпера.

rich_text_area (method, options = {}, &block)
Псевдоним для: rich_textarea
rich_textarea (method, options = {}, &block) Показать исходный код
# File actiontext/app/helpers/action_text/tag_helper.rb, line 114
def rich_textarea(method, options = {}, &block)
  @template.rich_textarea(@object_name, method, objectify_options(options), &block)
end

Оборачивает ActionView::Helpers::FormHelper#rich_textarea для построителей форм:

<%= form_with model: @message do |f| %>
  <%= f.rich_textarea :content %>
<% end %>

Подробности см. в документации базового хелпера.

Также имеет псевдоним: rich_text_area
search_field(method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1856
      

Оборачивает ActionView::Helpers::FormHelper#search_field для построителей форм:

<%= form_with model: @user do |f| %>
  <%= f.search_field :name %>
<% end %>

Подробности см. в документации базового хелпера.

select (method, choices = nil, options = {}, html_options = {}, &block) Показать исходный код
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 851
def select(method, choices = nil, options = {}, html_options = {}, &block)
  @template.select(@object_name, method, choices, objectify_options(options), @default_html_options.merge(html_options), &block)
end

Оборачивает ActionView::Helpers::FormOptionsHelper#select для построителей форм:

<%= form_with model: @post do |f| %>
  <%= f.select :person_id, Person.all.collect { |p| [ p.name, p.id ] }, include_blank: true %>
  <%= f.submit %>
<% end %>

Подробности см. в документации базового хелпера.

submit (value = nil, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 2589
def submit(value = nil, options = {})
  value, options = nil, value if value.is_a?(Hash)
  value ||= submit_default_value
  @template.submit_tag(value, options)
end

Добавляет кнопку отправки для указанной формы. Если значение не задано, проверяется, является ли объект новым ресурсом, чтобы выбрать подходящую подпись:

<%= form_with model: @article do |f| %>
  <%= f.submit %>
<% end %>

В приведенном выше примере, если @article — новая запись, в качестве подписи кнопки отправки будет использовано «Создать статью»; в противном случае — «Обновить статью».

Эти подписи можно настроить с помощью I18n в ключе helpers.submit, используя %{model} для подстановки перевода:

en:
  helpers:
    submit:
      create: "Create a %{model}"
      update: "Confirm changes to %{model}"

Также выполняется поиск ключа, относящегося к указанному объекту:

en:
  helpers:
    submit:
      article:
        create: "Add %{model}"
telephone_field(method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1869
      

Оборачивает ActionView::Helpers::FormHelper#telephone_field для построителей форм:

<%= form_with model: @user do |f| %>
  <%= f.telephone_field :phone %>
<% end %>

Подробности см. в документации базового хелпера.

text_area
Псевдоним для: textarea
text_field(method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1804
      

Оборачивает ActionView::Helpers::FormHelper#text_field для построителей форм:

<%= form_with model: @user do |f| %>
  <%= f.text_field :name %>
<% end %>

Подробности см. в документации базового хелпера.

textarea(method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1830
      

Оборачивает ActionView::Helpers::FormHelper#textarea для построителей форм:

<%= form_with model: @user do |f| %>
  <%= f.textarea :detail %>
<% end %>

Подробности см. в документации базового хелпера.

Также имеет псевдоним: text_area
time_field(method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1908
      

Оборачивает ActionView::Helpers::FormHelper#time_field для построителей форм:

<%= form_with model: @user do |f| %>
  <%= f.time_field :born_at %>
<% end %>

Подробности см. в документации базового хелпера.

time_select (method, options = {}, html_options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/date_helper.rb, line 1273
def time_select(method, options = {}, html_options = {})
  @template.time_select(@object_name, method, objectify_options(options), html_options)
end

Оборачивает ActionView::Helpers::DateHelper#time_select для построителей форм:

<%= form_with model: @race do |f| %>
  <%= f.time_select :average_lap %>
  <%= f.submit %>
<% end %>

Подробности см. в документации базового хелпера.

time_zone_select (method, priority_zones = nil, options = {}, html_options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 887
def time_zone_select(method, priority_zones = nil, options = {}, html_options = {})
  @template.time_zone_select(@object_name, method, priority_zones, objectify_options(options), @default_html_options.merge(html_options))
end

Оборачивает ActionView::Helpers::FormOptionsHelper#time_zone_select для построителей форм:

<%= form_with model: @user do |f| %>
  <%= f.time_zone_select :time_zone, nil, include_blank: true %>
  <%= f.submit %>
<% end %>

Подробности см. в документации базового хелпера.

to_model () Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1716
def to_model
  self
end
to_partial_path () Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1712
def to_partial_path
  self.class._to_partial_path
end
url_field(method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1973
      

Оборачивает ActionView::Helpers::FormHelper#url_field для построителей форм:

<%= form_with model: @user do |f| %>
  <%= f.url_field :homepage %>
<% end %>

Подробности см. в документации базового хелпера.

week_field(method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1960
      

Оборачивает ActionView::Helpers::FormHelper#week_field для построителей форм:

<%= form_with model: @user do |f| %>
  <%= f.week_field :birthday_week %>
<% end %>

Подробности см. в документации базового хелпера.

weekday_select (method, options = {}, html_options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 899
def weekday_select(method, options = {}, html_options = {})
  @template.weekday_select(@object_name, method, objectify_options(options), @default_html_options.merge(html_options))
end

Оборачивает ActionView::Helpers::FormOptionsHelper#weekday_select для построителей форм:

<%= form_with model: @user do |f| %>
  <%= f.weekday_select :weekday, include_blank: true %>
  <%= f.submit %>
<% end %>

Подробности см. в документации базового хелпера.

© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API