Spec-Zone.ru › Ruby on Rails 8.1

модуль ActionView::Helpers::FormHelper

Подключённые модули:
ActionView::Helpers::FormTagHelper, ActionView::Helpers::UrlHelper, ActionView::RecordIdentifier

Помощники форм Action View

Помощники форм призваны значительно упростить работу с ресурсами по сравнению с использованием обычного HTML.

Как правило, форма для создания или обновления ресурса отражает его идентичность несколькими способами: (i) URL-адрес, на который отправляется форма (атрибут action элемента form), должен приводить к маршрутизации запроса к соответствующему действию контроллера (с соответствующим параметром :id для существующего ресурса), (ii) поля ввода должны иметь такие имена, чтобы в контроллере их значения попадали в соответствующие места хеша params, и (iii) для существующей записи при первоначальном отображении формы поля ввода, соответствующие атрибутам ресурса, должны показывать текущие значения этих атрибутов.

В Rails это обычно реализуется созданием формы с помощью form_with или form_for и ряда связанных методов-помощников. Эти методы создают подходящий тег form и передают блоку объект построителя формы, которому известна модель, с которой связана форма. Поля ввода создаются вызовом методов, определённых в построителе формы, поэтому они могут формировать подходящие имена и значения по умолчанию, соответствующие атрибутам модели, а также удобные идентификаторы и т. д. Соглашения, применяемые при формировании имён полей, позволяют контроллерам без каких-либо дополнительных усилий получать данные формы в удобной структурированной форме в params.

Например, чтобы создать нового человека, обычно в действии PeopleController#new, @person, создают новый экземпляр Person, а в шаблоне представления передают этот объект в form_with или form_for:

<%= form_with model: @person do |f| %>
  <%= f.label :first_name %>:
  <%= f.text_field :first_name %><br />

  <%= f.label :last_name %>:
  <%= f.text_field :last_name %><br />

  <%= f.submit %>
<% end %>

Сгенерированный HTML будет выглядеть так (без учёта форматирования):

<form action="/people" class="new_person" id="new_person" method="post">
  <input name="authenticity_token" type="hidden" value="NrOp5bsjoLRuK8IW5+dQEYjKGUJDe7TQoZVvq95Wteg=" />
  <label for="person_first_name">First name</label>:
  <input id="person_first_name" name="person[first_name]" type="text" /><br />

  <label for="person_last_name">Last name</label>:
  <input id="person_last_name" name="person[last_name]" type="text" /><br />

  <input name="commit" type="submit" value="Create Person" />
</form>

Как видите, HTML в нескольких местах отражает сведения о ресурсе, например путь, по которому следует отправить форму, или имена полей ввода.

В частности, благодаря соглашениям, применяемым при формировании имён полей, контроллер получает вложенный хеш params[:person] с атрибутами человека, заданными в форме. Этот хеш можно сразу передать в Person.new:

@person = Person.new(params[:person])
if @person.save
  # success
else
  # error handling
end

Интересно, что тот же код представления из предыдущего примера можно использовать для редактирования человека. Если @person — существующая запись с именем «John Smith» и идентификатором 256, приведённый выше код без изменений выдаст:

<form action="/people/256" class="edit_person" id="edit_person_256" method="post">
  <input name="_method" type="hidden" value="patch" />
  <input name="authenticity_token" type="hidden" value="NrOp5bsjoLRuK8IW5+dQEYjKGUJDe7TQoZVvq95Wteg=" />
  <label for="person_first_name">First name</label>:
  <input id="person_first_name" name="person[first_name]" type="text" value="John" /><br />

  <label for="person_last_name">Last name</label>:
  <input id="person_last_name" name="person[last_name]" type="text" value="Smith" /><br />

  <input name="commit" type="submit" value="Update Person" />
</form>

Обратите внимание: конечная точка, значения по умолчанию и подпись кнопки отправки адаптированы для @person. Это происходит потому, что задействованные помощники знают, является ли ресурс новой записью, и формируют HTML соответствующим образом.

Контроллер снова получит данные формы в params[:person], готовые к передаче в Person#update:

if @person.update(params[:person])
  # success
else
  # error handling
end

Именно так обычно работают с ресурсами.

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

