プルダウンメニュー(select_tag)の中身をデータベースに用意する
プルダウンメニュー(select_tag)の選択肢を決め打ちでやらず、マスタとしてDB内のテーブルに用意する場合のやり方です。collection_select を使います。
ここでは例として、都道府県名を格納するために prefecture テーブルと Prefecture モデルを作成します。
|id |name | | 1|北海道 | | 2|青森県 | | 3|岩手県 | ...(以下省略)
このテーブルの中身をプルダウンメニューの選択肢として利用するには以下のように書きます。
<%= form_for @user do |f| %> <%= f.label :prefecture_id %> <%= f.collection_select :prefecture_id, Prefecture.all, :id, :name %> <%- end -%>
文法としてはこんな感じで、それぞれの引数の意味は以下の通りです。
<%= f.collection_select (1), (2), (3) , (4) [, オプション] %>
(1) | 属性名 | フォームの対象モデルの中の該当する属性名(ここでは User.prefecture_id) |
(2) | 配列データ | プルダウンメニューの選択肢に使用するデータ配列 各要素は連想配列やオブジェクトなど |
(3) | 値カラム名 | プルダウンメニューで値として扱うカラムの名前 |
(4) | 表示名カラム名 | プルダウンメニューで表示名として扱うカラムの名前 |
ちなみに同じことを select タグでやるとこんな感じでできます。
<%= f.select :prefecture_id, Prefecture.all.map{|pf| [pf.name, pf.id]} %>
あんまり変わらないやんって思った方、正解です(^^)
オプションあれこれ
プルダウンメニューの先頭に空白行を追加する(:include_blank オプション)
プルダウンメニューの選択肢の先頭に空白の選択肢を追加することができます。一旦どれかを選択しても、未選択の状態に戻せるということです。なお、空白行の value は空文字列が指定されます。
<%= f.collection_select :prefecture_id, Prefecture.all, :id, :name, :include_blank => true %>
include_blank オプションの値を true/false ではなく文字列にすると、その文字列が使用されます。
<%= f.collection_select :prefecture_id, Prefecture.all, :id, :name, :prompt => "選択を解除" %>
値が未設定の時にプロンプトを表示(:prompt オプション)
prompt オプションを使うと、プルダウンメニューが選択されていない時(=初期値が設定されなかったとき)に「選択して下さい」といった文字列の行が先頭に追加されます。
<%= f.collection_select :prefecture_id, Prefecture.all, :id, :name, :prompt => true %>
表示される文字列は I18n を使っている場合、ロケ―ルファイルで指定された文字列が使用されます。
ja: helpers: select: prompt: "選択してね♪"
promptオプションの値を true/false ではなく文字列にすると、それがプロンプトとして使用されます。
<%= f.collection_select :prefecture_id, Prefecture.all, :id, :name, :prompt => "好きなものを選んで" %>
include_blank オプションと prompt オプションはどちらも先頭行に追加しますが、動作がちょっとだけ違います。
:include_blank | 常に先頭行を追加 |
---|---|
:prompt | 選択行の指定がない時だけ先頭行を追加 |
デフォルトの選択を指定する(:selected オプション)
やりかたは通常の f.select と同じで
<%= f.collection_select :prefecture_id, Prefecture.all, :id, :name, :selected => 13 %>
と書けます。
が、あまりこのオプションはあまり使わないでしょう。
selected を指定しなくても、@user.prefecture_id に値が既に入っている場合は自動的にその値にセットされます。逆に selected を使うと、常に selected で指示されたものが選択されることになります。初期値として入れたい場合は、controller の new メソッド内で初期値を設定した方がいいでしょう。
class UserController < ApplicationController def new @user = User.new(:prefecture_id => 13) end end