2019-11-14に更新

【Rails】collection_selectを使いデータベースからプルダウンリストを作る

参考にしたサイト

はじめに

農作業の記録に使える作業日誌アプリを製作中です。
その日にやった作業の詳細をテキストエリアに入力する際に、
事前に作業ごとのテンプレートを制作しておいて、
プルダウンリストでそのテンプレートを呼び出せるような機能の実装を考えていました。

この部分をAjax処理にしたので、その実装のやり方を思い返しながらまとめておきたいと思ったのですが、
まずは前段としてcollection_selectの使い方を整理しておきます。

1.実装したいこと

その日にやった作業はWorkモデル、テンプレートは独立したTemplateモデルに格納されます。
プルダウンリストの作成はcollection_selectヘルパーメソッドを使用して、Templateモデルの一覧を取得し、テンプレートのnameカラムをリストに表示させます。
(この時点ではまだ特に選択したテンプレートの表示や保存は行われません。ただプルダウン上でテンプレートを選択するだけです)

このようなワーク入力画面で、「詳細」の下のプルダウンリストをクリックすると…

スクリーンショット 2019-11-13 18.36.51.png

2.テンプレートの名前リストが表示されるので、好きなのを選んで選択する。

スクリーンショット 2019-11-13 18.36.58.png

2.実装内容

該当するフォーム部分の上にプルダウンリストを以下のように記述しました。

views/works/form.html.erb

<label>詳細</label>
<%= collection_select(:template, :name, templates, :id, :name, {:include_blank => true}) %>
<%= form.text_area :body, :size => "40x10" %>

2行目のcollection_selectで、Templateモデルの一覧を取得し、テンプレートのnameカラムをリストに表示させています。

これはviews/works/new.html.erbとedit.html.erbのフォーム部分をパーシャルにしている状態です。そこの際に変数を受け渡ししてるので、@templatesというインスタンス変数だったのが、ローカル変数として渡されています。
(パーシャルにインスタンス変数は使わないのが基本と学んだ)

ちなみに該当するworksコントローラーのnewアクションの中身は以下のようになっています。

controllers/concerns/works_controller.rb

  def new
    @diary = Diary.find params[:diary_id]
    @work = @diary.works.build
    @templates = Template.all
  end

3.解説

collection_selectの引数がちょっと複雑。
参考リンク1がとっつきやすい感じで整理してくれているのですが、その中では

collection_select(オブジェクト名, プロパティ名, オブジェクトの配列, value属性の項目, テキストの項目 [, オプション])

と書かれています。僕の書いたコード

collection_select(:template, :name, templates, :id, :name, {:include_blank => true})

と照らし合わせてみると、

  • 第1引数 :template =オブジェクト名 
  • 第2引数 :name =プロパティ名
  • 第3引数 templates =オブジェクトの配列
  • 第4引数 :id =value属性の項目
  • 第5引数 :name =テキストの項目
  • 第6引数 {:include_blank => true} =オプション
     
     
    第1引数はオブジェクト名。
    ここではTemplateをとってきています。
    参考リンク2に少し詳しく書かれており、今回はform_withと関係なく独立しているのでこれで良いのですが、例えばform_withの中でf.collection_selectとかform.collection_selectみたいに使うケースでは、すでにオブジェクトを受け取っているのでここは省略しないとエラーになってしまうようなので注意が必要そうです。
     
     
    第2引数はプロパティ名。
    メソッドとか属性とも書かれていたりします。ここではオブジェクトの属性名を指定します。
    分かりづらいですね。これも参考リンク2で詳しく説明されているのを見てみると、どうやらここに指定したものがparamsで送る時のkeyになるようです。
    Templateの属性名(カラム名)、今回ではnameを指定することで、ドロップダウンリストを選択した時にparams[:name]で項目を取得できます。
    なんとなく分かるようで分からないもどかしい感じ。
     
     
    第3引数はオブジェクトの配列。
    これはイメージしやすいのですが、プルダウンリスト一覧にずらーっと並ぶものになります。
    今回はテンプレートの一覧から選ぶ形になるので、「テンプレートモデルに登録されているデータベース一覧を取得したもの」すなわちTemplate.allが配列となって入ります。コントローラーの方で@templates = Template.allを記述しているので、それが渡ってきています。 
     
     
    第4引数はバリュー属性の項目。
    これが正直よく分からず。HTMLの<select>タグで使う<option>タグのvalue属性に該当するようなのですが、もうちょっとこの辺の理解が必要そうです。
     
     
    第5引数はテキスト属性の項目。
    これもイメージしやすいですね。プルダウンリストの選択肢にどう表示させるかを、配列の属性(カラム)として指定します。今回はTemplateのnameを指定してあげることで、選択肢にはテンプレート名が一覧となって表示されます。
     
     
    第6引数はオプションとなっていますが、なくてもいけます。
    {:include_blank => true}で先頭に空白行を追加しています。これがなければテンプレートの1番目が初期値として選択されている感じでしょうか。
    他にも初期値を指定することができたり、今後javascriptを動かすのに必要なHTMLオプションもここに入ってきます。

MEMO

ちょっと理解が危うい部分があるのですが、
今後またこのプルダウンリストを実装するタイミングが近々あるので、復習しながら理解していきたいと思います。

ツイッターでシェア
みんなに共有、忘れないようにメモ

Massa

北海道でアプリ制作に取り組んでるノンプログラマな農夫。仕事や日常生活で感じる小さな不便を解消すべく趣味と実益を兼ねて遊んでます ■Python・GAS + LINE bot

Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

有料記事を販売できるようになりました!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?

コメント