************** コントローラ ************** ==================== コントローラを作る ==================== 学部の表示をするコントローラを作ってみる。 * ``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`` も出来る。 ========================= Railsの処理の流れ大図解 ========================= .. image:: controller.png コントローラが要求を受け付け、モデルとビューの間に立って処理を進める。要するに、モデルにもビューにも入らないところは全部コントローラに押し付けられる。 ルーティング HTTPリクエストに対して、どのコントローラのどのメソッドが呼び出されるかという対応関係をルーティングと言う。 上の例だと、ブラウザで http://localhost:3000/faculties/show にアクセスすると、 ``faculties`` コントローラの ``show`` メソッドが呼び出される。 レンダリング コントローラがビューを使ってレスポンスを作り出すことをレンダリングと言う。コントローラのメソッドの中で特に指定しなければ、コントローラ名とメソッド名から決まるERBファイルが自動的に使われる。 上の例だと、 ``faculties`` コントローラの ``show`` メソッドには何も書いていないので、 http://localhost:3000/faculties/show にアクセスすると、 ``app/views/faculties/show.html.erb`` を使ってレンダリングする。 ========================== コントローラの中身を書く ========================== 学部ごとに、学部名と学生リストを表示するようにしよう。 * コントローラはリクエストを解析してモデルから必要なデータを検索し、それをインスタンス変数に記憶する。 * ビューでは、そのインスタンス変数を使って表示を行う。 今は、ちょっと学部の指定は置いといて、常に総合政策学部のデータを取ってくることにする。 ``app/controllers/faculties_controller.rb`` は次のように書く。 .. code-block:: ruby class FacultiesController < ApplicationController def show @faculty = Faculty.find(1) end end これを表示するためのビュー ``app/views/faculties/show.html.erb`` は次のように書く。 .. code-block:: erb

Faculties#show

<%= @faculty.name %>

================== パラメータの指定 ================== このままでは環境情報学部が表示できないので、リクエストのURLによって学部を指定するようにしよう。 * URLのクエリ文字列(最後に ``?hoge=xxx`` の形で付いているやつ)で指定された名前と値は、Rubyのハッシュに変換され、 ``params`` という変数に格納される。 例えば http://localhost:3000/faculties/show?id=2 でアクセスすると、 ``show`` メソッドの中では ``params[:id]`` の値が2になる。 ``app/controllers/faculties_controller.rb`` は次のように書き直す。 .. code-block:: ruby class FacultiesController < ApplicationController def show @faculty = Faculty.find(params[:id]) end end .. admonition:: 課題15 :class: exercise 学部の表示ページで、その学部に属する学生の番号と名前を表示するようにせよ。 1. コントローラで学生の配列を ``@students`` という変数に記憶する。 2. ビューでは ``<% @students.each do |s| %> ... <% end %>`` の形で各学生のデータを順次表示する。 提出は、 ``app/controllers/faculties_controller.rb`` と ``app/views/faculties/show.html.erb`` をアップロード。 :ref:`【解答例】 ` ==================== ルーティングの指定 ==================== * 参考資料: `Railsのルーティング - RailsGuides `_ ブラウザからのリクエストをどのコントローラのどのメソッドが引き受けるかは ``config/routes.rb`` で指定する。 * 基本的には、各行にHTTPリクエストのメソッド(HTTP Verb)とURLのパターンが書いてある。 * 上から順に見ていって最初にマッチしたところの指示に従う。 個別のルーティング ------------------ 学部のコントローラーは ``rails generate controller`` で作ったので、 ``config/routes.rb`` には次の行が自動的に追加されている。 .. code-block:: ruby get 'faculties/show' * GETリクエストで http://localhost:3000/faculties/show というURLの時にマッチする。 * 本当は、この後に呼び出すべきコントローラとメソッドの指定を書くが、何も書かないとURLから勝手に判断する。この場合は ``FacultiesController`` の ``show`` メソッドが呼ばれる。 パラメータを含むルーティング ---------------------------- このルーティングでは、「どの学部か」という指定はURLの最後にクエリ文字列で ``?id=2`` とか書く必要がある。 * クエリ文字列は、長くなってうざい。 パス名の一部に直接パラメータを書くことができる。例えば、2番めの学部の情報を表示するには http://localhost:3000/faculties/2 と書ける。 .. code-block:: ruby get 'faculties/:id', to: 'faculties#show' * ルーティングの指定で、URLの中に ``:`` (コロン)で始まる名前を書くと、その部分がパラメータになる。 * ``:id`` に対応する部分が ``params[:id]`` に格納されてメソッドに渡される。 * URLが「コントローラ名/メソッド名」という形ではないので、コントローラ名とメソッド名の指定が必要。第二引数はハッシュで、キー ``to`` に対する値がコントローラ名とメソッド名を ``#`` でつないだ文字列。 リソースのルーティング ---------------------- 学生のコントローラは ``rails generate scaffold`` で作った。 * ``app/controllers/student_controller.rb`` が出来ている。 * ``index``, ``create``, ``new``, ``edit``, ``show``, ``update``, ``destroy`` というメソッドが自動的に用意される。 このようにCRUD操作(作成、編集、表示、削除など)が一通りできるものをリソースと言う。 これに対するルーティングは、操作ごとに書くのは面倒なので ``config/routes.rb`` に ``resources :students`` と一行書けば自動的に行われる。 ルーティングの確認 ------------------ 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 はコントローラ名とメソッド名を ``#`` でつなげたもの。 操作を限定したリソースルーティング ---------------------------------- 学部は個別ルーティングになっているが、リソースにするとヘルパーメソッド( ``faculty_path`` など)が使えたりして便利。しかし、 ``index`` や ``create`` といった操作は用意していないので、使える操作を限定しないといけない。 ``config/routes.rb`` の ``get 'faculties/:id'`` のところを次のように書き換える。 .. code-block:: ruby resources :faculties, only: [ :show ] * ``only:`` の後に、このリソースで使える操作( ``faculties`` コントローラのメソッド名)をシンボルの配列で書く。 * 操作は一般に複数個あるので、1個だけでも配列で指定する。 ============== 今日のまとめ ============== .. admonition:: 課題16 :class: exercise 前々回の課題で作った科目のモデル ``Course`` について、コントローラとビューを作成せよ。ただし、URLと操作は次のようにする。 * http://localhost:3000/courses で科目一覧と各科目の詳細ページへのリンクを表示 * http://localhost:3000/courses/1 で1番の科目の詳細を表示(科目名と単位数。必修科目の場合はその旨を表示。) 提出は、科目のコントローラ、科目一覧のERBファイル、科目詳細のERBファイル、 ``config/routes.rb`` をアップロード。 :ref:`【解答例】 ` .. admonition:: 課題17 :class: exercise 最終課題のアプリケーションについて、モデルとビューがどうなるか考えよ。 1. 表示したい画面の構成を考え、絵を描いてみよ。 2. データベースに記録するデータには何があるか、表の項目を列挙してみよ。 :ref:`【解答例】 ` `ここまでのソースコードはこちら `_ `課題16実行後 `_