もくじ
スポンサーリンク
MVCパターン
Ruby on Railsは、MVCパターンと呼ばれるアーキテクチャを採用しています。
MVCというのは、
- Model(モデル)
- View(ビュー)
- Controller(コントローラー)
の略で、ユーザーインタフェースをもつアプリケーションソフトウェアを実装するためのデザインパターンのことを言います。
と説明されてもよく分からん。という人に向けて書きます。長いです。
スポンサーリンク
コントローラーとは
コントローラーはまさにコントローラーです。司令塔です。
コントローラーの命令に従って、モデルとビューが働きます。コントローラーの命令無しでは何も動きません。
モデルとビューに命令を出すのがコントローラーの仕事です。
そういう意味では、コントローラーは意思決定をする上司みたいなものと言えます。
モデルとは
モデルとは、データを司る存在です。
コントローラーからの命令に従って、データベースから必要な情報を取り出してコントローラーにその情報を返したり、あるいは、コントローラーの命令に従って、データベースに情報を書き込んだり、書き換えたりします。
データベースを直接触れるのはモデルだけです。奥にこもって黙々と作業する職人さんみたいなイメージです。コントローラーの言うとおりに働きます。
ビューとは
ビューとは、デザイン及びユーザーインターフェースを司る存在です。
コントローラーから渡されたデータを使って、どういうhtmlページを表示するかをビューで定義します。
もちろん見た目だけの問題ではありません。入力フォームなどのユーザーが触れる部分を正しく機能するように設置するのもビューの仕事です。
ユーザーと直接やりとりするのはビューだけです。
ビューはお客さんに対応する窓口担当のような役割を持っています。笑顔でお客様に対応しながらも、背後から上司(コントローラー)にいろいろ命令されています。
ルーターとは
Railsでは、コントローラー、モデル、ビューとは別に、Router(ルーター)という重要な役割があります。
ルーターは、役割的にはコントローラーの一部と言えます。
webというのはクライアント側からのhttpリクエストに対するサーバー側からのレスポンス、その応酬で成り立っておりますが、ルーターがしているのは、そのhttpリクエストを読み取って、処理を振り分けるという役割です。
コントローラーが社長だとすると、ルーターはその秘書・取り次ぎ役みたいなものです。「社長、こんなリクエストが来ました」って。
MVCを実装してみる
抽象的な説明ではイメージはつかめても、いまいちピンと来ないと思うので具体的な話に移りましょう。
コントローラー、モデル、ビューは、それぞれファイルとして然るべきディレクトリに配置されます。
画面左のファイルツリーを確認してみてください。appディレクトリ下に、controllers、models、viewsと言う名前のディレクトリが既にあるのが分かると思います。
ディレクトリ名が複数形になっているように、コントローラー、モデル、ビューというのはそれぞれ一つずつではなく、普通は複数存在します。それらをまとめて置いておくのがcontrollers、models、viewsディレクトリです。
現状ではそれぞれのディレクトリの中身はデフォルト状態の必要最低限のものしかありません。これから、このアプリケーション独自のファイル(コントローラー、モデル、ビュー)を作成していきます。
作りたいページと情報
さて、これから電話帳アプリを作るわけですが、具体的にどんなものなのか説明しておきます。
メンバーごとに登録できる情報は、
- 名前
- よみがな
- 電話番号
これだけです。分かってるとは思いますが、全くもって実用的な代物じゃないのでそのつもりでお願いします。
日本語というのは不便なもので、五十音順にソートしようと思えば、必ずよみがなが要ります。
必要なページは、以下の3つです。
- 一覧ページ http://ドメイン/members
- 新規登録ページ http://ドメイン/members/new
- 編集ページ http://ドメイン/members/:id/edit
メンバーの一覧ページと、新たにメンバーを登録するページ、登録したメンバーの情報を編集するページです。
編集ページurlの、:idというのは、表示したい人のIDを意味しています。
例えば、IDが1の人の編集ページのurlは、
http://ドメイン/members/1/edit
となります。
編集ページというのは、誰か一人のデータを編集するページなので、その人ごとにページが存在することになります。つまり登録した人数分のページが必要です。リクエスト(url)の中にIDを含むことで、各々の編集ページを動的に表示します。
membersというのは言わばリソース名です。
電話帳アプリというのは、言い方を変えるとmembersリソースを管理する為のアプリだと言えます。membersリソースを管理する為に、上記の3つのページを用意するわけです。
ルーターでHTTPリクエストを捌く
上記のようにHTTPリクエスト(url)ごとに処理を分けるには、まずルーターを編集する必要があります。
/config/routes.rbが、ルーターと呼ばれるファイルです。開いて下さい。
ルーターがすることは、クライアントからのHTTPリクエストを読み取って、コントローラーへと取り次ぐという仕事です。
デフォルトでは、
1 2 3 | Rails.application.routes.draw do # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end |
↑このようにdoブロックの中身は英語でコメントが書いてあるだけで、空っぽです。
このdoブロックの中に、コントローラーへの取り次ぎのルールを書いていきます。
1 2 3 4 | Rails.application.routes.draw do resources :members # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end |
正しく書けたらcommand + sでroutes.rbを保存しましょう。
Cloud9ではcommand + sでファイルを上書き保存することができます。保存しない限り、プログラムには反映されません。
Cloud9では画面右上の方に設定ボタンがあり、そこで字下げの設定を変えることができます。
たったこれだけで、以下のHTTPリクエストに対応できるようになります。
1 2 3 4 5 6 7 8 | GET /members (一覧画面) POST /members GET /members/new (新規作成画面) GET /members/:id/edit (編集画面) GET /members/:id PATCH /members/:id PUT /members/:id DELETE /members/:id |
黄色のラインが入っているのが上記で説明した3つのページ(一覧画面、新規作成画面、編集画面)に当たります。
GET、POST、PATCH、PUT、DELETEというのはHTTPリクエストのメソッドのことです。
単純にwebページを閲覧する時に使われるメソッドはGETです。GETはサーバー上のファイルを読み込むメソッドです。
サーバー上のデータを書き換えたりする際のメソッドがPOST、PATCH、PUT、DELETEになります。
この辺は具体的に使い分ける処理を書くとよく分かってくると思うので、ここではサラッと行きます。
routes.rbのブロックの中に、resources :membersと書くことで、membersリソースに対する閲覧、編集、削除といったリクエストに一通り対応できる状態になるわけです。具体的な処理内容の定義はコントローラーで行います。
これで取り次ぎ役(ルーター)は、クライアントから上記のHTTPリクエストが来た場合に、正しく社長(コントローラー)へと取り次げるようになりました。
ルーターで設定した受け渡しルールのことをルーティングと言います。ルーティングはコンソールで以下のコマンドを打つことで確認することができます。
1 | $ rake routes |
コマンドを打つとコンソールに今現在設定されている全てのルーティングが一覧で表示されます。
1 2 3 4 5 6 7 8 9 | Prefix Verb URI Pattern Controller#Action members GET /members(.:format) members#index POST /members(.:format) members#create new_member GET /members/new(.:format) members#new edit_member GET /members/:id/edit(.:format) members#edit member GET /members/:id(.:format) members#show PATCH /members/:id(.:format) members#update PUT /members/:id(.:format) members#update DELETE /members/:id(.:format) members#destroy |
※初めは何が書いてあるのか良く分からないと思いますが、だんだん分かってきます。
コントローラーを作る
「社長、こんなリクエストが来ましたーーー!」と、ルーターが持ってきた客の要望に対して、どういう処理を行うか決定するのが社長(コントローラー)の仕事です。
では実際に、コントローラーを作ってみましょう。
前回、rails newコマンドでアプリケーションの土台を一気に作りましたが、同じようにコマンド操作でコントローラーを作ることができます。
コマンドを打つ前に、cdコマンドで、カレントディレクトリをphone-bookに変更しておきます。
1 | $ cd phone-book |
コマンド操作でアプリケーションに関する操作をする際はアプリケーションのルートディレクトリでコマンドを叩く必要があります。workspace自体のルートディレクトリではないので注意しましょう。
コントローラーは、リソースごとに名前を付けて作ります。
リソースと言うのはここでいうmembersのことです。現状ではルーターが取り次ぐのはmembersリソースに関するリクエストです。なのでここではmembersという名前のコントローラーを作ります。
コントローラー名は複数形で付けるのがRailsの規約です。
rails g controller コントローラー名
というコマンドで、その名前のコントローラーを作ることが出来ます。
コンソールに以下のコマンドを入力してエンターを押してください。
1 | $ rails g controller members |
これで以下の5つのファイルと1つの空ディレクトリが作られました。
1 2 3 4 5 6 | app/controllers/members_controller.rb app/views/members test/controllers/members_controller_test.rb app/helpers/members_helper.rb app/assets/javascripts/members.coffee app/assets/stylesheets/members.scss |
一番上のmembers_controller.rbというのがmembersコントローラーです。2番めのapp/views/membersというのは、membersビューを保存するためのディレクトリです。後で出てきます。
他のファイルはここでは触りません。
コマンド操作でコントローラー等を作るっていうのは、言ってみれば単にファイルやディレクトリを上記のように新規作成しているだけです。
自分で全てのファイルを一つ一つ新規作成しても構わないのですが、Railsではファイル名の命名規則があります。ファイルを置く場所(ディレクトリ)にもルールがあります。
決められたディレクトリに、命名規則に則ったファイルを置くというのがRailsでは重要です。ファイル名やディレクトリ構造こそがRailsシステムの根幹部分を支えています。
$ rails g contoroller members
というコマンド操作で、
members_controller.rb
というファイル名が出来上がったのを見れば分かるように、コントローラーファイルは、
コントローラー名_controller.rb
という命名規則に則っています。この名前のおかげで、このファイルはmembersのコントローラーだということが認識されます。
コマンド操作で作成すれば、そういったルールに則った形でファイルやディレクトリが作られます。細かい命名規則やそのファイルの配置場所(ディレクトリ)なんかを覚えずとも全て任せてしまえるわけです。
コントローラーを定義する
では出来上がったmembersコントローラーを見てみましょう。
/app/controllers/members_controller.rbを開いて下さい。
1 2 | class MembersController < ApplicationController end |
ご覧のように中身はまだ空っぽです。
class名がMembersControllerとなっていますが、これも命名規則に則って作られた名前です。
まずは、「一覧ページを見せてくれ」というリクエストに対応しましょう。
一覧ページを見せてくれというリクエストに対しては、indexというアクションが呼ばれます。
アクションというのは、コントローラーで定義するメソッドのことです。コントローラーでindexというメソッドを定義することで、ルーターからの取り次ぎに対応します。
1 2 3 4 5 | class MembersController < ApplicationController def index end end |
こうすることで、「membersの一覧画面を見せてくれ」というHTTPリクエストを受けると、membersコントローラーのindexメソッドが呼ばれる状態になったわけです。
このメソッドの定義部分にその対応を書きます。
ここでは一覧画面の表示機能を実装する前に、まずMVCの仕組み、および実装の仕方を簡単に理解する為に、「Hello」と表示するだけの画面を作ります。
1 2 3 4 5 | class MembersController < ApplicationController def index @message = "Hello" end end |
この@messageというのは、このクラスのインスタンス変数です。アクションメソッドの中でインスタンス変数に値を格納すると、ビューからもその値を参照することができます。
つまり、一覧画面を表示する為のビュー(窓口役)に、Helloという文字列を使って、ページを表示しなさい。と命令しているわけです。
その情報を使って、どういうページを表示するか決めるのはビューの仕事です。コントローラーがするのは、表示するべきデータを渡すことだけです。
この、ビューに何らかの値を渡すためのインスタンス変数のことを、テンプレート変数と呼びます。テンプレート変数に格納された値を使ってビューを定義します。
この分業制度がRailsの肝です。
このように、membersコントローラーのindexアクションによって、http://ドメイン/membersというページを表示する処理を行っているわけですが、rake routesコマンドで、ルーティングの一覧をもう一度見て下さい。
1 2 3 4 5 6 7 8 9 | Prefix Verb URI Pattern Controller#Action members GET /members(.:format) members#index POST /members(.:format) members#create new_member GET /members/new(.:format) members#new edit_member GET /members/:id/edit(.:format) members#edit member GET /members/:id(.:format) members#show PATCH /members/:id(.:format) members#update PUT /members/:id(.:format) members#update DELETE /members/:id(.:format) members#destroy |
2行目がhttp://ドメイン/membersを表示するリクエストに当たりますが、右端のController#Actionの項目がmembers#indexになっているのが分かると思います。
これは、/membersにGETリクエストを送ると、membersコントローラーのindexアクションが呼ばれることを示しています。
ビューを定義する
続いて一覧画面を表示するためのビューを作ります。
ビューはコマンド操作で作ることは出来ないので、普通に作ります。
※後で説明しますが、ここで言っているビューとはテンプレートファイルのことです。
ファイルツリーの/app/views/membersを右クリック→New Fileをクリックしてください。
ファイル名は、index.html.erbとします。
membersコントローラーのindexアクションで使われるビューのファイル名は、
/views/members/index.html.erb
にする必要があります。これもRailsの命名規則の1つです。
拡張子は.erbになっていますが、これはEmbedded Rubyの略で、htmlの中にRubyスクリプトを埋め込んだファイルのことです。
erbファイルを使って最終的にhtmlファイルを出力するので、.html.erbとなっています。
/view/membersにindex.html.erbというファイルが出来ました。これがmembersコントローラーのindexアクションで使われるビューです。
ではこのindex.html.erbを編集して、membersコントローラーの命令通り「Hello」という文字列を表示するようにします。ファイルを開いて下さい。
書くのはたった一行です。
1 | <p><%= @message %></p> |
<%= %>が、htmlの中にRubyスクリプトを埋め込むための表記です。
@messageというのは、コントローラーで定義したテンプレート変数です。コントローラーで定義したテンプレート変数はビューからも参照することが出来ます。
たったこれだけの表記で、コントローラーからの司令を受け取ることが出来るわけです。
Rubyのスクリプト表記には2種類あります。
<%= %>は、htmlとして出力する場合
<% %>は、評価するだけで出力しない場合
1 2 3 | <% price = 1000 result = price * 1.08 %> <p>税込み価格<%= result %>円</p> |
↓
1 | <p>税込み価格1080円</p> |
つまり、
1 | <p><%= @message %></p> |
というerbファイル内の表記は、サーバー上で、
1 | <p>Hello</p> |
というhtmlに変換されてからクライアント側へ送られることになります。
レイアウトテンプレート
上記では、index.html.erbのことをビューを呼びましたが、index.html.erb単体でビューの機能を果たすわけではありません。
index.html.erbは、あくまでそのページの一部分を表示するために使われるテンプレートファイルでしかありません。
ページ全体のhtmlを吐き出すファイルは、
/views/layoutsディレクトリにあるapplication.html.erbです。
このファイルはrails newコマンドで自動作成されたものです。開いてみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <!DOCTYPE html> <html> <head> <title>PhoneBook</title> <%= csrf_meta_tags %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> </head> <body> <%= yield %> </body> </html> |
デフォルト状態で、このように最低限webページの体裁が整う状態になっています。これがページ全体のhtmlの元となります。
この中で<%= yield %>という表記があると思います(12行目)。このyieldの部分に先程定義したテンプレートファイル(index.html.erb)が挿入される形になります。
もちろんyieldで読み込まれるのは、それぞれのページ固有のテンプレートファイルです。まだ今のところテンプレートファイルはindex.html.erbしか作っていませんが。
ページ全体に関わる部分(ヘッダーやフッターなど)はapplication.html.erbで定義し、各ページ固有の内容は各テンプレートファイルで定義するようにすれば、ビューのメンテナンスが非常に楽になります。
application.html.erbは、レイアウトテンプレート(あるいは単にレイアウト)と呼ばれています。
サイトの共通部分であるレイアウトテンプレートと、各ページ固有の部分であるテンプレートファイルが統合されることで、ビューとしての仕事をします。
モデルのすること
ここまでの実装に、モデルは登場していません。モデルは説明することが非常に多いので詳細はまた次回以降に回しますが、どこで何をするのかだけ簡単に説明しておきます。
コントローラー(members_controller.rb)のindexアクションを思い出して下さい。
1 2 3 4 5 | class MembersController < ApplicationController def index @message = "Hello" end end |
ここではテンプレート変数messageに、「Hello」という文字列を与えていました。そしてそれをビューから参照していたわけですが、ここがモデルの働きどころです。
「Hello」の例ようにコントローラーで勝手に値を用意するのではなく、モデルに対して「ID番号1のmemberの情報をデータベースから引っ張って来い」と命令して返ってきた値をテンプレート変数に格納する。なんてことが簡単にできるわけです。
1 2 3 4 5 | class MembersController < ApplicationController def index @member = モデル.find(1) end end |
コードの書き方についてはまた次回以降に説明しますが、こんな感じでコントローラーはモデルに対して「この情報持って来い!」と司令を出します。その命令に従ってデータを用意するのがモデルの仕事です。
そして、モデルに情報を用意させて、ビューにそれを渡す。それが上司であるコントローラーの主な仕事です。
HTTPリクエスト → Router → Controller → Model → Controller → View → レスポンス
この流れをまず理解しましょう。
さて、長々とやって参りましたが、これでとりあえず
http://ドメイン/members
にブラウザでアクセスすると、「Hello」という文字が表示される状態になりました。
テストサーバーを立ち上げて確かめてみましょう。
Railsには標準でテスト用のサーバーがついているので、書いたプログラムを簡単に走らせてみることが出来ます。
Railsの勉強をさせて頂いております。
とても分かりやすく、丁寧で助かります。
ですが、一点戸惑った部分がありましたので、ご指摘させて頂きます。
・「コントローラーを作る」に記載されているコマンド「$ rails g contoroller members」のcontrollerの綴りが間違い。
コピペで(見て写しても)正常に動作しないので少し混乱しました。
よろしくお願いいたします。
by purunus 2017年8月17日 11:01 AM
>purunusさん
ご指摘ありがとうございます。修正いたしました。
by nobuo 2017年8月17日 11:59 AM
[…] Ruby on Railsの基本中の基本 MVC + ルーターについて […]
by Rails5でシンプルチャット | IT技術情報局 2018年6月4日 5:51 PM
[…] Ruby on Railsの基本中の基本 MVC + ルーターについて Nobuoさん […]
by 【Rails】初心者がWebアプリを作ってみた!【第2回:実際にアプリが正常に動くまでを解説】 | ド素人が話題の趣味を始めてみた【シュミハジ】 2020年7月11日 7:41 AM