【Rails】ViewHelperのselectボックスのグループ化について

スポンサーリンク

View Helper でセレクトボックスに optgroup タグを使用したグループ化をする例です。

grouped_collection_selectメソッド

grouped_collection_select メソッドの基本構文は以下の通りです。

grouped_collection_select(オブジェクト名, プロパティ名, オブジェクトの配列, optionタグ取得メソッド, optgroupタグのラベル, optionタグのvalue項目, optionタグのテキスト項目 [, 動作オプション [, オプション]])

grouped_collection_select は optgroup タグを利用して選択肢をグループ化する、タグの階層構造を生成するためのビューヘルパーです。 使用するにはモデルの  アソシエーション を定義します。以下の例では Publisher と Book を 1:n の関係で定義しました。

class Publisher < ActiveRecord::Base
  has_many :books
end

class Book < ActiveRecord::Base
  belongs_to :publisher
end

この場合グループの元になるオブジェクトが Publisher となり、配下の option タグを取得するためのメソッドにbooksを指定します。これで各 Publisher に紐づく Book オブジェクトの配列が取得されます。 その他のオプションに関しては  コチラ 参照。

= grouped_collection_select :review, :book_id, Publisher.all, :books, :name, :id, :name
<select name="review[book_id]" id="review_book_id">
  <optgroup label="O'Reilly Japan, Inc.">
    <option value="1">ゼロから作るDeep Learning</option>
    <option value="2">入門 Python 3</option>
    ...
  </optgroup>
  <optgroup label="Gihyo inc.">
    <option value="6">パーフェクトRuby</option>
    <option value="7">パーフェクト Ruby on Rails</option>
    ...
  </optgroup>
</select>

form_forブロック配下の場合はオブジェクト名の:reviewは省略してください。

= f.grouped_collection_select :book_id, Publisher.all, :books, :name, :id, :name

 grouped_collection_select - リファレンス - - Railsドキュメント
 grouped_collection_select (ActionView::Helpers::FormOptionsHelper) - APIdock

option_groups_from_collection_for_selectメソッド

option_groups_from_collection_for_select メソッドの基本構文は以下の通りです。

option_groups_from_collection_for_select(オブジェクトの配列, optionタグ取得メソッド, optgroupタグのlabel属性, optionタグのvalue項目, optionタグのテキスト項目 [, selected / disabled])

引数には grouped_collection_select メソッドと同様にオブジェクトの配列を指定します。grouped_collection_select メソッドの内部ではこのメソッドが使用されているため同じ挙動になります。

irb(main):001:0> helper.option_groups_from_collection_for_select(Publisher.all, :books, :name, :id, :name)
  Publisher Load (0.6ms)  SELECT "publishers".* FROM "publishers"
  Book Load (0.2ms)  SELECT "books".* FROM "books" WHERE "books"."publisher_id" = ?  [["publisher_id", 1]]
  Book Load (0.1ms)  SELECT "books".* FROM "books" WHERE "books"."publisher_id" = ?  [["publisher_id", 2]]
=> "<optgroup label=\"O&#39;Reilly Japan, Inc.\"><option value=\"1\">ゼロから作るDeep Learning</option>\n<option value=\"2\">入門 Python 3</option>\n<option value=\"3\">Pythonによるデータ分析入門</option>\n<option value=\"4\">初めてのPython</option>\n<option value=\"5\">実践 機械学習システム</option></optgroup><optgroup label=\"Gihyo inc.\"><option value=\"6\">パーフェクトRuby</option>\n<option value=\"7\">パーフェクト Ruby on Rails</option>\n<option value=\"8\">パーフェクトJava</option>\n<option value=\"9\">パーフェクトJavaScript</option>\n<option value=\"10\">パーフェクトPython</option></optgroup>"

 options_groups_from_collection_for_select - リファレンス - - Railsドキュメント
 option_groups_from_collection_for_select (ActionView::Helpers::FormOptionsHelper) - APIdock

grouped_options_for_selectメソッド

grouped_options_for_select メソッドの基本構文は以下の通りです。

grouped_options_for_select(タグの配列 or ハッシュ [, デフォルトの選択値 [, 動作オプション]])

引数には select や options_for_select メソッドと同様にタグの配列かハッシュを指定します。ただし、optgroupタグのラベルに使用する文字列を追加している必要があります。

# 配列の例
[["O'Reilly Japan, Inc.", [["ゼロから作るDeep Learning", 1], ["入門 Python 3", 2], ...]], ["Gihyo inc.", [["パーフェクトRuby", 6], ["パーフェクト Ruby on Rails", 7], ...]]]
# ハッシュの例
{"O'Reilly Japan, Inc.": [["ゼロから作るDeep Learning", 1], ["入門 Python 3", 2], ...]], "Gihyo inc.": [["パーフェクトRuby", 6], ["パーフェクト Ruby on Rails", 7], ...]]}

デフォルトの選択値はタグの value 属性の値を指定してください。動作オプションには以下の 2 種類が使用できます。ここのソースを見ると日本語ドキュメントに書かれてる内容と少し違いました。

動作オプション 概要
prompt プロパティに値が設定されていない時に指定したオプションを先頭に追加する。
divider optgroupタグのラベルの文字列を指定する。
irb(main):001:0> helper.grouped_options_for_select(Publisher.all.map{|p| [p.name, p.books.map{|b| [b.name, b.id]}]}, 1, { prompt: "選択してください" })
  Publisher Load (0.3ms)  SELECT "publishers".* FROM "publishers"
  Book Load (0.1ms)  SELECT "books".* FROM "books" WHERE "books"."publisher_id" = ?  [["publisher_id", 1]]
  Book Load (0.1ms)  SELECT "books".* FROM "books" WHERE "books"."publisher_id" = ?  [["publisher_id", 2]]
=> "<option value=\"\">選択してください</option><optgroup label=\"O&#39;Reilly Japan, Inc.\"><option selected=\"selected\" value=\"1\">ゼロから作るDeep Learning</option>\n<option value=\"2\">入門 Python 3</option>\n<option value=\"3\">Pythonによるデータ分析入門</option>\n<option value=\"4\">初めてのPython</option>\n<option value=\"5\">実践 機械学習システム</option></optgroup><optgroup label=\"Gihyo inc.\"><option value=\"6\">パーフェクトRuby</option>\n<option value=\"7\">パーフェクト Ruby on Rails</option>\n<option value=\"8\">パーフェクトJava</option>\n<option value=\"9\">パーフェクトJavaScript</option>\n<option value=\"10\">パーフェクトPython</option></optgroup>"

divider オプションを使用する場合は上記で使用するような配列とハッシュのデータから optgroup タグのラベル用データを削除した状態にします。

irb(main):001:0> ary = [[["ゼロから作るDeep Learning", 1], ["入門 Python 3", 2], ...], [["パーフェクトRuby", 6], ["パーフェクト Ruby on Rails", 7], ...]]
irb(main):002:0> helper.grouped_options_for_select(ary, "", { divider: "----------" })
=> "<optgroup label=\"----------\"><option value=\"1\">ゼロから作るDeep Learning</option>\n<option value=\"2\">入門 Python 3</option></optgroup><optgroup label=\"----------\"><option value=\"6\">パーフェクトRuby</option>\n<option value=\"7\">パーフェクト Ruby on Rails</option></optgroup>"

 grouped_options_for_select - リファレンス - - Railsドキュメント
 grouped_options_for_select (ActionView::Helpers::FormOptionsHelper) - APIdock

 rails/form_options_helper.rb at master · rails/rails · GitHub
 rails/grouped_collection_select.rb at master · rails/rails · GitHub