Web Marina

日々の業務や勉強などで得た知識をアウトプットしていきます。

【Rails】select_tagを使って表示内容を変える

f:id:song-of-life1352607:20170220105406j:plain

こんにちは、マリンです。

今回はselect_tagを使ってページの表示内容を変える方法を書こうと思います。



概要

select_tagで項目を選択し、項目に合わせてページの内容を変える

この時、

  1. HTTPリクエストはGET
  2. 「項目.id」を使って関連付けされた「内容」を持ってくる
  3. 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>

です。こうやってメソッドを呼び出すことができるようになるんですね。

ここの部分はいまいち理解仕切れていないので、

参考にさせていただいた記事をご紹介するに留めておきます。

JS: new 呼び出しについて理解する - Qiita

クラス - JavaScript | MDN




関数の中身です。

$('#classes').on 'change' () ->
    $(@).parents('form').submit() 

id="classes"が変更されたら

これ(@=this)の親のformを送信する。」

という内容ですね。

JS系は完全に勉強不足なので、自滅する前にここでやめておきます。




まとめ

今までselect_tagformの一部としてしか使ったことがなかったですが、

このような使い方もよく見かけるのでとても良い勉強になりました。

ユーザービリティなども考えると、このJSのコードもいろいろなケースで

使えそうだなと思います。

余談ですが、今回この記事を書くにあたって自分でサンプルを作ってやってみましたが、

仕事と同じようにやってもやはりうまくいかずそれでまた一つ勉強できたりしたので、

手を動かすことの大切さを改めて実感しました。