跳到內容 跳到搜尋

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 關聯物件的下拉式選單標籤。

    範例,使用 @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 選取相關聯的 Author)

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

陷阱

當未選取任何核取方塊集合時,大多數網路瀏覽器將不會傳送任何值。

例如,如果我們有一個具有 category_ids 欄位的 User 模型,並且我們的更新動作中有以下程式碼

@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 選取相關聯的 Author)

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 規範說明,當未在選項按鈕集合中選取任何內容時,網路瀏覽器不會將任何值傳送到伺服器。不幸的是,這引入了一個陷阱:如果 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,則在 options 雜湊中未包含 :prompt:include_blank 的情況下,不會選取任何項目。

: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 選取相關聯的 Author)

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,則在 options 雜湊中未包含 :prompt:include_blank 的情況下,不會選取任何項目。

參數

  • object - 要用於下拉式選單標籤的類別實體

  • method - 對應於下拉式選單標籤的 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)

接受一個容器(雜湊、陣列、可列舉物件、您的類型),並返回一個 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 標籤,您必須將此呼叫包裝在常規的 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)

返回一個 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(一個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 標籤和一系列包含的 option 標籤。物件目前持有的選項將被選中,前提是該物件可用。

choices 參數有兩種可能的格式,對應於其他輔助方法的輸出

  • 平面集合(請參閱 options_for_select)。

  • 巢狀集合(請參閱 grouped_options_for_select)。

範例,使用 @post.person_id => 2

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

會變成

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

這可以用於以標準方式提供一組預設選項:在渲染建立表單之前,會將一個新的模型實例分配給預設選項並綁定到 @model_name。通常此模型不會儲存到資料庫中。相反,當收到建立請求時,會建立第二個模型物件。這允許使用者多次提交表單頁面,並產生建立多個記錄的預期結果。此外,這允許使用單個局部來為編輯和建立表單生成表單輸入。

預設情況下,post.person_id 是選定的選項。指定 selected: value 使用不同的選項,或 selected: nil 保持所有選項未選中。同樣,您可以通過指定 :disabled 選項來指定要在 option 標籤中停用的值。這可以是單個值或要停用的值的陣列。

可以將一個區塊傳遞給 select來自定義 option 標籤的渲染方式。這在 option 標籤具有複雜屬性時非常有用。

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

陷阱

HTML 規範指出,當將 multiple 參數傳遞給 select 並取消選中所有選項時,網路瀏覽器不會向伺服器發送任何值。不幸的是,這引入了一個陷阱:如果 User 模型具有許多 roles 並且具有 role_ids 存取器,並且在編輯使用者角色的表單中,使用者從 role_ids 多選框中取消選中所有角色,則不會發送 role_ids 參數。因此,任何像

@user.update(params[:user])

這樣的大量分配成語都不會更新角色。

為了防止這種情況,輔助方法會在每個多選之前生成一個輔助隱藏欄位。隱藏欄位與多選的名稱相同,且值為空。

注意: 用戶端要么只發送隱藏欄位(表示取消選中的多選框),要么發送兩個欄位。這表示結果陣列始終包含一個空字串。

如果您不希望輔助方法產生此隱藏欄位,您可以指定 include_hidden: false 選項。

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

返回一個字串,其中包含世界上幾乎所有時區的 option 標籤。提供一個 ActiveSupport::TimeZone 名稱作為 selected,將其標記為選定的 option 標籤。您還可以提供一個 ActiveSupport::TimeZone 物件陣列作為 priority_zones,以便它們列在(長)列表的其餘部分之上。(您可以使用 ActiveSupport::TimeZone.us_zones 作為獲取美國時區列表的便捷方法,或使用 Regexp 選擇您想要的時區)

selected 參數必須是 nil 或命名 ActiveSupport::TimeZone 的字串。

預設情況下,modelActiveSupport::TimeZone 常數(可以在 Active Record 中作為值物件獲取)。 model 參數必須回應 all 並返回表示時區的物件陣列;每個物件都必須回應 name。如果給定 Regexp,它將嘗試使用 match? 方法匹配時區。

注意:只會返回 option 標籤,您必須將此呼叫包裝在常規的 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 = {})

針對給定的物件和方法,使用 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

注意:只會返回 option 標籤,您必須將此呼叫包裝在常規的 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)

針對給定的物件和方法,使用 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