【Rails】select_tagを使って表示内容を変える
こんにちは、マリンです。
今回はselect_tag
を使ってページの表示内容を変える方法を書こうと思います。
概要
select_tag
で項目を選択し、項目に合わせてページの内容を変える
この時、
- HTTPリクエストはGET
- 「項目.id」を使って関連付けされた「内容」を持ってくる
submit
ボタンなしで切り替えを実現
こんな感じです。
なお、今回はクラスを選択すると生徒一覧が出てくる感じにしようと思います。
View
まずはviews
から。
<%= form_tag classes_path, method: :get do %> <%= select_tag 'classes', options_for_select(class_choices, @class_id), id: 'classes' %> <% end %> <% @students.each do |student| %> <%= student.name %> <% end %> <script> this.class_names.select(); </script>
前3行がセレクトで、中3行が生徒一覧を表示する部分、後3行がJSの呼び出しです。
JSについては最後に記述します。
セレクト部分
<%= form_tag classes_path, method: :get do %> <% end %>
コントローラにselect_tag
の情報を送るためにform_tag
で囲みます。
新規作成とかのページではないのでget
のアクションを使っています。
そのためmethod: :get
を指定してください。
<%= select_tag 'class_id', options_for_select(class_choices, @class_id), id: 'classes' %>
第一引数のclass_id
は、後ほどコントローラにこのセレクトタグの情報を渡す時に使う名前です。
第二引数には選択肢の文字列を指定しますが、
今回はoptions_for_select
を使っています。
このメソッドは、配列などを使って選択肢を生成してくれるメソッドです。
この引数には、helper
にクラス名とid
をとってくるメソッドを定義し、
それを使うことにします。
def class_choices ClassName.all.map{|class_name| [class_name.name, class_name.id]} end
@class_id
は、デフォルトでは選択後に表示名が最初に戻ってしまうので、
それを選んだ項目そそのまま表示させるためのものです。
こちらはコントローラに定義します。
id: 'classes'
は、後ほどJavaScriptに書く、
項目を選択するだけでデータを送れるようにするための処理で使います。
生徒表示一覧部分
<% @students.each do |student| %> <%= student.name %> <% end %>
対して説明はいらないと思いますが、
コントローラで@students
を定義し、
それを元に生徒の名前を羅列しています。
Controllers
次はControllers
です。
def classes # select_tagのデフォルト値に使用 class_first = ClassName.find(1) # select_tagから現在選択されているクラスのid取得 # 未選択時はデフォルトのclass_first @class_id = params[class_id] || class_first # クラスに属する生徒を取得 @students = Student.where(class_id: @class_id) end
@class_id
は未選択時にデフォルトで何を入れるか明示してあげないと、
「IDないんですけど?」と怒られてしまうのできちんと指定してあげましょう。
このid
をセットするところで、select_tag
に付けた名前が使われます。
「viewにあるclass_id
って名前のとこの値をとってきてね。」
という感じです。
最後に、とってきたクラスのid
を元に
関連付けられた生徒の名前を取得し、
これを使って表示をします。
JavaScripts
最後にプラスαで、サブミットボタンを付けなくても中身が切り替わるよう、
coffeeファイルを記述します。
これがないと、いちいちボタンを作って、それを押さないと切り替わりません。
class ClassNamesController select: -> $('#classes).on 'change' () -> $(@).parents('form').submit() return this.class_names = new ClassNamesController
言わずと知れたCoffeeScriptです。
コンストラクタ呼び出しを使っています。(new~
の部分)
これの呼び出しが、最初のviews
に記述した
<script> this.class_names.select(); <script>
です。こうやってメソッドを呼び出すことができるようになるんですね。
ここの部分はいまいち理解仕切れていないので、
参考にさせていただいた記事をご紹介するに留めておきます。
関数の中身です。
$('#classes').on 'change' () -> $(@).parents('form').submit()
「id="classes"
が変更されたら
これ(@=this)の親のform
を送信する。」
という内容ですね。
JS系は完全に勉強不足なので、自滅する前にここでやめておきます。
まとめ
今までselect_tag
はform
の一部としてしか使ったことがなかったですが、
このような使い方もよく見かけるのでとても良い勉強になりました。
ユーザービリティなども考えると、このJSのコードもいろいろなケースで
使えそうだなと思います。
余談ですが、今回この記事を書くにあたって自分でサンプルを作ってやってみましたが、
仕事と同じようにやってもやはりうまくいかずそれでまた一つ勉強できたりしたので、
手を動かすことの大切さを改めて実感しました。