9. コントローラ

9.1. コントローラを作る

学部の表示をするコントローラを作ってみる。

  • rails generate scaffold がモデル・ビューと一緒に作ってくれるコントローラには、既に表示・編集・追加などの操作が入っている。

  • rails generate controller は、必要なデータ操作を指定してコントローラを作る。

学部のデータは変更する必要がないので(学部の新設や廃止をするなら話は別だが)、学部の情報を表示する show という操作だけを作ることにする。

% rails generate controller faculties show
  • faculties がコントローラの名前。たまたまモデルと同じ名前(複数形)にしたが、モデルとは関係ない名前でもよい。

  • show が操作の名前。操作が複数あるときは空白で区切って並べて書く。

これで app/controllers/faculties_controller.rb というファイルが出来て、 FacultiesController というクラスに show というメソッドが用意される。ただし中身は空。

それだけでなく、対応するビューのERBファイル app/views/faculties/show.html.erb も出来る。

9.2. Railsの処理の流れ大図解

_images/controller.png

コントローラが要求を受け付け、モデルとビューの間に立って処理を進める。要するに、モデルにもビューにも入らないところは全部コントローラに押し付けられる。

ルーティング

HTTPリクエストに対して、どのコントローラのどのメソッドが呼び出されるかという対応関係をルーティングと言う。

上の例だと、ブラウザで http://localhost:3000/faculties/show にアクセスすると、 faculties コントローラの show メソッドが呼び出される。

レンダリング

コントローラがビューを使ってレスポンスを作り出すことをレンダリングと言う。コントローラのメソッドの中で特に指定しなければ、コントローラ名とメソッド名から決まるERBファイルが自動的に使われる。

上の例だと、 faculties コントローラの show メソッドには何も書いていないので、 http://localhost:3000/faculties/show にアクセスすると、 app/views/faculties/show.html.erb を使ってレンダリングする。

9.3. コントローラの中身を書く

学部ごとに、学部名と学生リストを表示するようにしよう。

  • コントローラはリクエストを解析してモデルから必要なデータを検索し、それをインスタンス変数に記憶する。

  • ビューでは、そのインスタンス変数を使って表示を行う。

今は、ちょっと学部の指定は置いといて、常に総合政策学部のデータを取ってくることにする。 app/controllers/faculties_controller.rb は次のように書く。

class FacultiesController < ApplicationController
  def show
    @faculty = Faculty.find(1)
  end
end

これを表示するためのビュー app/views/faculties/show.html.erb は次のように書く。

<h1>Faculties#show</h1>
<p><b><%= @faculty.name %></b></p>

9.4. パラメータの指定

このままでは環境情報学部が表示できないので、リクエストのURLによって学部を指定するようにしよう。

  • URLのクエリ文字列(最後に ?hoge=xxx の形で付いているやつ)で指定された名前と値は、Rubyのハッシュに変換され、 params という変数に格納される。

例えば http://localhost:3000/faculties/show?id=2 でアクセスすると、 show メソッドの中では params[:id] の値が2になる。

app/controllers/faculties_controller.rb は次のように書き直す。

class FacultiesController < ApplicationController
  def show
    @faculty = Faculty.find(params[:id])
  end
end

課題15

学部の表示ページで、その学部に属する学生の番号と名前を表示するようにせよ。

  1. コントローラで学生の配列を @students という変数に記憶する。

  2. ビューでは <% @students.each do |s| %> ... <% end %> の形で各学生のデータを順次表示する。

提出は、 app/controllers/faculties_controller.rbapp/views/faculties/show.html.erb をアップロード。

【解答例】

9.5. ルーティングの指定

ブラウザからのリクエストをどのコントローラのどのメソッドが引き受けるかは config/routes.rb で指定する。

  • 基本的には、各行にHTTPリクエストのメソッド(HTTP Verb)とURLのパターンが書いてある。

  • 上から順に見ていって最初にマッチしたところの指示に従う。

9.5.1. 個別のルーティング

