модуль ActionView::Helpers::FormOptionsHelper
Предоставляет множество методов для преобразования различных типов контейнеров в набор тегов 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=""></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=""></option> <option value="joke">joke</option> <option value="poem">poem</option> <option disabled="disabled" value="restricted">restricted</option> </select>
Когда используется вспомогательный метод
collection_select,:disabledтакже может быть методом Proc, который определяет те option, которые должны быть отключены.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 750
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
Примечания
Когда для коллекции флажков не выбран ни один элемент, большинство веб-браузеров не отправят никакого значения.
Например, если у нас есть модель User с полем category_ids и у нас есть следующий код в действии обновления:
@user.update(params[:user])
Если не выбраны category_ids, можно предположить, что это поле не будет обновлено.
Это возможно благодаря скрытому полю, генерируемому вспомогательным методом для каждой коллекции флажков. Это скрытое поле получает то же имя поля, что и флажки, со значением по умолчанию.
В редких случаях, если вам не нужно это скрытое поле, можно передать опцию include_hidden: false вспомогательному методу.
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 666
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
Примечания
Спецификация 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 201
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 257
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> -
group_label_method— имя метода, который, при вызове для элемента коллекцииcollection, возвращает строку, используемую в качестве атрибутаlabelдля его тега<optgroup> -
option_key_method— имя метода, который, при вызове для дочернего объекта элемента коллекцииcollection, возвращает значение, используемое в качестве атрибутаvalueдля его тега<option> -
option_value_method— имя метода, который, при вызове для дочернего объекта элемента коллекцииcollection, возвращает значение, используемое в качестве содержимого его тега<option>
Пример структуры объекта для использования с этим методом:
class Continent < ActiveRecord::Base has_many :countries # attribs: id, name end class Country < ActiveRecord::Base belongs_to :continent # attribs: id, name, continent_id end class City < ActiveRecord::Base belongs_to :country # attribs: id, name, country_id 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 525
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".freeze, 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".freeze, 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"]]]
-
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 455
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(
group.send(group_method), option_key_method, option_value_method, selected_key)
content_tag("optgroup".freeze, option_tags, label: group.send(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 351
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
content_tag_string(:option, text, html_attributes)
end.join("\n").html_safe
end Принимает контейнер (хеш, массив, перечислимый, ваш тип) и возвращает строку тегов option. Учитывая контейнер, элементы которого реагируют на first и last (например, массив из двух элементов), «last» служат значениями опций, а «first» — текстом опций. Хеши автоматически преобразуются в этот формат, поэтому ключи становятся «first», а значения — «last». Если selected указан, соответствующий «last» или элемент получит выделенный тег option. 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 394
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 , будут выделенными тегами option.
Если 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 162
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).
Например:
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=""></option> <option value="1" selected="selected">David</option> <option value="2">Eileen</option> <option value="3">Rafael</option> </select>
при условии, что соответствующий человек имеет ID 1.
Это можно использовать для предоставления набора опций стандартным способом: перед отрисовкой формы создания новой экземпляру модели назначаются стандартные опции и привязываются к @model_name. Обычно эта модель не сохраняется в базе данных. Вместо этого второй объект модели создается при получении запроса на создание. Это позволяет пользователю отправлять форму более одного раза с ожидаемыми результатами создания нескольких записей. Кроме того, это позволяет использовать один фрагмент для генерации входных данных формы как для форм редактирования, так и для форм создания.
По умолчанию, post.person_id является выделенной опцией. Укажите selected: value , чтобы использовать другой выбор, или selected: nil , чтобы оставить все опции без выделения. Аналогично, вы можете указать значения для отключения в тегах option, указав опцию :disabled . Это может быть либо одно значение, либо массив значений, которые нужно отключить.
Блок может быть передан в select для настройки того, как будут отображаться теги option. Это полезно, когда теги опции имеют сложные атрибуты.
select(report, "campaign_ids") do
available_campaigns.each do |c|
content_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 не отправляется. Таким образом, любой idiom массового назначения, как
@user.update(params[:user])
не обновит роли.
Для предотвращения этого вспомогательная функция генерирует дополнительное скрытое поле перед каждым полем многократного выбора. Скрытое поле имеет то же имя, что и поле многократного выбора, и пустое значение.
Примечание: Клиент отправляет либо только скрытое поле (представляющее снятое с выделения поле многократного выбора), либо оба поля. Это означает, что результирующий массив всегда содержит пустую строку.
В случае если вы не хотите, чтобы вспомогательная функция генерировала это скрытое поле, вы можете указать опцию include_hidden: false.
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 569
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 =~ priority_zones }
end
zone_options.safe_concat options_for_select(convert_zones[priority_zones], selected)
zone_options.safe_concat content_tag("option".freeze, '-------------', 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 для удобства получения списка часовых поясов США или регулярное выражение для выбора необходимых поясов)
Параметр selected должен быть либо nil, либо строкой, которая называет ActiveSupport::TimeZone.
По умолчанию model является константой ActiveSupport::TimeZone (которую можно получить в Active Record как объект-значение). Единственное требование заключается в том, чтобы параметр model был объектом, который отвечает на all, и возвращает массив объектов, представляющих часовые пояса.
ПРИМЕЧАНИЕ: Возвращаются только теги option, вам нужно заключить этот вызов в обычный тег HTML select.
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 291
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 для часовых поясов другой страны или регулярное выражение для выбора необходимых поясов.
Наконец, этот метод поддерживает параметр :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)
© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.