跳至内容 跳至搜索

Action View 表单选项助手

提供了一些方法,可以将不同类型的容器转换为一组选项标签。

collection_selectselecttime_zone_select 方法接受一个 options 参数,它是一个哈希表

  • :include_blank - 设置为 true 或提示字符串,如果选择元素的第一个选项元素为空。 如果选择元素不需要默认值,则很有用。

    select(:post, :category, Post::CATEGORIES, { include_blank: true })
    

    可能变成

    <select name="post[category]" id="post_category">
      <option value="" label=" "></option>
      <option value="joke">joke</option>
      <option value="poem">poem</option>
    </select>
    

    另一个常见情况是针对 belongs_to 关联对象的 select 标签。

    带有 @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(: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 - 可以是单个值或一个值数组,这些值将在最终输出中被禁用选项。

    select(:post, :category, Post::CATEGORIES, { disabled: "restricted" })
    

    可能变成

    <select name="post[category]" id="post_category">
      <option value="joke">joke</option>
      <option value="poem">poem</option>
      <option disabled="disabled" value="restricted">restricted</option>
    </select>
    

    collection_select 助手一起使用时,:disabled 也可以是一个 Proc,它识别应该禁用的选项。

    collection_select(:post, :category_id, Category.all, :id, :name, { disabled: -> (category) { category.archived? } })
    

    如果类别“2008 年的东西”和“圣诞节”在调用 archived? 方法时返回 true,则这将返回

    <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>
    
方法
C
G
O
S
T
W
包含的模块

实例公共方法

collection_check_boxes(object, method, collection, value_method, text_method, options = {}, html_options = {}, &block)

collection_checkboxes(object, method, collection, value_method, text_method, options = {}, html_options = {}, &block)

object 类中 method 的现有返回值集合返回复选框标签。 从在实例 object 上调用 method 返回的值将被选中。 如果调用 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_checkboxes(: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_checkboxes(:post, :author_ids, Author.all, :id, :name_with_initial) do |b|
  b.label { b.checkbox }
end

传递给代码块的参数是一种特殊类型的此集合的构建器,它能够生成当前项目在集合中的标签和复选框,并具有正确的文本和值。 使用它,可以更改标签和复选框的显示顺序,甚至可以像上面的例子一样使用标签作为包装器。

构建器方法 labelcheckbox 也接受额外的 HTML 选项

collection_checkboxes(:post, :author_ids, Author.all, :id, :name_with_initial) do |b|
  b.label(class: "checkbox") { b.checkbox(class: "checkbox") }
end

还有三个特殊的方法可用:objecttextvalue,它们分别是当前正在渲染的项目、其文本和值方法。 可以像这样使用它们

collection_checkboxes(:post, :author_ids, Author.all, :id, :name_with_initial) do |b|
   b.label(:"data-value" => b.value) { b.checkbox + b.text }
end

注意点

当没有为复选框集合进行选择时,大多数 Web 浏览器不会发送任何值。

例如,如果我们有一个 User 模型,其中有 category_ids 字段,并且我们在更新操作中使用以下代码

@user.update(params[:user])

如果没有选择 category_ids,那么我们可以安全地假设此字段不会被更新。

这是可能的,因为助手方法为每个复选框集合生成一个隐藏字段。 此隐藏字段被赋予与复选框相同的字段名,并具有空值。

在极少数情况下,你不希望这个隐藏字段,可以将 include_hidden: false 选项传递给助手方法。

# File actionview/lib/action_view/helpers/form_options_helper.rb, line 782
def collection_checkboxes(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

collection_radio_buttons(object, method, collection, value_method, text_method, options = {}, html_options = {}, &block)

object 类中 method 的现有返回值集合返回单选按钮标签。 从在实例 object 上调用 method 返回的值将被选中。 如果调用 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

传递给代码块的参数是一种特殊类型的此集合的构建器,它能够生成当前项目在集合中的标签和单选按钮,并具有正确的文本和值。 使用它,可以更改标签和单选按钮的显示顺序,甚至可以像上面的例子一样使用标签作为包装器。

构建器方法 labelradio_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

还有三个特殊的方法可用:objecttextvalue,它们分别是当前正在渲染的项目、其文本和值方法。 可以像这样使用它们

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 规范指出,当单选按钮集合中没有选中任何项目时,Web 浏览器不会向服务器发送任何值。 不幸的是,这会引入一个注意点:如果 User 模型有一个 category_id 字段,并且在表单中没有选择任何类别,则不会发送任何 category_id 参数。 因此,任何像这样的强参数习惯用法

params.expect(user: [...])

将引发错误,因为不会存在 {user: ...}

为了防止这种情况,助手在每个单选按钮集合之前生成一个辅助隐藏字段。 隐藏字段具有与单选按钮集合相同的名称和空值。

如果你不希望助手生成这个隐藏字段,可以指定 include_hidden: false 选项。

# File actionview/lib/action_view/helpers/form_options_helper.rb, line 698
def collection_radio_buttons(object, method, collection, value_method, text_method, options = {}, html_options = {}, &block)
  Tags::CollectionRadioButtons.new(object, method, self, collection, value_method, text_method, options, html_options).render(&block)
end

collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {})

object 类中 method 的现有返回值集合返回 <select><option> 标签。 从在实例 object 上调用 method 返回的值将被选中。 如果调用 method 返回 nil,则在不将 :prompt:include_blank 包含在 options 哈希表中时,不会进行任何选择。

:value_method:text_method 参数是要在 collection 的每个成员上调用的方法。 返回值分别用作每个 <option> 标签的 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_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 199
def collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {})
  Tags::CollectionSelect.new(object, method, self, collection, value_method, text_method, options, html_options).render
end

grouped_collection_select(object, method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})