学部のコントローラーは rails generate controller で作ったので、 config/routes.rb には次の行が自動的に追加されている。

get 'faculties/show'
  • GETリクエストで http://localhost:3000/faculties/show というURLの時にマッチする。

  • 本当は、この後に呼び出すべきコントローラとメソッドの指定を書くが、何も書かないとURLから勝手に判断する。この場合は FacultiesControllershow メソッドが呼ばれる。

9.5.2. パラメータを含むルーティング

このルーティングでは、「どの学部か」という指定はURLの最後にクエリ文字列で ?id=2 とか書く必要がある。

  • クエリ文字列は、長くなってうざい。

パス名の一部に直接パラメータを書くことができる。例えば、2番めの学部の情報を表示するには http://localhost:3000/faculties/2 と書ける。

get 'faculties/:id', to: 'faculties#show'
  • ルーティングの指定で、URLの中に : (コロン)で始まる名前を書くと、その部分がパラメータになる。

    • :id に対応する部分が params[:id] に格納されてメソッドに渡される。

  • URLが「コントローラ名/メソッド名」という形ではないので、コントローラ名とメソッド名の指定が必要。第二引数はハッシュで、キー to に対する値がコントローラ名とメソッド名を # でつないだ文字列。

9.5.3. リソースのルーティング

学生のコントローラは rails generate scaffold で作った。

  • app/controllers/student_controller.rb が出来ている。

  • index, create, new, edit, show, update, destroy というメソッドが自動的に用意される。

このようにCRUD操作(作成、編集、表示、削除など)が一通りできるものをリソースと言う。

これに対するルーティングは、操作ごとに書くのは面倒なので config/routes.rbresources :students と一行書けば自動的に行われる。

9.5.4. ルーティングの確認

URLとメソッドの対応が見たい場合は、次のコマンドを実行する。

# rails routes -c students
      Prefix Verb   URI Pattern                  Controller#Action
    students GET    /students(.:format)          students#index
             POST   /students(.:format)          students#create
 new_student GET    /students/new(.:format)      students#new
edit_student GET    /students/:id/edit(.:format) students#edit
     student GET    /students/:id(.:format)      students#show
             PATCH  /students/:id(.:format)      students#update
             PUT    /students/:id(.:format)      students#update
             DELETE /students/:id(.:format)      students#destroy
  • -c オプションでコントローラを指定する。指定しないと全部出てくるが、大変見づらい。

  • Prefix はヘルパーメソッドの名前などに使われるもの。

  • Verb はHTTPメソッドのこと。普通はGET、フォーム送信の時はPOST。それ以外は特別に指定しないと使われない。

  • URI Pattern はURLのアプリケーション名より後の部分。 (.:format) はとりあえず無視してよい。

  • Controller#Action はコントローラ名とメソッド名を # でつなげたもの。

9.5.5. 操作を限定したリソースルーティング

学部は個別ルーティングになっているが、リソースにするとヘルパーメソッド( faculty_path など)が使えたりして便利。しかし、 indexcreate といった操作は用意していないので、使える操作を限定しないといけない。

config/routes.rbget 'faculties/:id' のところを次のように書き換える。

resources :faculties, only: [ :show ]
  • only: の後に、このリソースで使える操作( faculties コントローラのメソッド名)をシンボルの配列で書く。

  • 操作は一般に複数個あるので、1個だけでも配列で指定する。

9.6. 今日のまとめ

課題16

前々回の課題で作った科目のモデル Course について、コントローラとビューを作成せよ。ただし、URLと操作は次のようにする。

提出は、科目のコントローラ、科目一覧のERBファイル、科目詳細のERBファイル、 config/routes.rb をアップロード。

【解答例】

課題17

最終課題のアプリケーションについて、モデルとビューがどうなるか考えよ。

  1. 表示したい画面の構成を考え、絵を描いてみよ。

  2. データベースに記録するデータには何があるか、表の項目を列挙してみよ。

【解答例】

ここまでのソースコードはこちら

課題16実行後