Spec-Zone.ru › Ruby on Rails 5.2

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

Включенные модули:
ActionView::Helpers::TextHelper

Предоставляет ряд методов для преобразования различных типов контейнеров в набор тегов option.

Методы collection_select, select и time_zone_select принимают параметр options, являющийся хэшем:

  • :include_blank — устанавливается в true или в строку запроса, если первый элемент опции тега 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 ещё нет значения, он добавляет опцию с общим запросом — «Пожалуйста, выберите» — или заданной строкой запроса.

    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, чтобы вручную установить идентификатор, используемый в выходных данных. В отличие от других вспомогательных функций, 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 — может быть одиночным значением или массивом значений, которые будут отключенными опциями в выходных данных.

    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 также может быть процедурой, определяющей опции, которые должны быть отключены.

    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>

Методы публичного экземпляра

collection_check_boxes(объект, метод, коллекция, метод_значения, метод_текста, options = {}, html_options = {}, &block) Показать исходный код
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 756
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 в метод-помощник.

collection_radio_buttons(объект, метод, коллекция, метод_значения, метод_текста, options = {}, html_options = {}, &block) Показать исходный код
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 672
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.

collection_select(объект, метод, коллекция, метод_значения, метод_текста, options = {}, html_options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 203
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>
grouped_collection_select(объект, метод, коллекция, метод_группы, метод_метки_группы, метод_ключа_опции, метод_значения_опции, options = {}, html_options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 263
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>

Пример структуры объекта для использования с этим методом:

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>
grouped_options_for_select(grouped_options, selected_key = nil, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 531
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>.

option_groups_from_collection_for_select(collection, group_method, group_label_method, option_key_method, option_value_method, selected_key = nil) Показать исходный код
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 461
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".freeze, 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>.

options_for_select(container, selected = nil) Показать исходный код
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 357
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 (например, массив из двух элементов), «lasts» служат значениями опций, а «firsts» - текстом опций. Хэши автоматически преобразуются в эту форму, поэтому ключи становятся «firsts», а значения - «lasts». Если 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>

Если вы хотите указать отключённые теги option, установите selected в хэш, где :disabled может быть значением или массивом значений, которые нужно отключить. В этом случае вы можете использовать :selected для указания выбранных тегов option.

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, вам нужно обернуть этот вызов в обычный тег select.

options_from_collection_for_select(collection, value_method, text_method, selected = nil) Показать исходный код
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 400
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)

должно дать желаемый результат.

select(object, method, choices = nil, options = {}, html_options = {}, &block) Показать исходный код
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 164
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. Это полезно, когда тег 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

Проблема

Спецификация HTML гласит, что когда параметр multiple передан в select, а все опции отменены, веб-браузеры не отправляют никакого значения на сервер. К сожалению, это приводит к проблеме: если у модели User есть многие roles, и у неё есть role_ids аксессор, и в форме редактирования ролей пользователя пользователь отменяет все роли из role_ids множественного поля выбора, параметр role_ids не отправляется. Следовательно, любой подход массового присвоения, такой как:

@user.update(params[:user])

не обновил бы роли.

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

Примечание: Клиент отправляет либо только скрытое поле (представляющее отменённое поле множественного выбора), либо оба поля. Это означает, что результирующий массив всегда содержит пустую строку.

В случае, если вы не хотите, чтобы помощник генерировал это скрытое поле, вы можете указать опцию include_hidden: false.

time_zone_options_for_select(selected = nil, priority_zones = nil, model = ::ActiveSupport::TimeZone) Показать исходный код
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 575
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.

time_zone_select(object, method, priority_zones = nil, options = {}, html_options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 297
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.

Spec-Zone.ru

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