object 类中 method 的现有返回值集合返回 <select><optgroup><option> 标签。 从在实例 object 上调用 method 返回的值将被选中。 如果调用 method 返回 nil,则在不将 :prompt:include_blank 包含在 options 哈希表中时,不会进行任何选择。

参数

  • object - 将用于 select 标签的类的实例

  • method - 对应于 select 标签的 object 的属性

  • collection - 代表 <optgroup> 标签的对象数组。

  • group_method - 当在 collection 的成员上调用时,返回代表 <option> 标签的子对象数组的方法的名称。 它也可以是任何响应 call 的对象,例如 proc,它将在 collection 的每个成员上被调用以检索值。

  • group_label_method - 当在 collection 的成员上调用时,返回要用于其 <optgroup> 标签的 label 属性的字符串的方法的名称。 它也可以是任何响应 call 的对象,例如 proc,它将在 collection 的每个成员上被调用以检索标签。

  • option_key_method - 当在 collection 的成员的子对象上调用时,返回要用于其 <option> 标签的 value 属性的值的方法的名称。

  • option_value_method - 当在 collection 的成员的子对象上调用时,返回要用于其 <option> 标签的内容的值的方法的名称。

此方法使用的示例对象结构

# attributes: id, name
class Continent < ActiveRecord::Base
  has_many :countries
end

# attributes: id, name, continent_id
class Country < ActiveRecord::Base
  belongs_to :continent
end

# attributes: id, name, country_id
class City < ActiveRecord::Base
  belongs_to :country
end

示例用法

grouped_collection_select(:city, :country_id, @continents, :countries, :name, :id, :name)

可能的输出

<select name="city[country_id]" id="city_country_id">
  <optgroup label="Africa">
    <option value="1">South Africa</option>
    <option value="3">Somalia</option>
  </optgroup>
  <optgroup label="Europe">
    <option value="7" selected="selected">Denmark</option>
    <option value="2">Ireland</option>
  </optgroup>
</select>
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 258
def grouped_collection_select(object, method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})
  Tags::GroupedCollectionSelect.new(object, method, self, collection, group_method, group_label_method, option_key_method, option_value_method, options, html_options).render
end

grouped_options_for_select(grouped_options, selected_key = nil, options = {})

返回一串 <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"]]]
    

    可以提供一个可选的第三个值作为 optgroup 的 HTML 属性。

    Ex. ["North America",[["United States","US"],["Canada","CA"]], { disabled: "disabled" }]
    
  • selected_key - 一个等于 <option> 标签之一的 value 属性的值,该标签将设置 selected 属性。 注意:此值可能与多个选项匹配,因为你可能在多个组中具有相同的选项。 然后,每个组将获得 selected="selected"

