Spec-Zone.ru › Ruby on Rails 5.1

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

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

Предоставляет множество методов для преобразования различных типов контейнеров в набор тегов 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>

Общедоступные методы экземпляров

collection_check_boxes(object, method, collection, value_method, text_method, options = {}, html_options = {}, &block) Показать исходный код
# 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 в вспомогательный метод.

collection_radio_buttons(object, method, collection, value_method, text_method, options = {}, html_options = {}, &block) Показать исходный код
# 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.

collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {}) Показать исходный код
# 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>
grouped_collection_select(object, method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 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>
grouped_options_for_select(grouped_options, selected_key = nil, options = {}) Показать исходный код
# 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>.

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 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>.

options_for_select(container, selected = nil) Показать исходный код
# 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

    tag_builder.content_tag_string(:option, text, html_attributes)
  end.join("\n").html_safe
end

Принимает контейнер (хеш, массив, перечисляемый, ваш тип) и возвращает строку тегов option. Если элементы контейнера отвечают методам first и last (например, двуэлементный массив), то «последние» элементы служат значениями опции, а «первые» — текстом опции. Хеши автоматически преобразуются в этот формат, поэтому ключи становятся «первыми», а значения — «последними». Если selected указано, соответствующее «последнее» значение или элемент получит тег опции 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>

Если вы хотите указать теги disabled 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, вам необходимо обернуть этот вызов в обычный HTML-тег select.

options_from_collection_for_select(collection, value_method, text_method, selected = nil) Показать исходный код
# 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')

Не выберет человека с идентификатором 1, так как 1 (тип Integer) не совпадает с '1' (тип string)

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 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, соответствующих выводу других helpers:

  • Плоская коллекция (см. 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>

предполагая, что у связанного человека есть идентификатор 1.

Это можно использовать для предоставления набора опций стандартным способом: перед рендерингом формы создания экземпляр новой модели назначается по умолчанию и привязывается к @model_name. Обычно эта модель не сохраняется в базе данных. Вместо этого, второй объект модели создаётся при получении запроса на создание. Это позволяет пользователю отправлять страницу формы более одного раза с ожидаемыми результатами создания нескольких записей. Кроме того, это позволяет использовать один partial для генерации входных данных формы как для форм редактирования, так и для форм создания.

По умолчанию, 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

Gotcha

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

@user.update(params[:user])

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

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

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

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

time_zone_select(object, method, priority_zones = nil, options = {}, html_options = {}) Показать исходный код
# 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.

Spec-Zone.ru

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