RubyOnRails を使ってみる 【第 1 回】

はじめに

もりきゅうです。 本稿では RubyOnRails (以下 Rails) という Web アプリケーションフレームワークを紹介します。

MVC モデル

Rails は MVC という考え方に基づいたフレームワークです。

IT用語辞典によると MVC とはソフトウェアの設計モデルのひとつで、

  • 処理の中核を担う Model
  • 表示・出力を司る View
  • 入力を受け取ってその内容に応じて View と Model を制御する Controller

これら 3 要素の組み合わせでシステムを実装する方式のことです。

Rails は

  • Model を担当する ActiveRecord
  • Controller と View を担当する ActionPack

というふたつのライブラリで構成されています。

Rails の特長

Ruby を用いた Web アプリケーションフレームワークはすでにたくさんあります。 本誌で連載されている RAA:nora もそのひとつです。

その中でも Rails は新しいプロジェクトです。すでにほかのフレームワークを使っている方ならともかく、自作で何となくやってきた方や、これから新たに Web アプリケーションを作ろうと思っている方が Rails を選択するメリットとしては何があるのでしょうか。

私も自作で何となくやってきたひとりですが、Rails はすんなり使えました。同時に、感銘を受けました。 Rails を導入する理由として、私は次の利点を挙げたいと思います。

  • ruby-man:Test::Unit を使ってテストを書く仕組みが用意されている。
  • ActiveRecord という使いやすい O/R マッピングライブラリを含んでいる。
  • テンプレートエンジンとして ruby-man:ERB を使っている。

Test::Unit

Test::Unit はどこでも使えるわけですから、自分でテストを書いてテスト駆動開発を行えばよいわけですが、Rails は Model, View, Controller に対するテストの雛形を自動的に作ってくれるので、すぐにテストを書き始めることができます。

特に、データベースのテストの仕組みが用意されているのは嬉しいことです。

データベースのテストは、以前実際に書いてみてわかったのですが、単純に書くと壁にぶつかります。 データベースに保持されるデータはアプリケーションを使うと書き換えられていくので、assert が書きにくいのです。 そのため、アプリケーションで用いる db と同じスキーマを持つ別の db をテスト用に用意して、テストの開始時点で決まったデータを保持しているように準備し、そのデータに合わせて assert を書いていく、という手順が必要になります。

Rails は、Fixture という仕組みを用いてテスト用のデータベースを構築してくれます。また、Rake (ruby による make) を用いるとテストをまとめて実行できます。

ActiveRecord

私はほかの O/R マッピングライブラリを用いたことがなく、比較できる知識を持ち合わせていないのですが (今号の RLR は O/R マッピング特集なので、是非そちらもご覧ください)、少なくともすぐに使えるというのは大きな特徴だと思います。データベースのフィールドを後で追加しても、特にほかを書き換えることなく使えるので、開発を迅速に進めることができます。

ERB

私は以前から ERB を使ってきたので、個人的には Rails への移行を容易に行えました。

ERB の良いところは、ちょっとしたタグの決まりさえ覚えれば、テンプレートにそのまま Ruby コードを書けるので、新たな記法を覚えなくてよいというところです。もちろんこの特徴は、テンプレートの中にロジックを実装してしまいがちになるという悪い点としても言及されることが多いのですが、実際にはそんなことは問題になりません。

なぜなら Rails では M, V, C それぞれに対するテストを容易に書けるので、ロジックも書き直しやすいのです。 また、ロジックをごりごり書かなくて済むように、多彩なユーティリティが用意されています。 View に書いても別に動くからいいんだけど、見苦しくなったとか、重複したコードがあるというときには Controller や Model にロジックを移してみたり、ユーティリティを使ってみることができます。

対象読者

さまざまな RDBMS を扱えるようになっているとか、Windows 環境でもすんなり動かせるとか、ほかにもメリットは挙げることができますが、とにかく使ってもらえれば Rails の良さは理解していただけることと思います。

本稿の対象読者としては、Ruby に慣れていて、これまでに cgi.rb などを使った Web アプリケーションを書いたことがあり (CGI パラメータ、それとセッションを理解されていれば問題ないでしょう)、RDBMS (MySQL, PostgreSQL ならすぐに Rails で扱えます*1) を何かひとつ扱える方を想定しています。

では、始めましょう。

インストール

http://www.rubyonrails.org/show/GemRails

Rails のインストール手順にはいく通りかありますが、最も容易なのは RubyGems を用いる方法です。

RubyGems を用いたインストール

あなたの環境に RubyGems が入っているか確認してください。

 $ gem