选项

  • :prompt - 设置为 true 或提示字符串。当选择元素还没有值时,这将预先添加一个带有通用提示的选项 - “请选择” - 或给定的提示字符串。

  • :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 534
def grouped_options_for_select(grouped_options, selected_key = nil, options = {})
  prompt  = options[:prompt]
  divider = options[:divider]

  body = "".html_safe

  if prompt
    body.safe_concat content_tag("option", prompt_text(prompt), value: "")
  end

  grouped_options.each do |container|
    html_attributes = option_html_attributes(container)

    if divider
      label = divider
    else
      label, container = container
    end

    html_attributes = { label: label }.merge!(html_attributes)
    body.safe_concat content_tag("optgroup", options_for_select(container, selected_key), html_attributes)
  end

  body
end

option_groups_from_collection_for_select(collection, group_method, group_label_method, option_key_method, option_value_method, selected_key = nil)

返回一个 <option> 标签的字符串,类似于 options_from_collection_for_select,但根据参数的对象关系将它们分组到 <optgroup> 标签中。

参数

  • collection - 代表 <optgroup> 标签的对象数组。

  • group_method - 当在 collection 的成员上调用时,返回一个表示 <option> 标签的子对象数组的方法的名称。

  • group_label_method - 当在 collection 的成员上调用时,返回一个字符串,该字符串将用作其 <optgroup> 标签的 label 属性的方法的名称。

  • option_key_method - 当在 collection 的成员的子对象上调用时,返回要用于其 <option> 标签的 value 属性的值的方法的名称。

  • option_value_method - 当在 collection 的成员的子对象上调用时,返回要用于其 <option> 标签的内容的值的方法的名称。

  • selected_key - 一个值,等于其中一个 <option> 标签的 value 属性,该属性将具有 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 462
def option_groups_from_collection_for_select(collection, group_method, group_label_method, option_key_method, option_value_method, selected_key = nil)
  collection.map do |group|
    option_tags = options_from_collection_for_select(
      value_for_collection(group, group_method), option_key_method, option_value_method, selected_key)

    content_tag("optgroup", option_tags, label: value_for_collection(group, group_label_method))
  end.join.html_safe
end

options_for_select(container, selected = nil)

接受一个容器(哈希、数组、可枚举、您的类型),并返回一个选项标签的字符串。给定一个元素响应 first 和 last(如两个元素数组)的容器,"lasts" 充当选项值,"firsts" 充当选项文本。哈希会自动转换为这种形式,因此键变为“firsts”,值变为“lasts”。如果指定了 selected,则匹配的“last”或元素将获得选定的选项标签。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>

注意:只返回选项标签,您必须将此调用包装在常规 HTML select 标签中。

# File actionview/lib/action_view/helpers/form_options_helper.rb, line 358
def options_for_select(container, selected = nil)
  return container if String === container

  selected, disabled = extract_selected_and_disabled(selected).map do |r|
    Array(r).map(&:to_s)
  end

  container.map do |element|
    html_attributes = option_html_attributes(element)
    text, value = option_text_and_value(element).map(&:to_s)

    html_attributes[:selected] ||= option_value_selected?(value, selected)
    html_attributes[:disabled] ||= disabled && option_value_selected?(value, disabled)
    html_attributes[:value] = value

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

options_from_collection_for_select(collection, value_method, text_method, selected = nil)

返回一个选项标签的字符串,这些标签是通过迭代 collection 并将对 value_method 的调用的结果分配为选项值,将 text_method 分配为选项文本而编译的。

options_from_collection_for_select(@people, 'id', 'name')
# => <option value="#{person.id}">#{person.name}</option>

这通常用在 select_tag 中,如下例所示

select_tag 'person', options_from_collection_for_select(@people, 'id', 'name')

如果 selected 指定为值或值数组,则在 value_method 上返回匹配项的元素将是选定的选项标签。

如果 selected 指定为 Proc,则对匿名函数返回 true 的集合成员是选定的值。

selected 也可以是哈希,根据需要指定 :selected 和/或 :disabled 值。

请确保在指定选定或禁用的选项时,指定与 value_method 相同的类。不这样做会导致意外结果。示例

options_from_collection_for_select(@people, 'id', 'name', '1')

不会选择 id 为 1 的人,因为 1(Integer)与 '1'(字符串)不同

options_from_collection_for_select(@people, 'id', 'name', 1)