check_box (object_name, method, options = {}, checked_value = "1", unchecked_value = "0")
Псевдоним для: checkbox
checkbox (object_name, method, options = {}, checked_value = "1", unchecked_value = "0") Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1346
def checkbox(object_name, method, options = {}, checked_value = "1", unchecked_value = "0")
  Tags::CheckBox.new(object_name, method, self, checked_value, unchecked_value, options).render
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("article", "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("puppy", "gooddog", {}, "yes", "no")
# => <input name="puppy[gooddog]" type="hidden" value="no" />
#    <input type="checkbox" id="puppy_gooddog" name="puppy[gooddog]" value="yes" />

checkbox("eula", "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
color_field (object_name, method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1377
def color_field(object_name, method, options = {})
  Tags::ColorField.new(object_name, method, self, options).render
end

Возвращает text_field типа «color».

color_field("car", "color")
# => <input id="car_color" name="car[color]" type="color" value="#000000" />
date_field (object_name, method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1441
def date_field(object_name, method, options = {})
  Tags::DateField.new(object_name, method, self, options).render
end

Возвращает text_field типа «date».

date_field("user", "born_on")
# => <input id="user_born_on" name="user[born_on]" type="date" />

Значение по умолчанию формируется попыткой вызвать strftime с форматом «%Y-%m-%d» для значения объекта. Благодаря этому для экземпляров DateTime и ActiveSupport::TimeWithZone всё работает ожидаемым образом. Это значение можно переопределить, явно передав параметр «value», например:

@user.born_on = Date.new(1984, 1, 27)
date_field("user", "born_on", value: "1984-05-12")
# => <input id="user_born_on" name="user[born_on]" type="date" value="1984-05-12" />

Значения атрибутов «min» и «max» можно задать, передав в хеше параметров экземпляры Date или Time.

date_field("user", "born_on", min: Date.today)
# => <input id="user_born_on" name="user[born_on]" type="date" min="2014-05-20" />

Кроме того, для значений «min» и «max» можно передать String в формате даты ISO8601.

date_field("user", "born_on", min: "2014-05-20")
# => <input id="user_born_on" name="user[born_on]" type="date" min="2014-05-20" />
datetime_field (object_name, method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1514
def datetime_field(object_name, method, options = {})
  Tags::DatetimeLocalField.new(object_name, method, self, options).render
end

Возвращает text_field типа «datetime-local».

datetime_field("user", "born_on")
# => <input id="user_born_on" name="user[born_on]" type="datetime-local" />

Значение по умолчанию формируется попыткой вызвать strftime с форматом «%Y-%m-%dT%T» для значения объекта. Благодаря этому для экземпляров DateTime и ActiveSupport::TimeWithZone всё работает ожидаемым образом.

@user.born_on = Date.new(1984, 1, 12)
datetime_field("user", "born_on")
# => <input id="user_born_on" name="user[born_on]" type="datetime-local" value="1984-01-12T00:00:00" />

Значения атрибутов «min» и «max» можно задать, передав в хеше параметров экземпляры Date или Time.

datetime_field("user", "born_on", min: Date.today)
# => <input id="user_born_on" name="user[born_on]" type="datetime-local" min="2014-05-20T00:00:00.000" />

Кроме того, для значений «min» и «max» можно передать String в формате даты и времени ISO8601.

datetime_field("user", "born_on", min: "2014-05-20T00:00:00")
# => <input id="user_born_on" name="user[born_on]" type="datetime-local" min="2014-05-20T00:00:00.000" />

По умолчанию переданные значения даты и времени форматируются с указанием секунд. Чтобы отображать только дату, час и минуты, передайте include_seconds: false.

@user.born_on = Time.current
datetime_field("user", "born_on", include_seconds: false)
# => <input id="user_born_on" name="user[born_on]" type="datetime-local" value="2014-05-20T14:35" />
Также имеет псевдоним: datetime_local_field
datetime_local_field (object_name, method, options = {})
Псевдоним для: datetime_field
email_field (object_name, method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1568
def email_field(object_name, method, options = {})
  Tags::EmailField.new(object_name, method, self, options).render
end

Возвращает text_field типа «email».

email_field("user", "address")
# => <input id="user_address" name="user[address]" type="email" />
fields (scope = nil, model: nil, **options, &block) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1079
def fields(scope = nil, model: nil, **options, &block)
  options = { allow_method_names_outside_object: true, skip_default_ids: !form_with_generates_ids }.merge!(options)

  if model
    model   = _object_for_form_builder(model)
    scope ||= model_name_from_record_or_class(model).param_key
  end

  builder = instantiate_builder(scope, model, options)
  capture(builder, &block)
end

Связывает поля ввода с явно заданной областью или моделью. Аналогично тому, как form_with работает с :scope или :model, но без вывода тегов формы.

# Using a scope prefixes the input field names:
<%= fields :comment do |fields| %>
  <%= fields.text_field :body %>
<% end %>
# => <input type="text" name="comment[body]">

# Using a model infers the scope and assigns field values:
<%= fields model: Comment.new(body: "full bodied") do |fields| %>
  <%= fields.text_field :body %>
<% end %>
# => <input type="text" name="comment[body]" value="full bodied">

# Using `fields` with `form_with`:
<%= form_with model: @article do |form| %>
  <%= form.text_field :title %>

  <%= form.fields :comment do |fields| %>
    <%= fields.text_field :body %>
  <% end %>
<% end %>

Как и в случае с form_with, блоку передаётся экземпляр FormBuilder, связанный с областью или моделью, поэтому имена всех созданных полей получают префикс из переданной области или области, определённой по :model.

Сочетание с другими помощниками форм

Хотя form_with использует объект FormBuilder, его можно сочетать с автономными методами FormHelper и методами FormTagHelper:

<%= fields model: @comment do |fields| %>
  <%= fields.text_field :body %>

  <%= textarea :commenter, :biography %>
  <%= checkbox_tag "comment[all_caps]", "1", @comment.commenter.hulk_mode? %>
<% end %>

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

fields_for (record_name, record_object = nil, options = {}, &block) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1028
def fields_for(record_name, record_object = nil, options = {}, &block)
  options = { model: record_object, allow_method_names_outside_object: false, skip_default_ids: false }.merge!(options)

  fields(record_name, **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 создаст новую область для этого атрибута. Это позволяет создавать формы, которые за один раз задают или изменяют атрибуты родительского объекта и его ассоциаций.

Методы записи вложенных атрибутов — это обычные методы-сеттеры, названные в соответствии с ассоциацией. Чаще всего такие методы определяются либо с помощью 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 автоматически создаёт скрытое поле для хранения идентификатора записи, если она поддерживает persisted?. В некоторых случаях это скрытое поле не требуется; передайте include_id: false, чтобы запретить fields_for автоматически его выводить.

file_field (object_name, method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1247
def file_field(object_name, method, options = {})
  options = { include_hidden: multiple_file_field_include_hidden }.merge!(options)

  Tags::FileField.new(object_name, method, self, convert_direct_upload_option_to_url(options.dup)).render
end

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

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

Параметры

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

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

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

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

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

Примеры

file_field(:user, :avatar)
# => <input type="file" id="user_avatar" name="user[avatar]" />

file_field(:article, :image, multiple: true)
# => <input type="file" id="article_image" name="article[image][]" multiple="multiple" />

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

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

file_field(:attachment, :file, class: 'file_input')
# => <input type="file" id="attachment_file" name="attachment[file]" class="file_input" />
form_for (record, options = {}, &block) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 435
def form_for(record, options = {}, &block)
  raise ArgumentError, "Missing block" unless block_given?

  case record
  when String, Symbol
    model       = false
    object_name = record
  else
    model       = record
    object      = _object_for_form_builder(record)
    raise ArgumentError, "First argument in form cannot contain nil or be empty" unless object
    object_name = options[:as] || model_name_from_record_or_class(object).param_key
    apply_form_for_options!(object, options)
  end

  remote = options.delete(:remote)

  if remote && !embed_authenticity_token_in_remote_forms && options[:authenticity_token].blank?
    options[:authenticity_token] = false
  end

  options[:model]                               = model
  options[:scope]                               = object_name
  options[:local]                               = !remote
  options[:skip_default_ids]                    = false
  options[:allow_method_names_outside_object]   = options.fetch(:allow_method_names_outside_object, false)

  form_with(**options, &block)
end

Создает форму, которая позволяет пользователю создавать или обновлять атрибуты определенного объекта модели.

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

<%= form_for :person do |f| %>
  First name: <%= f.text_field :first_name %><br />
  Last name : <%= f.text_field :last_name %><br />
  Biography : <%= f.textarea :biography %><br />
  Admin?    : <%= f.checkbox :admin %><br />
  <%= f.submit %>
<% end %>

Переменная f, переданная в блок, является объектом FormBuilder, который содержит сведения об объекте модели, представленном :person, переданном в form_for. Методы, определенные в FormBuilder, используются для создания полей, связанных с этой моделью. Так, например,

<%= f.text_field :first_name %>

будет преобразовано в

<%= text_field :person, :first_name %>

в результате чего будет создан HTML-тег <input>, атрибут name которого равен person[first_name]. Это означает, что после отправки формы введенное пользователем значение будет доступно в контроллере как params[:person][:first_name].

Для полей, созданных таким способом с помощью FormBuilder, если :person также является именем переменной экземпляра @person, значением поля по умолчанию при первоначальном отображении формы (например, при редактировании существующей записи) будет значение соответствующего атрибута @person.

Крайний правый аргумент form_for — это необязательный хеш параметров:

  • :url — URL, на который отправляется форма. Его можно указать так же, как значения, передаваемые в url_for или link_to. Например, можно напрямую использовать именованный маршрут. Если модель представлена строкой или символом, как в примере выше, и параметр :url не указан, по умолчанию форма отправляется на текущий URL. (Ниже мы опишем альтернативный вариант использования form_for, ориентированный на ресурсы, при котором URL не нужно указывать явно.)

  • :namespace — пространство имен для формы, обеспечивающее уникальность атрибутов id элементов формы. В сгенерированном HTML к атрибуту пространства имен будет добавлено подчеркивание как префикс для id.

  • :method — метод, используемый при отправке формы; обычно это «get» или «post». Если используется «patch», «put», «delete» или другой глагол, добавляется скрытое поле с именем _method, имитирующее этот глагол посредством post.

  • :authenticity_token — токен подлинности, используемый в форме. Используйте его, только если необходимо передать собственную строку токена подлинности или вообще не добавлять поле authenticity_token (передав false). Для удаленных форм встроенный токен подлинности можно опустить, задав config.action_view.embed_authenticity_token_in_remote_forms = false. Это полезно при фрагментном кэшировании формы. Удаленные формы получают токен подлинности из тега meta, поэтому встраивать его не нужно, если только вы не поддерживаете браузеры без JavaScript.

  • :remote — если задано значение true, драйверы ненавязчивого JavaScript смогут управлять поведением отправки формы.

  • :enforce_utf8 — если задано значение false, скрытое поле с именем utf8 не выводится.

  • :html — необязательные HTML-атрибуты для тега формы.

Обратите также внимание: form_for не создает изолированную область видимости. По-прежнему можно использовать как отдельные методы FormHelper, так и методы из FormTagHelper. Например:

<%= form_for :person do |f| %>
  First name: <%= f.text_field :first_name %>
  Last name : <%= f.text_field :last_name %>
  Biography : <%= textarea :person, :biography %>
  Admin?    : <%= checkbox_tag "person[admin]", "1", @person.company.admin? %>
  <%= f.submit %>
<% end %>

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

form_for с объектом модели

В приведенных выше примерах объект, который нужно создать или отредактировать, был представлен символом, переданным в form_for; мы также отметили, что вместо него можно использовать строку. Однако в form_for можно передать и сам объект модели. Например, если @article — существующая запись, которую вы хотите отредактировать, форму можно создать следующим образом:

<%= form_for @article do |f| %>
  ...
<% end %>

Это работает почти так же, как описано выше, за несколькими небольшими исключениями. Во-первых, префикс, используемый для именования элементов ввода в форме (а значит, и ключ, обозначающий их в хеше params), определяется на основе класса объекта; например, params[:article], если класс объекта — Article. Однако это можно переопределить с помощью параметра :as, например:

<%= form_for(@person, as: :client) do |f| %>
  ...
<% end %>

в результате чего получится params[:client].

Во-вторых, значения полей при первоначальном отображении формы берутся из атрибутов объекта, переданного в form_for, независимо от того, является ли объект переменнойю экземпляра. Например, если у нас есть локальная переменная article, представляющая существующую запись,

<%= form_for article do |f| %>
  ...
<% end %>

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

Стиль, ориентированный на ресурсы

В только что приведенных примерах, хотя это и не указано явно, нам все еще нужно использовать параметр :url, чтобы задать адрес отправки формы. Однако можно еще больше упростить запись, если переданная в form_for запись является ресурсом, то есть соответствует набору маршрутов RESTful, например определенных с помощью метода resources в config/routes.rb. В этом случае Rails просто определит соответствующий URL по самой записи. Например,

<%= form_for @article do |f| %>
  ...
<% end %>

эквивалентно примерно следующему:

<%= form_for @article, as: :article, url: article_path(@article), method: :patch, html: { class: "edit_article", id: "edit_article_45" } do |f| %>
  ...
<% end %>

А для новой записи

<%= form_for(Article.new) do |f| %>
  ...
<% end %>

эквивалентно примерно следующему:

<%= form_for @article, as: :article, url: articles_path, html: { class: "new_article", id: "new_article" } do |f| %>
  ...
<% end %>

Однако отдельные соглашения по-прежнему можно переопределить, например:

<%= form_for(@article, url: super_articles_path) do |f| %>
  ...
<% end %>

Атрибут action можно опустить, передав url: false:

<%= form_for(@article, url: false) do |f| %>
  ...
<% end %>

Также можно задать формат ответа, например:

<%= form_for(@article, format: :json) do |f| %>
  ...
<% end %>

Для маршрутов с пространством имен, например admin_article_url:

<%= form_for([:admin, @article]) do |f| %>
 ...
<% end %>

Если у ресурса определены ассоциации, можно, например, добавить комментарии к документу, при условии что маршруты настроены правильно:

<%= form_for([@document, @comment]) do |f| %>
 ...
<% end %>

Здесь @document = Document.find(params[:id]) и @comment = Comment.new.

Задание метода

Можно заставить форму использовать полный набор HTTP-глаголов, задав

method: (:get|:post|:patch|:put|:delete)

в хеше параметров. Если используется глагол, отличный от GET или POST, которые изначально поддерживаются HTML-формами, для формы будет задан метод POST, а скрытое поле с именем _method будет содержать предназначенный для сервера глагол.

Ненавязчивый JavaScript

Указание:

remote: true

в хеше параметров создает форму, поведение которой могут изменять драйверы ненавязчивого JavaScript. Для принимающей стороны отправка формы будет работать так же, как обычная отправка (все элементы будут доступны в params).

Пример:

<%= form_for(@article, remote: true) do |f| %>
  ...
<% end %>

Для этого будет сгенерирован следующий HTML:

<form action='http://www.example.com' method='post' data-remote='true'>
  <input name='_method' type='hidden' value='patch' />
  ...
</form>

Задание параметров HTML

Атрибуты data можно задать напрямую, передав хеш data, но все остальные параметры HTML необходимо обернуть в ключ HTML. Пример:

<%= form_for(@article, data: { behavior: "autosave" }, html: { name: "go" }) do |f| %>
  ...
<% end %>

Для этого будет сгенерирован следующий HTML:

<form action='http://www.example.com' method='post' data-behavior='autosave' name='go'>
  <input name='_method' type='hidden' value='patch' />
  ...
</form>

Удаление скрытых идентификаторов модели

Метод form_for автоматически добавляет идентификатор модели в форму в виде скрытого поля. Это позволяет сохранять связь между данными формы и соответствующей моделью. Некоторые ORM-системы не используют идентификаторы для вложенных моделей, поэтому в таких случаях может потребоваться отключить скрытое поле с идентификатором.

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

Пример:

<%= form_for(@article) do |f| %>
  <%= f.fields_for(:comments, include_id: false) do |cf| %>
    ...
  <% end %>
<% end %>

Настраиваемые построители форм

Формы также можно создавать с помощью настраиваемого класса FormBuilder. Создайте подкласс FormBuilder, переопределите или добавьте вспомогательные методы, а затем используйте собственный построитель. Например, предположим, что вы создали вспомогательный метод для автоматического добавления меток к полям формы.

<%= form_for @person, url: { action: "create" }, builder: LabellingFormBuilder do |f| %>
  <%= f.text_field :first_name %>
  <%= f.text_field :last_name %>
  <%= f.textarea :biography %>
  <%= f.checkbox :admin %>
  <%= f.submit %>
<% end %>

В этом случае, если использовать следующее:

<%= render f %>

Будет отображен шаблон people/_labelling_form, а локальная переменная, ссылающаяся на построитель формы, будет называться labelling_form.

Настраиваемый класс FormBuilder автоматически объединяется с параметрами вложенного вызова fields_for, если только он не задан явно.

Во многих случаях приведенный выше код удобно обернуть в другой вспомогательный метод. Например, можно сделать следующее:

def labelled_form_for(record_or_name_or_array, *args, &block)
  options = args.extract_options!
  form_for(record_or_name_or_array, *(args << options.merge(builder: LabellingFormBuilder)), &block)
end

Если вам не нужно связывать форму с экземпляром модели, обратитесь к FormTagHelper#form_tag.

Форма для внешних ресурсов

При создании форм для внешних ресурсов иногда требуется задать токен подлинности или отобразить форму без него. Например, при отправке данных на платежный шлюз могут быть ограничены количество и типы полей.

Чтобы задать токен подлинности, необходимо передать параметр :authenticity_token

<%= form_for @invoice, url: external_url, authenticity_token: 'external_token' do |f| %>
  ...
<% end %>

Если вы вообще не хотите отображать поле токена подлинности, просто передайте false:

<%= form_for @invoice, url: external_url, authenticity_token: false do |f| %>
  ...
<% end %>
form_with (model: false, scope: nil, url: nil, format: nil, **options, &block) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 755
def form_with(model: false, scope: nil, url: nil, format: nil, **options, &block)
  raise ArgumentError, "Passed nil to the :model argument, expect an object or false" if model.nil?

  options = { allow_method_names_outside_object: true, skip_default_ids: !form_with_generates_ids }.merge!(options)

  if model
    if url != false
      url ||= if format.nil?
        polymorphic_path(model, {})
      else
        polymorphic_path(model, format: format)
      end
    end

    model   = convert_to_model(_object_for_form_builder(model))
    scope ||= model_name_from_record_or_class(model).param_key
  end

  if block_given?
    builder = instantiate_builder(scope, model, options)
    output  = capture(builder, &block)
    options[:multipart] ||= builder.multipart?

    html_options = html_options_for_form_with(url, model, **options)
    form_tag_with_body(html_options, output)
  else
    html_options = html_options_for_form_with(url, model, **options)
    form_tag_html(html_options)
  end
end

Создает тег формы на основе сочетания URL, областей видимости или моделей.

# Using just a URL:
<%= form_with url: articles_path do |form| %>
  <%= form.text_field :title %>
<% end %>
# =>
<form action="/articles" method="post">
  <input type="text" name="title" />
</form>

# With an intentionally empty URL:
<%= form_with url: false do |form| %>
  <%= form.text_field :title %>
<% end %>
# =>
<form method="post">
  <input type="text" name="title" />
</form>

# Adding a scope prefixes the input field names:
<%= form_with scope: :article, url: articles_path do |form| %>
  <%= form.text_field :title %>
<% end %>
# =>
<form action="/articles" method="post">
  <input type="text" name="article[title]" />
</form>

# Using a model infers both the URL and scope:
<%= form_with model: Article.new do |form| %>
  <%= form.text_field :title %>
<% end %>
# =>
<form action="/articles" method="post">
  <input type="text" name="article[title]" />
</form>

# An existing model makes an update form and fills out field values:
<%= form_with model: Article.first do |form| %>
  <%= form.text_field :title %>
<% end %>
# =>
<form action="/articles/1" method="post">
  <input type="hidden" name="_method" value="patch" />
  <input type="text" name="article[title]" value="<the title of the article>" />
</form>
# Though the fields don't have to correspond to model attributes:
<%= form_with model: Cat.new do |form| %>
  <%= form.text_field :cats_dont_have_gills %>
  <%= form.text_field :but_in_forms_they_can %>
<% end %>
# =>
<form action="/cats" method="post">
  <input type="text" name="cat[cats_dont_have_gills]" />
  <input type="text" name="cat[but_in_forms_they_can]" />
</form>

Параметры формы доступны в контроллерах в соответствии с их вложенностью в именах. Поэтому поля с именами title и article[title] доступны соответственно как params[:title] и params[:article][:title].

Для удобства сравнения в примерах выше не указаны кнопка отправки и автоматически сгенерированные скрытые поля, которые включают поддержку UTF-8 и добавляют токен подлинности, необходимый для защиты от межсайтовой подделки запросов.

Стиль, ориентированный на ресурсы

Во многих только что приведенных примерах в form_with передается :model, являющийся ресурсом. Он соответствует набору маршрутов RESTful, скорее всего определенных с помощью resources в config/routes.rb.

Таким образом, при передаче такой записи модели Rails определяет URL и метод.

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

эквивалентно примерно следующему:

<%= form_with scope: :article, url: article_path(@article), method: :patch do |form| %>
  ...
<% end %>

А для новой записи

<%= form_with model: Article.new do |form| %>
  ...
<% end %>

эквивалентно примерно следующему:

<%= form_with scope: :article, url: articles_path do |form| %>
  ...
<% end %>

Параметры form_with

  • :url — URL, на который отправляется форма. Аналогичен значениям, передаваемым в url_for или link_to. Например, можно напрямую использовать именованный маршрут. Если :scope передан без :url, форма отправляется на текущий URL.

  • :method — метод, используемый при отправке формы; обычно это «get» или «post». Если используется «patch», «put», «delete» или другой глагол, добавляется скрытое поле с именем _method, имитирующее этот глагол посредством post.

  • :format — формат маршрута, на который отправляется форма. Полезен при отправке данных другому типу ресурса, например :json. Игнорируется, если передан :url.

  • :scope — область видимости, добавляемая в качестве префикса к именам полей ввода и определяющая группировку отправленных параметров в контроллерах.

  • :namespace — пространство имен для формы, обеспечивающее уникальность атрибутов id элементов формы. В сгенерированном HTML к атрибуту пространства имен будет добавлено подчеркивание как префикс для id.

  • :model — объект модели, по которому определяются :url и :scope, а также заполняются значения полей ввода. Например, если атрибут title имеет значение «Ahoy!», то значение поля ввода title будет равно «Ahoy!». Если модель представляет собой новую запись, создается форма создания; если существующую — форма обновления. Передайте :scope или :url, чтобы переопределить значения по умолчанию. Например, превратить params[:article] в params[:blog].

  • :authenticity_token — токен подлинности, используемый в форме. Переопределите его собственным токеном подлинности или передайте false, чтобы полностью пропустить поле токена подлинности. Это полезно при отправке данных внешнему ресурсу, например платежному шлюзу, который может ограничивать допустимые поля. Для удаленных форм встроенный токен подлинности можно опустить, задав config.action_view.embed_authenticity_token_in_remote_forms = false. Это полезно при фрагментном кэшировании формы. Удаленные формы получают токен подлинности из тега meta, поэтому встраивать его не нужно, если только вы не поддерживаете браузеры без JavaScript.

  • :local — использовать ли стандартную отправку HTML-формы по HTTP. Если задано значение true, форма отправляется по стандартному HTTP. Если задано значение false, форма отправляется как «удаленная форма», обрабатываемая Rails UJS в виде XHR-запроса. Если значение не задано, поведение определяется параметром config.action_view.form_with_generates_remote_forms, значение которого в конфигурации является обратным значению local. Начиная с Rails 6.1, для этого параметра конфигурации по умолчанию задано значение false (что эквивалентно передаче local: true). В предыдущих версиях Rails для этого параметра конфигурации по умолчанию задано значение true (что эквивалентно передаче local: false).

  • :skip_enforcing_utf8 — если задано значение true, скрытое поле с именем utf8 не выводится.

  • :builder — переопределяет объект, используемый для создания формы.

  • :id — необязательный HTML-атрибут id.

  • :class — необязательный HTML-атрибут class.

  • :data — необязательные HTML-атрибуты data.

  • :html — другие необязательные HTML-атрибуты для тега формы.

Примеры

Если блок не передан, form_with просто создает открывающий тег формы.

<%= form_with(model: @article, url: super_articles_path) %>
<%= form_with(model: @article, scope: :blog) %>
<%= form_with(model: @article, format: :json) %>
<%= form_with(model: @article, authenticity_token: false) %> # Disables the token.

Для маршрутов с пространством имен, например admin_article_url:

<%= form_with(model: [ :admin, @article ]) do |form| %>
  ...
<% end %>

Если у ресурса определены ассоциации, можно, например, добавить комментарии к документу, при условии что маршруты настроены правильно:

<%= form_with(model: [ @document, Comment.new ]) do |form| %>
  ...
<% end %>

Здесь @document = Document.find(params[:id]).

Совместное использование с другими вспомогательными методами форм

Хотя form_with использует объект FormBuilder, можно комбинировать отдельные методы FormHelper и методы FormTagHelper:

<%= form_with scope: :person do |form| %>
  <%= form.text_field :first_name %>
  <%= form.text_field :last_name %>

  <%= textarea :person, :biography %>
  <%= checkbox_tag "person[admin]", "1", @person.company.admin? %>

  <%= form.submit %>
<% end %>

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

Задание метода

Можно заставить форму использовать полный набор HTTP-глаголов, задав

method: (:get|:post|:patch|:put|:delete)

в хеше параметров. Если используется глагол, отличный от GET или POST, которые изначально поддерживаются HTML-формами, для формы будет задан метод POST, а скрытое поле с именем _method будет содержать предназначенный для сервера глагол.

Задание параметров HTML

Атрибуты data можно задать напрямую в хеше data, но HTML-параметры, кроме id и class, необходимо обернуть в ключ HTML:

<%= form_with(model: @article, data: { behavior: "autosave" }, html: { name: "go" }) do |form| %>
  ...
<% end %>

создает

<form action="/articles/123" method="post" data-behavior="autosave" name="go">
  <input name="_method" type="hidden" value="patch" />
  ...
</form>

Удаление скрытых идентификаторов модели

Метод form_with автоматически добавляет идентификатор модели в форму в виде скрытого поля. Это позволяет сохранять связь между данными формы и соответствующей моделью. Некоторые ORM-системы не используют идентификаторы для вложенных моделей, поэтому в таких случаях может потребоваться отключить скрытое поле с идентификатором.

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

<%= form_with(model: @article) do |form| %>
  <%= form.fields(:comments, skip_id: true) do |fields| %>
    ...
  <% end %>
<% end %>

Настраиваемые построители форм

Формы также можно создавать с помощью настраиваемого класса FormBuilder. Создайте подкласс FormBuilder, переопределите или добавьте вспомогательные методы, а затем используйте собственный построитель. Например, предположим, что вы создали вспомогательный метод для автоматического добавления меток к полям формы.

<%= form_with model: @person, url: { action: "create" }, builder: LabellingFormBuilder do |form| %>
  <%= form.text_field :first_name %>
  <%= form.text_field :last_name %>
  <%= form.textarea :biography %>
  <%= form.checkbox :admin %>
  <%= form.submit %>
<% end %>

В этом случае, если использовать:

<%= render form %>

Будет отображен шаблон people/_labelling_form, а локальная переменная, ссылающаяся на построитель формы, будет называться labelling_form.

Настраиваемый класс FormBuilder автоматически объединяется с параметрами вложенного вызова fields, если только он не задан явно.

Во многих случаях приведенный выше код удобно обернуть в другой вспомогательный метод. Например, можно сделать следующее:

def labelled_form_with(**options, &block)
  form_with(**options.merge(builder: LabellingFormBuilder), &block)
end
hidden_field (object_name, method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1214
def hidden_field(object_name, method, options = {})
  Tags::HiddenField.new(object_name, method, self, options).render
end

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

Примеры

hidden_field(:signup, :pass_confirm)
# => <input type="hidden" id="signup_pass_confirm" name="signup[pass_confirm]" value="#{@signup.pass_confirm}" />

hidden_field(:article, :tag_list)
# => <input type="hidden" id="article_tag_list" name="article[tag_list]" value="#{@article.tag_list}" />

hidden_field(:user, :token)
# => <input type="hidden" id="user_token" name="user[token]" value="#{@user.token}" />
label (object_name, method, content_or_options = nil, options = nil, &block) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1151
def label(object_name, method, content_or_options = nil, options = nil, &block)
  Tags::Label.new(object_name, method, self, content_or_options, options).render(&block)
end

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

Примеры

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

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

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

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

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

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

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

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

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

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

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

label(:article, :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(:article, :terms) do
  raw('Accept <a href="/terms">Terms</a>.')
end
# => <label for="article_terms">Accept <a href="/terms">Terms</a>.</label>
month_field (object_name, method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1533
def month_field(object_name, method, options = {})
  Tags::MonthField.new(object_name, method, self, options).render
end

Возвращает text_field типа «month».

month_field("user", "born_on")
# => <input id="user_born_on" name="user[born_on]" type="month" />

Значение по умолчанию формируется попыткой вызвать strftime со строкой формата «%Y-%m» для значения объекта. Это обеспечивает ожидаемое поведение для экземпляров DateTime и ActiveSupport::TimeWithZone.

@user.born_on = Date.new(1984, 1, 27)
month_field("user", "born_on")
# => <input id="user_born_on" name="user[born_on]" type="date" value="1984-01" />
number_field (object_name, method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1577
def number_field(object_name, method, options = {})
  Tags::NumberField.new(object_name, method, self, options).render
end

Возвращает тег поля ввода типа «number».

Параметры

Поддерживает те же параметры, что и FormTagHelper#number_field_tag.

password_field (object_name, method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1196
def password_field(object_name, method, options = {})
  Tags::PasswordField.new(object_name, method, self, options).render
end

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

Примеры

password_field(:login, :pass, size: 20)
# => <input type="password" id="login_pass" name="login[pass]" size="20" />

password_field(:account, :secret, class: "form_input", value: @account.secret)
# => <input type="password" id="account_secret" name="account[secret]" value="#{@account.secret}" class="form_input" />

password_field(:user, :password, onchange: "if ($('#user_password').val().length > 30) { alert('Your password needs to be shorter!'); }")
# => <input type="password" id="user_password" name="user[password]" onchange="if ($('#user_password').val().length > 30) { alert('Your password needs to be shorter!'); }"/>

password_field(:account, :pin, size: 20, class: 'form_input')
# => <input type="password" id="account_pin" name="account[pin]" size="20" class="form_input" />
phone_field (object_name, method, options = {})

является псевдонимом для telephone_field

Псевдоним для: telephone_field
radio_button (object_name, method, tag_value, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1369
def radio_button(object_name, method, tag_value, options = {})
  Tags::RadioButton.new(object_name, method, self, tag_value, options).render
end

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

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

# Let's say that @article.category returns "rails":
radio_button("article", "category", "rails")
radio_button("article", "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("user", "receive_newsletter", "yes")
radio_button("user", "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 (object_name, method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1586
def range_field(object_name, method, options = {})
  Tags::RangeField.new(object_name, method, self, options).render
end

Возвращает тег поля ввода типа «range».

Параметры

Поддерживает те же параметры, что и FormTagHelper#range_field_tag.

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

Возвращает тег trix-editor, который создает редактор JavaScript Trix, а также скрытое поле, в которое Trix записывает изменения, чтобы содержимое отправлялось вместе с формой.

Параметры

  • :class — по умолчанию «trix-content», что обеспечивает применение стандартных стилей.

  • :value — добавляет значение по умолчанию в тег поля ввода HTML.

  • [:data][:direct_upload_url] — по умолчанию rails_direct_uploads_url.

  • [:data][:blob_url_template] — по умолчанию rails_service_blob_url(":signed_id", ":filename").

Пример

rich_textarea :message, :content
# <input type="hidden" name="message[content]" id="message_content_trix_input_message_1">
# <trix-editor id="content" input="message_content_trix_input_message_1" class="trix-content" ...></trix-editor>

rich_textarea :message, :content, value: "<h1>Default message</h1>"
# <input type="hidden" name="message[content]" id="message_content_trix_input_message_1" value="&lt;h1&gt;Default message&lt;/h1&gt;">
# <trix-editor id="content" input="message_content_trix_input_message_1" class="trix-content" ...></trix-editor>

rich_textarea :message, :content do
  "<h1>Default message</h1>"
end
# <input type="hidden" name="message[content]" id="message_content_trix_input_message_1" value="&lt;h1&gt;Default message&lt;/h1&gt;">
# <trix-editor id="content" input="message_content_trix_input_message_1" class="trix-content" ...></trix-editor>
Также имеет псевдоним: rich_text_area
search_field (object_name, method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1400
def search_field(object_name, method, options = {})
  Tags::SearchField.new(object_name, method, self, options).render
end

Возвращает поле ввода типа «search» для доступа к указанному атрибуту (идентифицируемому с помощью method) объекта, назначенного шаблону (идентифицируемого с помощью object_name). В некоторых браузерах поля ввода типа «search» могут отображаться иначе.

search_field(:user, :name)
# => <input id="user_name" name="user[name]" type="search" />
search_field(:user, :name, autosave: false)
# => <input autosave="false" id="user_name" name="user[name]" type="search" />
search_field(:user, :name, results: 3)
# => <input id="user_name" name="user[name]" results="3" type="search" />
#  Assume request.host returns "www.example.com"
search_field(:user, :name, autosave: true)
# => <input autosave="com.example.www" id="user_name" name="user[name]" results="10" type="search" />
search_field(:user, :name, onsearch: true)
# => <input id="user_name" incremental="true" name="user[name]" onsearch="true" type="search" />
search_field(:user, :name, autosave: false, onsearch: true)
# => <input autosave="false" id="user_name" incremental="true" name="user[name]" onsearch="true" type="search" />
search_field(:user, :name, autosave: true, onsearch: true)
# => <input autosave="com.example.www" id="user_name" incremental="true" name="user[name]" onsearch="true" results="10" type="search" />
telephone_field (object_name, method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1409
def telephone_field(object_name, method, options = {})
  Tags::TelField.new(object_name, method, self, options).render
end

Возвращает text_field типа «tel».

telephone_field("user", "phone")
# => <input id="user_phone" name="user[phone]" type="tel" />
Также имеет псевдоним: phone_field
text_area (object_name, method, options = {})
Псевдоним для: textarea
text_field (object_name, method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1175
def text_field(object_name, method, options = {})
  Tags::TextField.new(object_name, method, self, options).render
end

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

Примеры

text_field(:article, :title, size: 20)
# => <input type="text" id="article_title" name="article[title]" size="20" value="#{@article.title}" />

text_field(:article, :title, class: "create_input")
# => <input type="text" id="article_title" name="article[title]" value="#{@article.title}" class="create_input" />

text_field(:article, :title,  maxlength: 30, class: "title_input")
# => <input type="text" id="article_title" name="article[title]" maxlength="30" size="30" value="#{@article.title}" class="title_input" />

text_field(:session, :user, onchange: "if ($('#session_user').val() === 'admin') { alert('Your login cannot be admin!'); }")
# => <input type="text" id="session_user" name="session[user]" value="#{@session.user}" onchange="if ($('#session_user').val() === 'admin') { alert('Your login cannot be admin!'); }"/>

text_field(:snippet, :code, size: 20, class: 'code_input')
# => <input type="text" id="snippet_code" name="snippet[code]" size="20" value="#{@snippet.code}" class="code_input" />
textarea (object_name, method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1277
def textarea(object_name, method, options = {})
  Tags::TextArea.new(object_name, method, self, options).render
end

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

Примеры

textarea(:article, :body, cols: 20, rows: 40)
# => <textarea cols="20" rows="40" id="article_body" name="article[body]">
#      #{@article.body}
#    </textarea>

textarea(:comment, :text, size: "20x30")
# => <textarea cols="20" rows="30" id="comment_text" name="comment[text]">
#      #{@comment.text}
#    </textarea>

textarea(:application, :notes, cols: 40, rows: 15, class: 'app_input')
# => <textarea cols="40" rows="15" id="application_notes" name="application[notes]" class="app_input">
#      #{@application.notes}
#    </textarea>

textarea(:entry, :body, size: "20x20", disabled: 'disabled')
# => <textarea cols="20" rows="20" id="entry_body" name="entry[body]" disabled="disabled">
#      #{@entry.body}
#    </textarea>
Также имеет псевдоним: text_area
time_field (object_name, method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1479
def time_field(object_name, method, options = {})
  Tags::TimeField.new(object_name, method, self, options).render
end

Возвращает text_field типа «time».

Значение по умолчанию формируется попыткой вызвать strftime с форматом «%T.%L» для значения объекта. Если передать include_seconds: false, оно будет отформатировано попыткой вызвать strftime с форматом «%H:%M» для значения объекта. Это также можно переопределить, передав параметр «value».

Параметры

Поддерживаются те же параметры, что и у FormTagHelper#time_field_tag.

Примеры

time_field("task", "started_at")
# => <input id="task_started_at" name="task[started_at]" type="time" />

Значения атрибутов «min» и «max» можно задать, передав в хеш параметров экземпляры Date или Time.

time_field("task", "started_at", min: Time.now)
# => <input id="task_started_at" name="task[started_at]" type="time" min="01:00:00.000" />

В качестве значений для «min» и «max» также можно передать String в формате времени ISO8601.

time_field("task", "started_at", min: "01:00:00")
# => <input id="task_started_at" name="task[started_at]" type="time" min="01:00:00.000" />

По умолчанию переданные значения времени будут отформатированы с секундами. Чтобы отображались только часы и минуты, передайте include_seconds: false. Некоторые браузеры отображают более простой интерфейс, если в формате временной метки не указаны секунды.

time_field("task", "started_at", value: Time.now, include_seconds: false)
# => <input id="task_started_at" name="task[started_at]" type="time" value="01:00" />
url_field (object_name, method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1559
def url_field(object_name, method, options = {})
  Tags::UrlField.new(object_name, method, self, options).render
end

Возвращает text_field типа «url».

url_field("user", "homepage")
# => <input id="user_homepage" name="user[homepage]" type="url" />
week_field (object_name, method, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_helper.rb, line 1550
def week_field(object_name, method, options = {})
  Tags::WeekField.new(object_name, method, self, options).render
end

Возвращает text_field типа «week».

week_field("user", "born_on")
# => <input id="user_born_on" name="user[born_on]" type="week" />

Значение по умолчанию формируется попыткой вызвать strftime с форматом «%Y-W%W» для значения объекта, благодаря чему поле работает ожидаемым образом с экземплярами DateTime и ActiveSupport::TimeWithZone.

@user.born_on = Date.new(1984, 5, 12)
week_field("user", "born_on")
# => <input id="user_born_on" name="user[born_on]" type="date" value="1984-W19" />

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

Spec-Zone.ru

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