もし入っていなければ RubyGems の導入に踏み切るか、ほかの方法を検討しなくてはなりません。 今回はあまりインストールに誌面を割きたくないので (一刻も早く Rails を体験してもらわなくては!) とりあえず RubyGems を入れていただくことにします*2。 RubyGems についてはプロジェクトサイトをご参照ください。 インストールは簡単で、

 rubygems$ ruby install.rb

とします。 RubyGems さえあれば Rails のインストールは簡単で、

 $ gem install rails

とします。 いくつか依存ライブラリ (ActionMailer, ActionPack, ActiveRecord, Rake) のインストールを確認されますので y と答えてください。

RDBMS

MySQL か PostgreSQL をお勧めします。SQLite も扱えますが私は良く知りません。

ウェブサーバ

ウェブサーバは mod_write またはそれに類する機能を持つものが望ましく、Apache か Webrick を用いればよいでしょう。

Windows 環境でのインストール

http://www.rubyonrails.org/show/HowtoInstallOnWindows

ここに RubyGems と XMAPP を用いたインストール手順が動画で紹介されています。

XMAPP

XMAPP は apachefriends と銘打っているように、Apache とその仲間たち、Apache2, MySQL4.0, Perl5.8, PHP5 を全て含んだパッケージです*3。 XMAPP はこれらを簡単にインストールして管理できますので、特にこだわりがなければ、とりあえず入れてみることをお勧めします。 特に MySQL をブラウザから管理できる phpMyAdmin は一見の価値があります。日本語にも対応しているので、是非一度体験してみてください。

テストで動作を確認

Rails のインストールはうまくできましたか。 インストールできたら、インストールされたファイルを一通り確認してみてください。

RubyGems でインストールすると $(prefix)/lib/ruby/gems/1.8 に cache, doc, gems, specifications というディレクトリが作られているはずです。

cache の中には *.gem ファイルが置かれます。これは RPM でいうところの *.rpm のようなもので、gem の形式でまとめられたパッケージです。*.gem は gem unpack コマンドで展開できます。

doc の中には RDoc で生成されたドキュメントが置かれます。

gems には *.gem を展開したものが置かれます。 ここにライブラリ本体が含まれています。

specifications には *.gemspec ファイルが置かれます。これは RPM の *.spec に相当します。

$(prefix)/bin にはコマンドが用意されます。 Windows 環境では *.cmd というバッチファイルが作られます。 gem, rails, rake といったコマンドが置かれていることを確認してください。

ActiveRecord の確認

さて、ではまず ActiveRecord から確認してみましょう。 執筆時点での ActiveRecord gem のバージョンは activerecord-1.1.0 です。 $(prefix)/lib/ruby/gems/1.8/gems/activerecord-1.1.0/ に README, RUNNING_UNIT_TESTS が置かれていますので読んでみましょう。

Rails はドキュメントがしっかり書かれているので (素晴らしいことです)、 一通り目を通してみることをお勧めします。サンプルコードが豊富で、丁寧に説明されており、英語に不慣れな私であっても理解できました。

では、RUNNING_UNIT_TESTS に従って、ActiveRecord のテストを行ってみましょう。 RUNNING_UNIT_TESTS に書かれているように、あらかじめテスト用のデータベースを作成しなくてはなりません。 ここでは RDBMS として MySQL を用いてみます。PostgreSQL でも手順は同じなので、適宜読み替えてください。 テスト用のデータベースの名前, username, password は test/connections/native_mysql/connection.rb で設定します。デフォルトでは、データベース名は activerecord_unittest と activerecord_unittest2 (このテストはデータベースをふたつ使います)、username は root, password は なし です。ご自分の環境に合わせて設定していただければいいわけですが、テストの username にはテスト用のデータベースに対して create, delete, select, insert, update 権限が必要になります。

 $ mysql -u root
 > create database activerecord_unittest;
 > create database activerecord_unittest2;
 > \q

次にデータベースにテーブルを作ります。 テスト用のテーブルは test/fixtures/db_definitions/mysql.sql, mysql2.sql に定義が書かれています。

 $ mysql -u root activerecord_unittest < test/fixtures/db_definitions/mysql.sql
 $ mysql -u root activerecord_unittest2 < test/fixtures/db_definitions/mysql2.sql

テストの準備ができました。では実際にテストを行ってみましょう。

基本的なテストは test/base_test.rb で行えます。

 $ cd test
 $ ruby -I "connections/native_mysql" base_test.rb

用意されたすべてのテストを行うには all.sh が使えます。

 $ cd test
 $ all.sh "connections/native_mysql"

また、テストは Rake を用いても行えます。

 $ rake test_mysql_ruby
 $ rake test_ruby_mysql

Rakefile の task は rake -T (または --tasks) で確認できます。Rake については rake コマンド、ドキュメントをご参照ください。