应该产生预期的结果。

# File actionview/lib/action_view/helpers/form_options_helper.rb, line 401
def options_from_collection_for_select(collection, value_method, text_method, selected = nil)
  options = collection.map do |element|
    [value_for_collection(element, text_method), value_for_collection(element, value_method), option_html_attributes(element)]
  end
  selected, disabled = extract_selected_and_disabled(selected)
  select_deselect = {
    selected: extract_values_from_collection(collection, value_method, selected),
    disabled: extract_values_from_collection(collection, value_method, disabled)
  }

  options_for_select(options, select_deselect)
end

select(object, method, choices = nil, options = {}, html_options = {}, &block)

为提供的对象和方法创建 select 标签和一系列包含的选项标签。如果对象可用,则将选择对象当前持有的选项。

choices 参数有两种可能的格式,对应于其他帮助器的输出

  • 平面集合(参见 options_for_select)。

  • 嵌套集合(参见 grouped_options_for_select)。

带有 @post.person_id => 2 的示例

select :post, :person_id, Person.all.collect { |p| [ p.name, p.id ] }, { include_blank: true })

将变成

<select name="post[person_id]" id="post_person_id">
  <option value="" label=" "></option>
  <option value="1">David</option>
  <option value="2" selected="selected">Eileen</option>
  <option value="3">Rafael</option>
</select>

这可用于以标准方式提供一组默认选项:在渲染创建表单之前,将默认选项分配给新模型实例,并将其绑定到 @model_name。通常,此模型不会保存到数据库中。相反,在收到创建请求时,会创建第二个模型对象。这允许用户多次提交表单页面,并获得创建多个记录的预期结果。此外,这允许使用单个部分来生成编辑和创建表单的表单输入。

默认情况下,post.person_id 是选定的选项。指定 selected: value 以使用不同的选择,或指定 selected: nil 以使所有选项不选中。类似地,您可以通过指定 :disabled 选项,指定要在选项标签中禁用的值。这可以是单个值,也可以是要禁用的值的数组。

可以将代码块传递给 select,以自定义选项标签的渲染方式。当选项标签具有复杂属性时,这很有用。

select(report, :campaign_ids) do
  available_campaigns.each do |c|
    tag.option(c.name, value: c.id, data: { tags: c.tags.to_json })
  end
end

注意点

HTML 规范说,当 multiple 参数传递给 select 并且所有选项都被取消选中时,Web 浏览器不会向服务器发送任何值。不幸的是,这会带来一个陷阱:如果 User 模型具有多个 roles 并具有 role_ids 访问器,并且在编辑用户角色的表单中,用户从 role_ids 多选框中取消选中所有角色,则不会发送任何 role_ids 参数。因此,任何类似于以下的批量分配习惯用法

@user.update(params[:user])

将不会更新角色。

为了防止这种情况,帮助器在每个多选框之前生成一个辅助隐藏字段。隐藏字段与多选框具有相同的名称,并且具有空值。

注意: 客户端要么只发送隐藏字段(表示取消选中的多选框),要么发送这两个字段。这意味着结果数组始终包含一个空字符串。

如果你不希望助手生成这个隐藏字段,可以指定 include_hidden: false 选项。

# File actionview/lib/action_view/helpers/form_options_helper.rb, line 159
def select(object, method, choices = nil, options = {}, html_options = {}, &block)
  Tags::Select.new(object, method, self, choices, options, html_options, &block).render
end

time_zone_options_for_select(selected = nil, priority_zones = nil, model = ::ActiveSupport::TimeZone)

返回一个选项标签的字符串,用于世界上几乎任何时区。提供一个 ActiveSupport::TimeZone 名称作为 selected,将其标记为选定的选项标签。您也可以提供一个 ActiveSupport::TimeZone 对象数组作为 priority_zones,这样它们将列在其余(长)列表的顶部。(您可以使用 ActiveSupport::TimeZone.us_zones 作为获取美国时区列表的便利方法,或使用 Regexp 选择您选择的时区)

selected 参数必须是 nil 或命名 ActiveSupport::TimeZone 的字符串。

默认情况下,modelActiveSupport::TimeZone 常量(可以在 Active Record 中作为值对象获得)。model 参数必须响应 all 并返回一个表示时区对象的数组;每个对象必须响应 name。如果给定 Regexp,它将尝试使用 match? 方法匹配时区。

