Web サーバーと Rails の基本
このページでは、基礎的な PC の知識と、HTML に関する知識、簡単なプログラミング、データベースの知識を前提にしています。
Rails と共に Web アプリケーション開発の旅にでる前に、色々と役に立つ武器があると効率良く開発を進めていくことが出来ます。ここではそのような知っておいたほうが開発がスムーズになること紹介していきます。
Web アプリケーションの仕組み
そもそも、Web アプリケーションはどのように動いているかを理解していないと Rails の話をしても理解するのは大変です。まずは基礎的なところから説明していきます。
サーバーとクライアントの通信
皆さんが使用している PC は Web アプリケーションの用語ではクライアント(厳密には今皆さんが使っているブラウザがクライアント)と呼ばれます。対して、皆さんに何かしらのサービスを提供するどこか別な場所にある PC のことをサーバーと呼びます。このクライアントとサーバーはどのようにして通信しているのでしょうか。
答えは URL の中にあります。 URL は例えば
http://5dot.info/hoge/index.html
といった形で表されますが、この「 http 」の部分が通信方法を表す部分です。つまり、クライアントとサーバーは http を利用して通信しているのです。この、 http などの通信方法の決まりのことをプロトコルと言います。
さて、この http ですが、いったいどんな通信をするのかというのは、 RFC に書かれています。詳しく調べたい時は RFC を見る必要がありますが、概要だけを把握したい場合はそこまでする必要はありません。 Studying HTTP が詳しいので参考にして下さい。
http の概要
では http の中身を確認してみましょう。
http では主に二つの処理があります。サーバーにデータを要求するリクエスト (Request) と、サーバーがデータを返すレスポンス (Response) です。
このようにサーバーにデータを送り、返事を求める事をリクエストを送ると言い、送るデータ自体のことをリクエストと呼びます。また、サーバーが返事としてデータをクライアントに送ることをレスポンスを返すと言い、返されるデータ自体をレスポンスと呼びます。
では、リクエストとレスポンスはどのような形をしているのでしょうか?
リクエストはリクエスト行(メソッド、 URI 、 HTTP バージョン)、ヘッダ、メッセージボディで構成されています。 URI と書いていますが URL の上位版みたいなものです。 URL についての詳細は後述します。
対して、レスポンスはレスポンス行( HTTP バージョン、ステータスコード)、ヘッダ、メッセージボディで構成されています。
ステータスコードはサーバーの処理がうまくいったか、リクエストが不正なものであった、などリクエストの処理結果を表すものです。
これらの HTTP の中身を見るには Wireshark などのアプリケーションを使うほか、 Telnet 等で実際に GET リクエストをサーバーに送ってみると良いかもしません。
リクエストの概要です。サーバーに送るのがリクエストです。
レスポンスの概要です。サーバーから返ってくるのがレスポンスです。
GET と POST
さて、 http でリクエストを送る方法は大きく分けて二つあります。一つが、 GET で、もうひとつは POST です。この2つ(本当はもっとたくさんある)をメソッドまたはリクエストメソッドと読んだりします。
GET はサーバーからデータを取得してくる際に利用されるもので、 URL に付随するクエリというものでデータを渡します。クエリについては後ほど説明します。
GET でのリクエストはブラウザのアドレスバーに履歴が残る場合や、ブックマークされる場合があるので、サーバーデータ変更のためのリクエストや、パスワードの入力で利用するのを避けるのが無難です。
また、GET にはデータの長さ(正確には URL +クエリの長さ)の制限があるので注意が必要です。大量のデータを扱う場合は POST を使うようにします。
もう一つの POST はデータをサーバーに送るときに使うもので、リクエストの中(メッセージボディ)に情報を格納して、サーバーに送る方法です。
GET と違って URL の後ろにデータが埋め込まれるわけではないので、データの長さに制限がありませんし、履歴に投稿内容が残ることがありません。
ただ、リクエストの中身を少しだけ変えたい時でも HTML を変えなければいけないので、テストをするのは大変です。 Firefox や Chrome には POST リクエストを送るためのプラグインがあるようなのでそれを使うと良いかもしれません。
ヘッダーの中身
リクエストや、レスポンスには一般的なデータ( HTML や POST で送られるフォームの情報)以外にもヘッダーに付加的な情報が載せられた状態で送られます。
レスポンスに含まれるヘッダには、リダイレクトに関するもの (Location) 、キャッシュに関するもの(Cache-Control) など重要な物が幾つかあります。
URL の読み方
先ほど、
http://5dot.info/hoge/index.html
のうち http の説明をしました。残りの部分はどういった意味を持つのでしょうか。
5dot.info
の部分は通信相手のサーバーを表しています。
これはホスト名または FQDN と呼ばれているもので、世界にある個々のコンピュータを識別するためのものです(実はもっと話は複雑なのですが、ここではそういうものと思って下さい)。
つまり、
http://5dot.info/hoge/index.html
と、
http://5dot.info/uga/foo.html
は全く同じサーバーと通信していることになります。
それでは残った部分
/hoge/index.html
は何でしょうか?これはサーバーの中のどのファイルを表示して欲しいかを表すもので、パスと呼ばれています。
一般的な Linux サーバーのルート「 /
」を Web サーバー公開すると(普通はやりません)、パスを「 /var/log/syslog
」と指定することでそのサーバーのログを外部から見ることが出来ます。
クエリの形式
さて、一般的な URL はこれだけわかっていれば十分なのですが、私達が作る Web アプリケーションでは他にクエリというものがついてきます。クエリは Google や bing 、 Yahoo! で検索した時に出てくる URL にも付いてきます。例えば、bing で apple と検索すると、
http://www.bing.com/search?q=apple&go=&qs=n&form=QBLH&filt=all&pq=apple&sc=8-4&sp=-1&sk=
のような URL が表示されます。この内、
http://www.bing.com/search
の部分は先程まで説明した通り、プロトコル「 http
」、ホスト名「 www.bing.com
」、パス「 /search
」を表す事が分かります。そして、先程紹介したクエリというのが ? 以降の部分
?q=apple&go=&qs=n&form=QBLH&filt=all&pq=apple&sc=8-4&sp=-1&sk=
に相当します。
実はクエリは名前とその値を表す組み合わせが列挙されていて、「 q
」の部分が名前で「 apple
」の部分がその値を表します。プログラミングでいう連想配列や、辞書、マップなどと呼ばれるものと同じイメージです。同様に、
- 「
go
」→「」(空) - 「
form
」→「QBLH
」 - 「
filt
」→「all
」 - 「
pq
」→「apple
」 - 「
sc
」→「8-4
」 - 「
sp
」→「-1
」 - 「
sk
」→「」(空)
=
」で結ばれていて、それぞれの名前と値の組みは「 &
」で分けられています。
これらのクエリは HTML のタグによって作られる、テキストボックス、テキストエリア、ラジオボタン、セレクトボックス、隠しフィールドなどに入力されている値を反映したものになっています。
どのようなタグを使うとどのようなクエリが生成されるかは、HTML5リファレンスなどを参照しながら調べる必要があります。
普通の Web サーバーに対するアクセスではパスの部分に静的なファイル( HTML ファイルや、画像ファイル)を指定することで、いつも同じ情報を取得してきます。
対して、 Web アプリケーションではパスの部分にプログラムを指定します。このプログラムは渡されたクエリを使って何らかの処理を行い、適切な HTML ファイルを出力します。つまり、リクエストの処理の一部を Web サーバーがプログラムに任せることで動的なページ表示を実現するのです。
Web アプリケーションを実現するためには、サーバーがプログラムにクエリの情報を渡さなければならないわけですが、このためのクエリの渡し方の決まりとして CGI などがあります。
しかし、 CGI には色々と問題があるため現在ではあまり使われていません。
Rails ではこのクエリの受け渡しに params
というオブジェクトを用いています。詳細はこれから学んで行く事になります。
全体の処理の流れ
さて、ここまでの説明で Web アプリケーションの全体の流れを俯瞰するための準備は整いました。実際に全体の流れを確認して行きましょう。
- 表示されている画面のフォームに何かしらの入力を行います。
- 送信ボタンを押すと
<form>
タグで指定されているmethod
属性で指定されたメソッドでリクエストを送ります。このリクエストはaction
属性で指定されているパスのプログラムになります。 - リクエストを受け取った Web サーバーが与えられたパスにしたがって、適切なプログラムにリクエスト情報( URL やクエリなど)を渡し、プログラムを実行します。
- プログラムが受け取ったリクエスト情報を元に様々な処理(データベースの更新や出力 HTML の生成など)を行い、 HTML ファイルを出力します。
- Web サーバーは出力された HTML をクライアントにレスポンスとして返します。
- クライアントはレスポンスを元に画面の表示を行います。
Web サーバーがプログラムに処理をプログラムに委託することで、動的なコンテンツの生成が可能になっています。
以上が、基本的な処理の流れになります。このように Web アプリケーションの基本はリクエストに対して適切なレスポンスを返すことに尽きます。
Rails の概要
この「 Rails の概要」は Getting Started with Rails を参考に書いています。
Ruby on Rails は Ruby 上で実行される Web アプリケーションフレームワークです。よく、 Rails と書いたりしますが、正式名称は Ruby on Rails だということは覚えておいて損は無いと思います。
Ruby on Rails を使えばWebアプリケーションを簡単に作ることができます。さらに、 Rails はかなり洗練されたフレームワークなので少ないコードで Web アプリケーションを楽しく作ることができます(ただし、最初の勉強をするところは大変かもしれません、調子が乗ってくると楽しいのでそれまでの辛抱です)。
Rails の哲学
Rails では物事を進める上で最も良い方法が存在すると考えます。そのような理由で、 Rails は最も良い方法を簡単に出来るように設計されています。
つまり、「 Rails 流」の方法を学ぶことによって、生産性を飛躍的に向上させることが出来ます。なので、他の言語で学んだことをそのまま Rails で適用しようとすると、色々と苦労することになります。例え、それが会社のルールだとしてもです。もし仕事で Rails を使う場合は会社のルールを Rails に合わせる必要があるかもしれませんね。
Rails の哲学には以下の様な原理が根底にあります。
- DRY("Don't Repeat Yourself") - 同じようなコードを何度も書くことは悪いこと!!
- 設定より規約 - つまり Rails はいちいち小さな設定を開発者にさせるより、開発者がどんなことをやりたいか、どうやろうとしているかを仮定して処理をする!!
- REST は Web アプリケーションで最も優れたパターン - アプリケーションをリソースと基本的な HTTP メソッドに則って整理するのが最も良い方法!!
MVC アーキテクチャ
Rails は MVC(Model View Controller) アーキテクチャを採用しています。
Model はアプリケーションが扱うデータと、手続き(ビジネスロジック)を担当する要素です。データベースの操作に直結するのが Model ということになります。 Rails ではそれぞれのテーブルが一つずつ Model オブジェクトに対応しています。つまり Model の数だけテーブルが存在するということです(一部例外を除く)。
View は Model のデータを取り出して、ユーザーに提示する仕事をする要素です。 Rails で言うと HTML の生成や CSS の生成がこの部分に含まれます。 Rails では HTML に Ruby のコードを埋め込むことで動的な HTML の作成を行います。また、 View はブラウザに表示するデータを作ると同時に HTML の form を作る、つまりデータの送信形式(クエリの形)を決めるという役割も担っています。
Controller はユーザーの入力に対応した処理を行う要素です。つまり、リクエストで渡されたクエリを( Rails の場合は Web サーバー兼用なのでパスの部分も)さばき、適切な描画処理 (View) を呼び出すことが仕事です。 Rails では、 View に描画処理を委任する際に表示がしやすいようにデータの加工をすることも Controller の役割になっています。
この MVC アーキテクチャの特徴としては、ビジネスロジックとユーザーインターフェースの分離が出来ること。Rails の哲学である DRY なコードを維持するのが簡単であること(つまり、生産性が高い)、そしてコードの責務が明確になるのでメンテンナンスが容易になることが挙げられます。
Railsのコンポーネント
以上のような MVC アーキテクチャや、 Rails の哲学を実現するために幾つかの重要なコンポーネントが存在します。ここではそれらについて簡単に紹介していきます。
気をつけて欲しいのは、すべてのコンポーネントを一度に理解する必要は無いということです。ここで説明するのはあくまでも概要なので、こういうものがあるんだなと頭の片隅に置いておけば十分です。
まずは全体としてどういったコンポーネントがあるのかを見てみましょう。それをまとめたのが下のリストです。
- Action Pack
- Action Controlloer
- Action Dispatch
- Action View
- Action Mailer
- Active Model
- Active Record
- Active Resource
- Active Support
- Railties
Action Pack
「 Action Pack 」は「 Action Controller 」、「 Action View 」、「 Action Dispatch 」を含むMVCのうちの View と Controller に当たる部分です。この部分は他のコンポーネントに比べて結合が強いため「 Action Pack 」という一つのコンポーネントとしてまとめられています。
昔は「 Active Record 」も「 Action Pack 」に含まれていたのですが、現在では分離されています。
Action Controlloer
「 Action Controller 」は Rails アプリケーションの MVC の Controller を司るコンポーネントです。「 Action Controlloer 」はリクエストを Rails アプリケーション(のコントローラ or アクション)に渡す役目を負っています。他にも、セッションの管理や、テンプレートのレンダリング( View の処理の呼び出し)、リダイレクトの機能などを持っています。
それらの機能について詳しく調べたい時は、「 Action Controller 」のリファレンスを参照すれば良いのです。
Action View
「 Action View 」は MCV の View を担当するコンポーネントです。「 Action View 」は HTML だけでなく XML の出力も可能で、テンプレートのレンダリングの管理や、部分テンプレート(サイトの一部をテンプレートとして使いまわす方法)、さらに AJAX(リロードなどのページの再読み込みなしに動的に HTML を変更する事)のサポートも行います。
重要なのは HTML の生成の際にテンプレートを用いている点です。繰り返しになりますが、 Action View では予め作成しておいた HTML のテンプレートに Ruby のコードを埋め込んおきます。レンダリング時にはその Ruby コードを解釈して文字列をその部分に埋め込んだり、ループや条件分岐を行って動的なページを生成します。
Action Dispatch
「 Action Dispatch 」はアプリケーションのルーティングを担当します。来たリクエストをどの Controller に処理させるのかを決めるのがルーティングという処理です。しかも、 Rack アプリケーションでは更に高度な処理を任せることが出来ます。しかし普通の場合は、適切な Controller にリクエストを回すのが「 Action Dispatch 」の役目になります。
Action Mailer
「 Action Mailer 」はメールを作り、送信、受信するためのコンポーネントです。簡単なテキストメールはもちろん、複雑なメールの処理もテンプレートの力を借りて行うことが出来ます。
Active Model
「 Active Model 」は「 Action Pack 」とRuby上のオブジェクトとデータベースを関連付けるコンポーネント(「 Active Record 」など)のインターフェースを提供します。つまり、「 Active Model 」のインターフェースを提供する他のコンポーネントを利用すれば、「 Active Record 」以外のコンポーネントも使用可能になります。
Active Record
「 Active Record 」は Rails アプリケーションのモデルの元になるオブジェクトです。「 Active Record 」はデータベースに必須である CRUD(Create, Read, Update, Delete) の機能を提供する他、データの検索、データの関連 (Relation) などを扱うことが出来ます。いわゆる O/R マッパーに当たるもので、データベースと Ruby のオブジェクト指向のミスマッチを吸収するための層と言えます。
Active Resouorce
「 Active Resource 」は Rails アプリケーションを簡単に RESTful にするためのフレームワークです。
Active Support
「 Active Support 」は Ruby のライブラリを拡張するコンポーネントです。つまり、 Ruby をより便利に使うために作られたライブラリがここに収められています。
Railties
「 Railties 」は Rails アプリケーションを新しく作ったり、幾つかのフレームワークをプラグインという形で Rails アプリケーションに組み込む働きを持つコンポーネントです。 Rails 開発で使うコマンドなどはこのコンポーネントに含まれています。
REST の概要
いままで、 REST や RESTful といった言葉が出てくることがありましたが、これについて説明して来なかったので、ここで簡単に REST について紹介しておきます。
REST(Representational State Transfer) は Rails では、以下のような二つの意味で捉えられています。
- URL などを使ってリソースを表現する
- リソースの状態の表現をシステムコンポーネント間でやり取りする
正直これだけ書かれても良く分かりません(訳してきた私も分かりませんというか、訳が適切かもわからない)。どうにか、URL を使って具体的なオブジェクトの操作を行うことはわかります。
どうやら、 RESTFul な Webアプリケーションは内部にユーザーの状態を持たず、URLだけで処理を決めるといった考え方のようです。
しかしそんなことが分かっても仕方ありません。そこで、例を見てみます。
例えば、
DELETE /photos/17
は ID17 の写真を削除するという事を表します。
このように、REST ではやりたいこととその対象が非常に明確です。しかし、これを真面目に実装しようとするとかなりの困難に直面することになります。実現しようとするとルーティングが複雑になってしまうのです。Rails(Active Resouorce) を使えばこの実装上の困難を回避することが出来るわけです。
Rails の全体像
さて、色々とコンポーネントや MVC の REST について解説してきましたが、ここで特に重要なところだけまとめてみましょう。
まず、基本的な Web アプリケーションの流れに沿って使われるコンポーネントを確認してみます。
始めにクライアントからリクエストが送られてきますが、このリクエストのパスに基づいて Action Dispatch が呼び出すコントローラ( ActionController::Base を継承したリクエストに対する処理を具体的に記述したクラス)を決めてくれます。どのような規則で呼び出すコントローラを決めるのかをルーティングと呼び、この呼び出し処理をディスパッチと言います。
選ばれたコントローラはクエリに含まれているデータに合わせて適切な処理を行い、描画に利用するビュー( HTML のテンプレート)に情報を渡し結果を生成してもらいます。ビューに情報を渡す場合はコントローラー内でインスタンス変数にオブジェクトを代入しておくだけで、同じ名前のインスタンス変数がビュー内でも使えるようになります。この変数を利用した Ruby コードの断片を埋め込むことで動的に HTML を生成します。また、 Rails アプリケーションでは描画に利用するビューを指定するのに、 render メソッドを利用します。
fp この際に、データベースにアクセスする必要が出てくるかもしれませんが、その時は Active Record を継承したオブジェクトを利用することによって処理を行います。データベースの変更はこのオブジェクトを介して行います。 Active Record ではデーターベースの「テーブル」が「クラス」、「行」が「オブジェクト」、「列」が「属性」に対応づけられています。
そして、ビューから生成した結果を元に Rails が自動的にレスポンスをクライアントに返します。