MySQL の Ruby 拡張ライブラリ

MySQL の Ruby 拡張ライブラリとしては RAA:mysql-rubyRAA:ruby-mysql というふたつの (互換性のある) ライブラリがあります (どちらもとみたさんによって書かれました)。 MySQL/Ruby は C言語で実装されたライブラリであり mysql.so が本体です。存在しない場合はインストールする必要があります。 一方、Ruby/MySQL はすべて Ruby で実装された (pure ruby) ライブラリであり、ActiveRecord には lib/active_record/vendor/mysql.rb として含まれています。 ActiveRecord で MySQL アダプタを用いる際には、まず ActiveRecord は MySQL/Ruby の存在を確認し、あればそれを使います。なければ vendor にある Ruby/MySQL を使います (アダプタのソースは lib/activerecord/connection_adapters/mysql_adapter.rb にあります)。

PostgreSQL の Ruby 拡張ライブラリ

PostgreSQL の Ruby 拡張ライブラリも C言語による実装 RAA:postgres と Ruby による実装 RAA:postgres-pr があります。これらは互換性があり、ActiveRecord ではどちらも利用できます*4

ActionPack の確認

執筆時点での ActionPack gem のバージョンは actionpack-0.9.5 です。 これも ActiveRecord と同じように確認してください。

ActionMailer の確認

執筆時点での ActionMailer gem のバージョンは actionmailer-0.4.0 です。 これは青木さんの RAA:tmail に対するラッパーとして実装されたライブラリです。 ActionMailer には lib/action_mailer/vendor/tmail として含まれています。

チュートリアル

テストで動作を確認できたら、Rails のチュートリアルを一通りこなしてみましょう。

Tutorial in Rails

このチュートリアルでは簡単なアドレス帳を作っています。

また、ここで扱うデータベースはひとりの人物が複数の電話番号を持つというリレーションを含んでおり、ActiveRecord の O/R マッピングを扱う例になっています。

このチュートリアルを構成するページとその簡単な説明を以下に示します。

Tutorial Step 1-4

まず、チュートリアルで扱うデータベーステーブルを MySQL を用いて定義し、 ActiveRecord で用いる接続設定を config/database.yml に記述しています。

次に、script/new_controller, new_model といったスクリプトを用いてクラス定義を生成しています*5

Tutorial Step Five - Test Your Rails

このページでは、rake を用いたテストの自動化を紹介しています。

Tutorial Step Six - Develop your Rails application!

このページでは、View (ERB テンプレート), Controller に Model (データベース) へのアクセスを実装する例を紹介しています。

Tutorial Basic Relational

このページでは、1対多のリレーションを Rails (ActiveRecord) で扱う例を紹介しています。

Tutorial Scaffolding

このページでは、データモデルに対する最小限の操作を実装してくれる scaffold という仕組みを紹介しています。

ひとつのデータモデルに対して最小限必要な操作としては、追加 (新規作成)・削除・表示・一覧・編集があります。 これらの操作の実装は、ひとつひとつはそれほど手間ではありませんが、データモデルがたくさんあると同じようなものを何度も作る破目になります。退屈な仕事になりそうですね。

こんなときには scaffold を使いましょう。 Controller に、たった一行

 scaffold :person

と書くだけで、追加・削除・表示・一覧・編集の各操作を行えるようになります。

scaffold の追加・編集テンプレートは、データベーステーブルのフィールド型に合わせたフォームを作成してくれます。例えば DATE 型なら年・月・日の各入力フォームを生成します。

Tutorial Helper Methods

このページでは、手作業でテンプレートを作る際に役立つ Helper method を紹介しています。

scaffold は自動的にテンプレートを用意してくれますが、実用的なサービスを提供するためには、使い勝手の良いフォームを生成するテンプレートを自分で作る必要があります。

ここで紹介されている Helper method は HTML タグを生成するメソッドで、リンクを生成する link_to, フォームを生成する form_tag, hidden_field, text_field といったものがあります。

Tutorial Framing Out

このページでは、Controller の update, destroy メソッドの実装例を紹介しています。

Tutorial Relational Forms

このページでは、電話番号の編集・追加フォームをアドレス帳の編集フォームに追加しています。

このチュートリアルの作例では、person, phones テーブルは1対多の関係であり、ひとりの人物に対して電話番号を複数登録できます。

この例を読めば、複数のオブジェクトに対応するパラメータを Rails ではどのように扱えばよいのか理解できるでしょう。

例えば、input タグの name に "phones[1][phone]" と指定することで、対応する値を @params["phones"][1]["phone"] として得ることができます。

How to make a todo list program with Rails