注意:只返回选项标签,您必须将此调用包装在常规 HTML select 标签中。

# File actionview/lib/action_view/helpers/form_options_helper.rb, line 579
def time_zone_options_for_select(selected = nil, priority_zones = nil, model = ::ActiveSupport::TimeZone)
  zone_options = "".html_safe

  zones = model.all
  convert_zones = lambda { |list| list.map { |z| [ z.to_s, z.name ] } }

  if priority_zones
    if priority_zones.is_a?(Regexp)
      priority_zones = zones.select { |z| z.match?(priority_zones) }
    end

    zone_options.safe_concat options_for_select(convert_zones[priority_zones], selected)
    zone_options.safe_concat content_tag("option", "-------------", value: "", disabled: true)
    zone_options.safe_concat "\n"

    zones = zones - priority_zones
  end

  zone_options.safe_concat options_for_select(convert_zones[zones], selected)
end

time_zone_select(object, method, priority_zones = nil, options = {}, html_options = {})

为给定的对象和方法返回 select 和 option 标签,使用 time_zone_options_for_select 生成选项标签列表。

除了上面记录的 :include_blank 选项之外,此方法还支持 :model 选项,该选项默认为 ActiveSupport::TimeZone。用户可以使用它指定不同的时区模型对象。(有关更多信息,请参见 time_zone_options_for_select。)

您也可以提供一个 ActiveSupport::TimeZone 对象数组作为 priority_zones,这样它们将列在其余(长)列表的顶部。您可以使用 ActiveSupport::TimeZone.us_zones 获取美国时区列表,ActiveSupport::TimeZone.country_zones(country_code) 获取另一个国家的时区列表,或使用 Regexp 选择您选择的时区。

最后,此方法支持 :default 选项,该选项会在对象的时区为 nil 时选择一个默认的 ActiveSupport::TimeZone

time_zone_select(:user, :time_zone, nil, include_blank: true)

time_zone_select(:user, :time_zone, nil, default: "Pacific Time (US & Canada)")

time_zone_select(:user, :time_zone, ActiveSupport::TimeZone.us_zones, default: "Pacific Time (US & Canada)")

time_zone_select(:user, :time_zone, [ ActiveSupport::TimeZone["Alaska"], ActiveSupport::TimeZone["Hawaii"] ])

time_zone_select(:user, :time_zone, /Australia/)

time_zone_select(:user, :time_zone, ActiveSupport::TimeZone.all.sort, model: ActiveSupport::TimeZone)
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 292
def time_zone_select(object, method, priority_zones = nil, options = {}, html_options = {})
  Tags::TimeZoneSelect.new(object, method, self, priority_zones, options, html_options).render
end

weekday_options_for_select(selected = nil, index_as_value: false, day_format: :day_names, beginning_of_week: Date.beginning_of_week)

返回一个表示一周中各天的选项标签的字符串。

选项

  • :index_as_value - 默认为 false,设置为 true 以使用 I18n.translate("date.day_names") 中的索引作为值。默认情况下,星期日始终为 0。

  • :day_format - 用于一周中各天选项的数组的 I18n 键。默认为 :day_names,设置为 :abbr_day_names 以获取缩写。

  • :beginning_of_week - 默认为 Date.beginning_of_week

注意:只返回选项标签,您必须将此调用包装在常规 HTML select 标签中。

# File actionview/lib/action_view/helpers/form_options_helper.rb, line 611
def weekday_options_for_select(selected = nil, index_as_value: false, day_format: :day_names, beginning_of_week: Date.beginning_of_week)
  day_names = I18n.translate("date.#{day_format}")
  day_names = day_names.map.with_index.to_a if index_as_value
  day_names = day_names.rotate(Date::DAYS_INTO_WEEK.fetch(beginning_of_week))

  options_for_select(day_names, selected)
end

weekday_select(object, method, options = {}, html_options = {}, &block)

为给定的对象和方法返回 select 和 option 标签,使用 weekday_options_for_select 生成选项标签列表。

# File actionview/lib/action_view/helpers/form_options_helper.rb, line 298
def weekday_select(object, method, options = {}, html_options = {}, &block)
  Tags::WeekdaySelect.new(object, method, self, options, html_options, &block).render
end