【Rails】完全理解 formでセレクトボックスをつくるselectの使い方

rails

こんにちは。菜笑なえです。

今回はRailsでformのセレクトボックスをつくるときに使う、select の使い方についての解説です。

完成コード

<%= form_with model: @post, url: posts_path, do |form| %>
  <%= form.select :user_id, [['太郎', 1], ['二郎', 2]], { include_blank: true, selected: 1 }, { id: "user_id", class: "user_class" } %>
<% end %>

form_with を使ってますが、form_for の方も同じように書けます。

selectの使い方解説

f.select( プロパティ名, タグの情報, {オプション}, {HTMLオプション} )

それぞれが表しているものは以下の通りです。

  • プロパティ名 : カラム名 (下記に補足あり)
  • タグの情報 : セレクトボックス表示に使うデータの配列 or ハッシュ
  • オプション : セレクトボックスのオプション(include_blank, selectedなど)
  • HTMLオプション : HTMLのオプション (id, classなど)

もう少し具体的に見ていきます。

プロパティ名

まず、ちょっと補足です。

form_for ではプロパティ名 = カラム名でしたが、
form_with ではカラム名以外の好きな名前が指定出来ます。

要は「コントローラで、どんな名前として値を受け取りたいか?」という名前を指定しています。

コントローラでのデータの受け取り方。

params[:post][:user_id]

タグの情報

こちらは、セレクトボックス の表示に使うデータです。
つまり、optionタグに設定されるデータです。

必ず配列か、ハッシュを指定します。

# 配列
[[ 選択肢の表示名1, 実際に送信されるデータ1 ], [ 選択肢の表示名1, 実際に送信されるデータ2 ]]

# ハッシュ
{ "選択肢の表示名1" => "実際に送信されるデータ1", "選択肢の表示名1" => "実際に送信されるデータ2" }

今回の場合だと、選択肢に表示されるものは「太郎, 二郎」で、コントローラに送られるデータは「1, 2」となります。

オプション, HTMLのオプション

その名の通りセレクトボックスのオプション設定です。

ただオプションを設定する場所は、2箇所あります。

{ include_blank: true, selected: 1 }, { id: "user_id", class: "user_class" }

=> {オプション}, {HTMLオプション}

前者が通常、オプションと呼ばれるものです。
以下のようなものが代表的です。

  • include_blank : 先頭を空の選択肢にする
  • selected : デフォルトで選択しておきたい値を設定

後者はHTMLオプションと呼ばれます。
こちらはselectタグにid, classを指定したいときに使用します。

  • id : selectタグのid
  • class : selectタグのclass

このHTMLオプションを使う際には注意点があります。
必ず通常のオプションを設定しない場合でも空のカッコ{},をオプション部分に設定してください。
この空のカッコがないと、HTMLオプションが無視されてしまうので、id/classを設定したのに効いていない!ということになってしまいます。

HTMLオプション NG例

<%= form.select :user_id, [['太郎', 1], ['二郎', 2]], { id: "user_id", class: "user_class" } %>

HTMLオプション OK例

<%= form.select :user_id, [['太郎', 1], ['二郎', 2]], {}, { id: "user_id", class: "user_class" } %>

環境

Rails 5.2

おわりに

以上でセレクトボックスの基本的な使い方は完全理解できたのではないかと思います。

オプションの設定ミスで、id/classが効かないというのはよくあると思うので、気をつけていきましょう!

最初のころはform系のものって、コピペでなんとなく使うだけだと思うんですが(自分もそうでした)、少しずつ意味を理解しながら使えるようになれれば良いかなと思います。

SNS

Twitter:@nae310_
Instagram:310nae