このチュートリアルでは TODO リストを作ります。

このチュートリアルの前半は、先に見たチュートリアルと同じように、データベーステーブルの作成、Model, Controller の作成、scaffold、View (ERB テンプレート) の作成といった基本的な内容になっています。

Model と Controller が同じ名前 (todo) なので、名前がどのように関係しているのか理解しにくいかもしれません。

後半は、目新しい機能が盛り込まれています。 ひとつには、JavaScript を用いた機能があります。

  • 削除する際に確認のダイアログを出す。
  • checkbox をクリックしたときにアクションを起こす。

といった機能です。

Displaying the items: part II 以降はより実践的な内容になっています。

  • find_all の検索条件
  • Helper module へのメソッド定義
  • render_partial を用いたテンプレート分割

find_all の検索条件

ActiveRecord の find_all メソッドには引数として検索条件を与えることができます。

find_all の定義は以下のようになっています。

 module ActiveRecord
   class Base
     class << self # Class methods
       def find_all(conditions = nil, orderings = nil, limit = nil, joins = nil)

この引数は順に SQL の WHERE 節、ORDER BY 節、LIMIT 節として用いられます (joins には FROM 節の後にそのまま挿入される SQL を設定できます)。

Helper module へのメソッド定義

Helper module にはテンプレート内で用いる関数を定義できます。 このチュートリアルでは、Helper module は app/helpers/todo_helper.rb に記述することになります。

render_partial を用いたテンプレート分割

render_partial はテンプレートをそのままの形で分割できます。 機能的には Helper module でも同等のことを行えますが、Helper module は ERB のガワと中身をひっくり返す必要があるのに対し、render_partial は ERB そのままの形で使えます。

このチュートリアルでは、app/views/todo/_display.rhtml に分割したテンプレートの一部 (partial) を置いています。そして render_partial "display", @item といった形で呼び出しています。

また、繰り返しの中で render_partial を呼ぶ代わりに、繰り返しを内包した render_collection_of_partials を用いる例も示されています。

ここで出てくる <% @item = display %> に関する説明書きはわかりにくいと思います。ここではあえて Rails のわかりにくいところを指摘してくれているのかもしれません。

Rails のわかりにくさ

Rails を使っていると、この例に見られるように「どこでどうやってパラメータを渡しているのか」悩むことがありますが、これについては今のところ Rails のソースを読んで理解するしかないと思います。 この例では render_template の実装を読めば eval を使って (なんてこった!) ローカル変数に設定 (代入) していることがわかります。

また、ActionController は CGI パラメータや ActiveRecord オブジェクトを eval を使ってインスタンス変数に設定 (代入) しています。

Rails はベースとなるクラスに数多くのメソッドを定義したフラットな構成になっているので、基本的にメソッドはどこからでも呼べ、インスタンス変数上のパラメータはどこからでも読めます。 これは使いやすい反面、全体の構造は理解しにくくなっていると思います。また、このために RDoc による Rails ドキュメントもひとつのクラスに数多くの機能がまとめて書かれた形になっています。

まとめ

一通りチュートリアルをこなせば、これを真似して Web アプリケーションを作成しはじめることができるでしょう。

ではみなさん、ご健闘を! と言ってしまうと続かないし、1行もコードを書いていないのは悲しいので、次回は私が作った買い物かごを紹介しつつ、Rails の具体的な機能を確認していきたいと思っています。

Rails の開発はばりばり進んでいるので、記事がすぐに古びないかちょっと心配……

著者について

もりきゅうは異業種社長 4 名 + 主婦 2 名 + 私という妙なパーティで運営している会社ミッタシステムのプログラマです。

著者の連絡先は moriq@moriq.com です。

*1 Rails の扱える RDBMS は MySQL, PostgreSQL だけではなく、Windows であれば Ruby/DBI 経由で ADO を扱えますし、Rails ML によると DB2, Oracle, FrontBase アダプタは存在するようです。ご自分で db アダプタを書くことも比較的容易です。私は InterBase/Firebird アダプタを書いてみました。

*2 次号では RubyGems と RPA の特集が予定されています。今ここで入れておいても損はないでしょう。

*3 xampp-win32-1.4.9-installer.exe を入れて確認したバージョンです。このほか FileZillaFTP, MercuryMail, webalizer を含んでいます。

*4 PostgreSQL 8.0 からは Windows インストーラが配布されています。postgresql-8.0.0-beta5-en.zip, gem install postgres-pr の組み合わせで試したところ、activerecord-1.1.0 の base_test.rb は native_postgresql アダプタそのままで通りました。

*5 svn head では script/new_* はなくなりました。代わりに script/generate {controller, model} を使います。