модуль ActionView::Helpers::FormOptionsHelper
Справочник по вспомогательным функциям Action View для выбора параметров формы
Предоставляет ряд методов для преобразования различных типов контейнеров в набор тегов option.
Методы collection_select, select и time_zone_select принимают параметр options, представляющий собой хэш:
-
:include_blank— устанавливается в значение true или строку-подсказку, если первый элемент option в элементе select пустой. Полезно, если для элемента select не требуется значение по умолчанию.select(:post, :category, Post::CATEGORIES, { include_blank: true })может стать:
<select name="post[category]" id="post_category"> <option value="" label=" "></option> <option value="joke">joke</option> <option value="poem">poem</option> </select>
Другой распространенный случай — тег select для объекта, связанного с
belongs_to.Пример с
@post.person_id => 2.select(:post, :person_id, Person.all.collect { |p| [ p.name, p.id ] }, { include_blank: "None" })может стать:
<select name="post[person_id]" id="post_person_id"> <option value="">None</option> <option value="1">David</option> <option value="2" selected="selected">Eileen</option> <option value="3">Rafael</option> </select>
-
:prompt— устанавливается в значение true или строку-подсказку. Если элемент select ещё не имеет значения, этот параметр добавляет option с общим запросом — «Пожалуйста, выберите» — или заданной строкой-подсказкой.select(:post, :person_id, Person.all.collect { |p| [ p.name, p.id ] }, { prompt: "Select Person" })может стать:
<select name="post[person_id]" id="post_person_id"> <option value="">Select Person</option> <option value="1">David</option> <option value="2">Eileen</option> <option value="3">Rafael</option> </select>
-
:index— как и другие вспомогательные функции для форм,selectможет принимать параметр:indexдля ручного указания ID, используемого в выходных данных. В отличие от других вспомогательных функций,selectожидает этот параметр вhtml_options.select("album[]", :genre, %w[ rap rock country ], {}, { index: nil })становится:
<select name="album[][genre]" id="album__genre"> <option value="rap">rap</option> <option value="rock">rock</option> <option value="country">country</option> </select>
-
:disabled— может быть одним значением или массивом значений, которые будут отключенными option в выходных данных.select(:post, :category, Post::CATEGORIES, { disabled: "restricted" })может стать:
<select name="post[category]" id="post_category"> <option value="joke">joke</option> <option value="poem">poem</option> <option disabled="disabled" value="restricted">restricted</option> </select>
При использовании с вспомогательной функцией
collection_select,:disabledтакже может быть процедурой, которая определяет опции, которые должны быть отключены.collection_select(:post, :category_id, Category.all, :id, :name, { disabled: -> (category) { category.archived? } })Если категории «2008 stuff» и «Christmas» возвращают true при вызове метода
archived?, это вернёт:<select name="post[category_id]" id="post_category_id"> <option value="1" disabled="disabled">2008 stuff</option> <option value="2" disabled="disabled">Christmas</option> <option value="3">Jokes</option> <option value="4">Poems</option> </select>
Публичные методы экземпляров
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 782
def collection_check_boxes(object, method, collection, value_method, text_method, options = {}, html_options = {}, &block)
Tags::CollectionCheckBoxes.new(object, method, self, collection, value_method, text_method, options, html_options).render(&block)
end Возвращает теги чекбоксов для коллекции существующих возвращаемых значений метода method для класса object. Значение, возвращаемое вызовом метода method для экземпляра object, будет выбрано. Если метод method возвращает nil, выбор не делается.
Параметры :value_method и :text_method представляют собой методы, которые вызываются для каждого элемента коллекции collection. Возвращаемые значения используются в качестве атрибута value и содержимого каждого тега чекбокса соответственно. Они также могут быть любыми объектами, которые отвечают на запрос call, такими как proc, который вызывается для каждого элемента collection для получения значения/текста.
Пример структуры объекта для использования с этим методом:
class Post < ActiveRecord::Base
has_and_belongs_to_many :authors
end
class Author < ActiveRecord::Base
has_and_belongs_to_many :posts
def name_with_initial
"#{first_name.first}. #{last_name}"
end
end
Пример использования (выбор соответствующего автора для экземпляра Post, @post):
collection_check_boxes(:post, :author_ids, Author.all, :id, :name_with_initial)
Если @post.author_ids уже [1], это вернет:
<input id="post_author_ids_1" name="post[author_ids][]" type="checkbox" value="1" checked="checked" /> <label for="post_author_ids_1">D. Heinemeier Hansson</label> <input id="post_author_ids_2" name="post[author_ids][]" type="checkbox" value="2" /> <label for="post_author_ids_2">D. Thomas</label> <input id="post_author_ids_3" name="post[author_ids][]" type="checkbox" value="3" /> <label for="post_author_ids_3">M. Clark</label> <input name="post[author_ids][]" type="hidden" value="" />
Также можно настроить отображение элементов, передав блок в метод:
collection_check_boxes(:post, :author_ids, Author.all, :id, :name_with_initial) do |b|
b.label { b.check_box }
end
Аргументом, передаваемым в блок, является специальный вид билдера для этой коллекции, который имеет возможность генерировать метку и чекбокс для текущего элемента коллекции с правильным текстом и значением. С его помощью можно изменить порядок отображения метки и чекбокса, или даже использовать метку в качестве обертки, как в примере выше.
Методы билдера label и check_box также принимают дополнительные HTML-параметры:
collection_check_boxes(:post, :author_ids, Author.all, :id, :name_with_initial) do |b|
b.label(class: "check_box") { b.check_box(class: "check_box") }
end
Доступны также три специальных метода: object, text и value, которые представляют собой текущий рендерируемый элемент, его методы получения текста и значения соответственно. Их можно использовать так:
collection_check_boxes(:post, :author_ids, Author.all, :id, :name_with_initial) do |b|
b.label(:"data-value" => b.value) { b.check_box + b.text }
end
Gotcha
Когда для коллекции чекбоксов не выбран ни один элемент, большинство веб-браузеров не отправляют значение.
Например, если у нас есть модель User с полем category_ids и в нашем действии обновления есть следующий код:
@user.update(params[:user])
Если не выбраны category_ids, то можно предположить, что это поле не будет обновлено.
Это возможно благодаря скрытому полю, генерируемому методом-помощником для каждой коллекции чекбоксов. Это скрытое поле имеет то же имя поля, что и чекбоксы, со значением по умолчанию.
В редких случаях, если вам не нужно это скрытое поле, можно передать параметр include_hidden: false методу-помощнику.
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 698
def collection_radio_buttons(object, method, collection, value_method, text_method, options = {}, html_options = {}, &block)
Tags::CollectionRadioButtons.new(object, method, self, collection, value_method, text_method, options, html_options).render(&block)
end Возвращает теги радиокнопок для коллекции существующих возвращаемых значений method для класса object. Значение, возвращаемое вызовом метода method для экземпляра object, будет выбрано. Если метод method возвращает nil, выбор не делается.
Параметры :value_method и :text_method — это методы, вызываемые для каждого элемента коллекции collection. Возвращаемые значения используются в качестве атрибута value и содержимого каждого тега радиокнопки соответственно. Они также могут быть любым объектом, который отвечает на запрос call, таким как proc, который вызывается для каждого элемента collection для получения значения/текста.
Пример структуры объекта для использования с этим методом:
class Post < ActiveRecord::Base
belongs_to :author
end
class Author < ActiveRecord::Base
has_many :posts
def name_with_initial
"#{first_name.first}. #{last_name}"
end
end
Пример использования (выбор соответствующего автора для экземпляра Post, @post):
collection_radio_buttons(:post, :author_id, Author.all, :id, :name_with_initial)
Если @post.author_id уже 1, это вернет:
<input id="post_author_id_1" name="post[author_id]" type="radio" value="1" checked="checked" /> <label for="post_author_id_1">D. Heinemeier Hansson</label> <input id="post_author_id_2" name="post[author_id]" type="radio" value="2" /> <label for="post_author_id_2">D. Thomas</label> <input id="post_author_id_3" name="post[author_id]" type="radio" value="3" /> <label for="post_author_id_3">M. Clark</label>
Также можно настроить отображение элементов, передав блок в метод:
collection_radio_buttons(:post, :author_id, Author.all, :id, :name_with_initial) do |b|
b.label { b.radio_button }
end
Аргумент, передаваемый в блок, — это специальный вид билдера для этой коллекции, который может генерировать метку и радиокнопку для текущего элемента коллекции с соответствующим текстом и значением. С его помощью можно изменить порядок отображения метки и радиокнопки или даже использовать метку в качестве обертки, как в примере выше.
Методы билдера label и radio_button также принимают дополнительные HTML-параметры:
collection_radio_buttons(:post, :author_id, Author.all, :id, :name_with_initial) do |b|
b.label(class: "radio_button") { b.radio_button(class: "radio_button") }
end
Доступны также три специальных метода: object, text и value, которые представляют собой текущий рендерируемый элемент, его методы получения текста и значения соответственно. Их можно использовать так:
collection_radio_buttons(:post, :author_id, Author.all, :id, :name_with_initial) do |b|
b.label(:"data-value" => b.value) { b.radio_button + b.text }
end
Gotcha
Спецификация HTML говорит, что когда ничего не выбрано в коллекции радиокнопок, веб-браузеры не отправляют серверу никакого значения. К сожалению, это приводит к проблеме: если у модели User есть поле category_id, и в форме не выбрана ни одна категория, параметр category_id не отправляется. Таким образом, любой idiom сильных параметров, такой как:
params.require(:user).permit(...)
вызовет ошибку, поскольку параметр {user: ...} отсутствует.
Чтобы предотвратить это, метод-помощник генерирует вспомогательное скрытое поле перед каждой коллекцией радиокнопок. Скрытое поле имеет то же имя, что и радиокнопки, и пустое значение.
Если вы не хотите, чтобы метод-помощник генерировал это скрытое поле, вы можете указать параметр include_hidden: false.
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 199
def collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {})
Tags::CollectionSelect.new(object, method, self, collection, value_method, text_method, options, html_options).render
end Возвращает теги <select> и <option> для коллекции существующих возвращаемых значений method для класса object. Значение, возвращаемое вызовом метода method для экземпляра object, будет выбрано. Если метод method возвращает nil, выбор не делается, если не включить :prompt или :include_blank в хеш options.
Параметры :value_method и :text_method — это методы, которые вызываются для каждого элемента коллекции collection. Возвращаемые значения используются в качестве атрибута value и содержимого каждого тега <option> соответственно. Они также могут быть любыми объектами, которые отвечают на запрос call, такими как proc, которые вызываются для каждого элемента коллекции collection для получения значения/текста.
Пример структуры объекта для использования с этим методом:
class Post < ActiveRecord::Base
belongs_to :author
end
class Author < ActiveRecord::Base
has_many :posts
def name_with_initial
"#{first_name.first}. #{last_name}"
end
end
Пример использования (выбор соответствующего автора для экземпляра Post, @post):
collection_select(:post, :author_id, Author.all, :id, :name_with_initial, prompt: true)
Если @post.author_id уже 1, это вернет:
<select name="post[author_id]" id="post_author_id"> <option value="">Please select</option> <option value="1" selected="selected">D. Heinemeier Hansson</option> <option value="2">D. Thomas</option> <option value="3">M. Clark</option> </select>
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 258
def grouped_collection_select(object, method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})
Tags::GroupedCollectionSelect.new(object, method, self, collection, group_method, group_label_method, option_key_method, option_value_method, options, html_options).render
end Возвращает теги <select>, <optgroup> и <option> для коллекции существующих возвращаемых значений method для класса object. Значение, возвращаемое вызовом метода method для экземпляра object, будет выбрано. Если метод method возвращает nil, выбор не делается, если не включить :prompt или :include_blank в хеш options.
Параметры:
-
object- Экземпляр класса, используемый для тега select -
method- Атрибутobject, соответствующий тегу select -
collection- Массив объектов, представляющих теги<optgroup> -
group_method- Имя метода, который, при вызове для членаcollection, возвращает массив дочерних объектов, представляющих теги<option>. Он также может быть любым объектом, который отвечает на запросcall, напримерproc, который вызывается для каждого членаcollectionдля получения значения. -
group_label_method- Имя метода, который, при вызове для членаcollection, возвращает строку, используемую в качестве атрибутаlabelдля его тега<optgroup>. Он также может быть любым объектом, который отвечает на запросcall, напримерproc, который вызывается для каждого членаcollectionдля получения метки. -
option_key_method- Имя метода, который, при вызове для дочернего объекта членаcollection, возвращает значение, используемое в качестве атрибутаvalueдля его тега<option>. -
option_value_method- Имя метода, который, при вызове для дочернего объекта членаcollection, возвращает значение, используемое в качестве содержимого тега<option>.
Пример структуры объекта для использования с этим методом:
# attributes: id, name class Continent < ActiveRecord::Base has_many :countries end # attributes: id, name, continent_id class Country < ActiveRecord::Base belongs_to :continent end # attributes: id, name, country_id class City < ActiveRecord::Base belongs_to :country end
Пример использования:
grouped_collection_select(:city, :country_id, @continents, :countries, :name, :id, :name)
Возможный вывод:
<select name="city[country_id]" id="city_country_id">
<optgroup label="Africa">
<option value="1">South Africa</option>
<option value="3">Somalia</option>
</optgroup>
<optgroup label="Europe">
<option value="7" selected="selected">Denmark</option>
<option value="2">Ireland</option>
</optgroup>
</select> # File actionview/lib/action_view/helpers/form_options_helper.rb, line 534
def grouped_options_for_select(grouped_options, selected_key = nil, options = {})
prompt = options[:prompt]
divider = options[:divider]
body = "".html_safe
if prompt
body.safe_concat content_tag("option", prompt_text(prompt), value: "")
end
grouped_options.each do |container|
html_attributes = option_html_attributes(container)
if divider
label = divider
else
label, container = container
end
html_attributes = { label: label }.merge!(html_attributes)
body.safe_concat content_tag("optgroup", options_for_select(container, selected_key), html_attributes)
end
body
end Возвращает строку тегов <option>, подобную options_for_select, но обернутые в теги <optgroup>.
grouped_options = [
['North America',
[['United States','US'],'Canada']],
['Europe',
['Denmark','Germany','France']]
]
grouped_options_for_select(grouped_options)
grouped_options = {
'North America' => [['United States','US'], 'Canada'],
'Europe' => ['Denmark','Germany','France']
}
grouped_options_for_select(grouped_options)
Возможный результат:
<optgroup label="North America"> <option value="US">United States</option> <option value="Canada">Canada</option> </optgroup> <optgroup label="Europe"> <option value="Denmark">Denmark</option> <option value="Germany">Germany</option> <option value="France">France</option> </optgroup>
Параметры:
-
grouped_options- Принимает вложенный массив или хеш строк. Первое значение используется в качестве метки<optgroup>, а второе значение должно быть массивом опций. Второе значение может быть вложенным массивом пар «текст-значение». Смотритеoptions_for_selectдля получения дополнительной информации.Ex. ["North America",[["United States","US"],["Canada","CA"]]]
Дополнительное третье значение может быть предоставлено в качестве атрибутов HTML для
optgroup.Ex. ["North America",[["United States","US"],["Canada","CA"]], { disabled: "disabled" }] -
selected_key- Значение, равное атрибутуvalueдля одного из тегов<option>, для которого будет установлено атрибутselected. Примечание: возможно, это значение соответствует нескольким опциям, поскольку одинаковая опция может встречаться в нескольких группах. В таком случае каждой из них будет присвоеноselected="selected".
Опции:
-
:prompt- устанавливается в true или строку подсказки. Если элемент select ещё не имеет значения, это добавляет опцию с общей подсказкой - «Пожалуйста, выберите» - или предоставленной строкой подсказки. -
:divider- разделитель для групп опций.grouped_options = [ [['United States','US'], 'Canada'], ['Denmark','Germany','France'] ] grouped_options_for_select(grouped_options, nil, divider: '---------')
Возможный результат:
<optgroup label="---------"> <option value="US">United States</option> <option value="Canada">Canada</option> </optgroup> <optgroup label="---------"> <option value="Denmark">Denmark</option> <option value="Germany">Germany</option> <option value="France">France</option> </optgroup>
Примечание: Возвращаются только теги <optgroup> и <option>, поэтому вам все равно нужно обернуть результат в соответствующий тег <select>.
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 462
def option_groups_from_collection_for_select(collection, group_method, group_label_method, option_key_method, option_value_method, selected_key = nil)
collection.map do |group|
option_tags = options_from_collection_for_select(
value_for_collection(group, group_method), option_key_method, option_value_method, selected_key)
content_tag("optgroup", option_tags, label: value_for_collection(group, group_label_method))
end.join.html_safe
end Возвращает строку тегов <option>, подобную options_from_collection_for_select, но группирует их по тегам <optgroup> на основе отношений объектов в аргументах.
Параметры:
-
collection- Массив объектов, представляющих теги<optgroup>. -
group_method- Название метода, который, при вызове на членеcollection, возвращает массив дочерних объектов, представляющих теги<option>. -
group_label_method- Название метода, который, при вызове на членеcollection, возвращает строку, используемую в качестве атрибутаlabelдля его тега<optgroup>. -
option_key_method- Название метода, который, при вызове на дочернем объекте членаcollection, возвращает значение, используемое в качестве атрибутаvalueдля его тега<option>. -
option_value_method- Название метода, который, при вызове на дочернем объекте членаcollection, возвращает значение, используемое в качестве содержимого тега<option>. -
selected_key- Значение, равное атрибутуvalueдля одного из тегов<option>, для которого будет установлено атрибутselected. Соответствует возвращаемому значению одного из вызововoption_key_method. Еслиnil, выбор не производится. Также может быть хешем, если необходимо указать отключенные значения.
Пример структуры объекта для использования с этим методом:
class Continent < ActiveRecord::Base has_many :countries # attribs: id, name end class Country < ActiveRecord::Base belongs_to :continent # attribs: id, name, continent_id end
Пример использования:
option_groups_from_collection_for_select(@continents, :countries, :name, :id, :name, 3)
Возможный результат:
<optgroup label="Africa"> <option value="1">Egypt</option> <option value="4">Rwanda</option> ... </optgroup> <optgroup label="Asia"> <option value="3" selected="selected">China</option> <option value="12">India</option> <option value="5">Japan</option> ... </optgroup>
Примечание: Возвращаются только теги <optgroup> и <option>, поэтому вам все равно нужно обернуть результат в соответствующий тег <select>.
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 358
def options_for_select(container, selected = nil)
return container if String === container
selected, disabled = extract_selected_and_disabled(selected).map do |r|
Array(r).map(&:to_s)
end
container.map do |element|
html_attributes = option_html_attributes(element)
text, value = option_text_and_value(element).map(&:to_s)
html_attributes[:selected] ||= option_value_selected?(value, selected)
html_attributes[:disabled] ||= disabled && option_value_selected?(value, disabled)
html_attributes[:value] = value
tag_builder.content_tag_string(:option, text, html_attributes)
end.join("\n").html_safe
end Принимает контейнер (хеш, массив, перечисляемый объект) и возвращает строку тегов option. Если элементы контейнера поддерживают методы first и last (например, массив из двух элементов), «last» используется как значение опции, а «first» - как текстовое значение. Хеши автоматически преобразуются в этот формат, поэтому ключи становятся «first», а значения - «last». Если selected указано, соответствующий «last» или элемент получит тег опции selected. selected также может быть массивом значений, которые необходимо выбрать при использовании многократного выбора.
options_for_select([["Dollar", "$"], ["Kroner", "DKK"]])
# => <option value="$">Dollar</option>
# => <option value="DKK">Kroner</option>
options_for_select([ "VISA", "MasterCard" ], "MasterCard")
# => <option value="VISA">VISA</option>
# => <option selected="selected" value="MasterCard">MasterCard</option>
options_for_select({ "Basic" => "$20", "Plus" => "$40" }, "$40")
# => <option value="$20">Basic</option>
# => <option value="$40" selected="selected">Plus</option>
options_for_select([ "VISA", "MasterCard", "Discover" ], ["VISA", "Discover"])
# => <option selected="selected" value="VISA">VISA</option>
# => <option value="MasterCard">MasterCard</option>
# => <option selected="selected" value="Discover">Discover</option>
Вы можете необязательно указать атрибуты HTML в качестве последнего элемента массива.
options_for_select([ "Denmark", ["USA", { class: 'bold' }], "Sweden" ], ["USA", "Sweden"])
# => <option value="Denmark">Denmark</option>
# => <option value="USA" class="bold" selected="selected">USA</option>
# => <option value="Sweden" selected="selected">Sweden</option>
options_for_select([["Dollar", "$", { class: "bold" }], ["Kroner", "DKK", { onclick: "alert('HI');" }]])
# => <option value="$" class="bold">Dollar</option>
# => <option value="DKK" onclick="alert('HI');">Kroner</option>
Если вы хотите указать отключенные теги опций, установите selected в хеш, где :disabled - это значение или массив значений, которые следует отключить. В этом случае вы можете использовать :selected для указания выбранных тегов опций.
options_for_select(["Free", "Basic", "Advanced", "Super Platinum"], disabled: "Super Platinum") # => <option value="Free">Free</option> # => <option value="Basic">Basic</option> # => <option value="Advanced">Advanced</option> # => <option value="Super Platinum" disabled="disabled">Super Platinum</option> options_for_select(["Free", "Basic", "Advanced", "Super Platinum"], disabled: ["Advanced", "Super Platinum"]) # => <option value="Free">Free</option> # => <option value="Basic">Basic</option> # => <option value="Advanced" disabled="disabled">Advanced</option> # => <option value="Super Platinum" disabled="disabled">Super Platinum</option> options_for_select(["Free", "Basic", "Advanced", "Super Platinum"], selected: "Free", disabled: "Super Platinum") # => <option value="Free" selected="selected">Free</option> # => <option value="Basic">Basic</option> # => <option value="Advanced">Advanced</option> # => <option value="Super Platinum" disabled="disabled">Super Platinum</option>
ПРИМЕЧАНИЕ: Возвращаются только теги option, вам нужно обернуть этот вызов в стандартный тег HTML select.
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 401
def options_from_collection_for_select(collection, value_method, text_method, selected = nil)
options = collection.map do |element|
[value_for_collection(element, text_method), value_for_collection(element, value_method), option_html_attributes(element)]
end
selected, disabled = extract_selected_and_disabled(selected)
select_deselect = {
selected: extract_values_from_collection(collection, value_method, selected),
disabled: extract_values_from_collection(collection, value_method, disabled)
}
options_for_select(options, select_deselect)
end Возвращает строку тегов option, сгенерированных итерацией по collection, где результат вызова value_method используется в качестве значения опции, а text_method - в качестве текстового значения опции.
options_from_collection_for_select(@people, 'id', 'name')
# => <option value="#{person.id}">#{person.name}</option>
Чаще всего используется внутри select_tag, как показано в этом примере:
select_tag 'person', options_from_collection_for_select(@people, 'id', 'name')
Если selected указано как значение или массив значений, теги опции, соответствующие элементам, совпадающим по value_method, будут выделены.
Если selected указано как Proc, те члены коллекции, которые возвращают true для анонимной функции, будут выделены.
selected также может быть хешем, определяющим значения :selected и/или :disabled по мере необходимости.
Убедитесь, что вы используете тот же класс для value_method, что и при указании выбранных или отключенных опций. Отсутствие этого может привести к нежелательным результатам. Пример:
options_from_collection_for_select(@people, 'id', 'name', '1')
Не выберет человека с id 1, потому что 1 (целое число) не равно '1' (строка).
options_from_collection_for_select(@people, 'id', 'name', 1)
должно дать нужный результат.
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 159
def select(object, method, choices = nil, options = {}, html_options = {}, &block)
Tags::Select.new(object, method, self, choices, options, html_options, &block).render
end Создаёт тег select и серию вложенных тегов option для предоставленного объекта и метода. Текущая опция объекта будет выбрана, если объект доступен.
Существует два возможных формата для параметра choices, соответствующих выводу других хелперов:
-
Плоская коллекция (см.
options_for_select). -
Вложенная коллекция (см.
grouped_options_for_select).
Пример с @post.person_id => 2:
select :post, :person_id, Person.all.collect { |p| [ p.name, p.id ] }, { include_blank: true }) превратится в:
<select name="post[person_id]" id="post_person_id"> <option value="" label=" "></option> <option value="1">David</option> <option value="2" selected="selected">Eileen</option> <option value="3">Rafael</option> </select>
Это можно использовать для предоставления набора стандартных опций: перед рендерингом формы создания экземпляр новой модели получает значения по умолчанию и связывается с @model_name. Обычно эта модель не сохраняется в базе данных. Вместо этого, второй объект модели создаётся при получении запроса на создание. Это позволяет пользователю несколько раз отправлять страницу формы с ожидаемыми результатами создания нескольких записей. Кроме того, это позволяет использовать один частичный шаблон для генерации полей формы как для форм редактирования, так и для создания.
По умолчанию post.person_id - это выделенная опция. Укажите selected: value для выбора другой опции или selected: nil для снятия выделения со всех опций. Аналогично, вы можете указать значения, которые будут отключены в тегах опций, указав опцию :disabled. Это может быть одно значение или массив значений, которые следует отключить.
Блок может быть передан в select для настройки рендеринга тегов option. Это полезно, когда тег option имеет сложные атрибуты.
select(report, :campaign_ids) do
available_campaigns.each do |c|
tag.option(c.name, value: c.id, data: { tags: c.tags.to_json })
end
end
Gotcha
Спецификация HTML гласит, что когда параметр multiple передан в select, и все опции сняты с выделения, веб-браузеры не отправляют никакие значения на сервер. К сожалению, это создаёт проблему: если у модели User много roles, и есть аксессор role_ids, а в форме редактирования ролей пользователя пользователь снимает выделение со всех ролей из role_ids поля многократного выбора, параметр role_ids не отправляется. Поэтому любое выражение массового присваивания, такое как
@user.update(params[:user])
не обновит роли.
Для предотвращения этого хелпер генерирует дополнительное скрытое поле перед каждым полем многократного выбора. У скрытого поля то же имя, что и у поля многократного выбора, и пустое значение.
Примечание: Клиент либо отправляет только скрытое поле (представляющее снятие выделения с поля многократного выбора), либо оба поля. Это означает, что результирующий массив всегда содержит пустую строку.
Если вы не хотите, чтобы хелпер генерировал это скрытое поле, вы можете указать опцию include_hidden: false.
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 579
def time_zone_options_for_select(selected = nil, priority_zones = nil, model = ::ActiveSupport::TimeZone)
zone_options = "".html_safe
zones = model.all
convert_zones = lambda { |list| list.map { |z| [ z.to_s, z.name ] } }
if priority_zones
if priority_zones.is_a?(Regexp)
priority_zones = zones.select { |z| z.match?(priority_zones) }
end
zone_options.safe_concat options_for_select(convert_zones[priority_zones], selected)
zone_options.safe_concat content_tag("option", "-------------", value: "", disabled: true)
zone_options.safe_concat "\n"
zones = zones - priority_zones
end
zone_options.safe_concat options_for_select(convert_zones[zones], selected)
end Возвращает строку тегов <option> для практически всех часовых поясов мира. Укажите имя ActiveSupport::TimeZone в качестве selected, чтобы отметить его как выбранный тег <option>. Вы также можете указать массив объектов ActiveSupport::TimeZone в качестве priority_zones, чтобы они были перечислены выше остальных (длинных) элементов списка. (Вы можете использовать ActiveSupport::TimeZone.us_zones для получения списка часовых поясов США или Regexp, чтобы выбрать часовые пояса по своему усмотрению)
Параметр selected должен быть либо nil, либо строкой, которая указывает имя ActiveSupport::TimeZone.
По умолчанию model является константой ActiveSupport::TimeZone (которую можно получить в Active Record как объект значения). Параметр model должен отвечать на запрос all и возвращать массив объектов, представляющих часовые пояса; каждый объект должен отвечать на запрос name. Если задан Regexp, он будет пытаться сопоставить часовые пояса, используя метод match?.
ПРИМЕЧАНИЕ: Возвращаются только теги <option>, вам нужно обернуть этот вызов в обычный HTML-тег <select>.
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 292
def time_zone_select(object, method, priority_zones = nil, options = {}, html_options = {})
Tags::TimeZoneSelect.new(object, method, self, priority_zones, options, html_options).render
end Возвращает теги <select> и <option> для данного объекта и метода, используя time_zone_options_for_select для генерации списка тегов <option>.
В дополнение к параметру :include_blank, описанному выше, этот метод также поддерживает параметр :model, который по умолчанию равен ActiveSupport::TimeZone. Пользователи могут использовать его для указания объекта модели часового пояса. (См. time_zone_options_for_select для получения дополнительной информации.)
Вы также можете указать массив объектов ActiveSupport::TimeZone как priority_zones, чтобы они были перечислены выше остальных (длинных) элементов списка. Вы можете использовать ActiveSupport::TimeZone.us_zones для списка часовых поясов США, ActiveSupport::TimeZone.country_zones(country_code) для часовых поясов другой страны или Regexp для выбора часовых поясов по своему усмотрению.
Наконец, этот метод поддерживает параметр :default, который выбирает значение по умолчанию ActiveSupport::TimeZone, если часовой пояс объекта nil.
time_zone_select(:user, :time_zone, nil, include_blank: true) time_zone_select(:user, :time_zone, nil, default: "Pacific Time (US & Canada)") time_zone_select(:user, :time_zone, ActiveSupport::TimeZone.us_zones, default: "Pacific Time (US & Canada)") time_zone_select(:user, :time_zone, [ ActiveSupport::TimeZone["Alaska"], ActiveSupport::TimeZone["Hawaii"] ]) time_zone_select(:user, :time_zone, /Australia/) time_zone_select(:user, :time_zone, ActiveSupport::TimeZone.all.sort, model: ActiveSupport::TimeZone)
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 611
def weekday_options_for_select(selected = nil, index_as_value: false, day_format: :day_names, beginning_of_week: Date.beginning_of_week)
day_names = I18n.translate("date.#{day_format}")
day_names = day_names.map.with_index.to_a if index_as_value
day_names = day_names.rotate(Date::DAYS_INTO_WEEK.fetch(beginning_of_week))
options_for_select(day_names, selected)
end Возвращает строку тегов <option> для дней недели.
Параметры:
-
:index_as_value- По умолчанию false, установите в true, чтобы использовать индексы изI18n.translate("date.day_names")в качестве значений. По умолчанию воскресенье всегда 0. -
:day_format- Ключ I18n массива для использования в качестве вариантов дней недели. По умолчанию:day_names, установите в:abbr_day_namesдля сокращений. -
:beginning_of_week- По умолчаниюDate.beginning_of_week.
ПРИМЕЧАНИЕ: Возвращаются только теги <option>, вам нужно обернуть этот вызов в обычный HTML-тег <select>.
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 298
def weekday_select(object, method, options = {}, html_options = {}, &block)
Tags::WeekdaySelect.new(object, method, self, options, html_options, &block).render
end Возвращает теги <select> и <option> для данного объекта и метода, используя weekday_options_for_select для генерации списка тегов <option>.
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.