Ruby on RailsによるWebアプリケーションの高速開発

迅速な開発のためのこのRubyベースのフレームワークでは、モデル/ビュー/コントローラー・パターンが使用されている

Ruby on RailsがWebアプリケーション開発の世界に登場したのは最近のことですが、ベータ版のうちから急速に人気を得ています。Railsの人気の原因は、最も一般的なタイプのWebアプリケーションの作成を自動化できるだけでなく、カスタムまたは一般的でない要件を追加したい場合でも制約を受けない点にあります。さらに、FreeSoftwareライブラリーの多くがWebアプリケーションの個別の局面を扱うのに対して、Railsには統合化されたすばらしいツール・セットが含まれているため、あらゆる局面に対応できます。

David Mertz, Ph.D (mertz@gnosis.cx), Developer, Gnosis Software, Inc.

Photo of David MertzDavid Mertz氏は多くの分野で活躍しています。ソフトウェア開発や、それについて著述もしています。その他、学術政策理念について分野を問わず、関係する雑誌に記事も書いています。かなり以前には、超限集合論、ロジック、モデル理論などを研究していました。その後、労働組合組織者として活動していました。そして、David Mertz氏自身は人生の半ばにもまだ達していないと思っているので、これから何かほかの仕事をするかもしれません。



2005年 6月 24日

Ruby on RailsはWeb開発に新旋風を巻き起こしています。では、まず、基本テクノロジーの復習から始めましょう。

  • Rubyは、迅速かつ容易なオブジェクト指向プログラミングのためのフリー、シンプル、簡単、拡張可能、移植可能なインタープリタ型スクリプト言語であり、Perlと同様に、テキスト・ファイルを処理し、システム管理タスクを実行するための多くの機能を備えています。
  • Railsは、実世界のアプリケーションをより簡単に、より少ないコードで書くためのフルスタックのRubyのオープン・ソースWebフレームワークです。

フルスタックのフレームワークとは、Railsのすべての層が連携するように組み立てられているので、開発者が自分で組み立てる必要がなく、最初から最後まで単一の言語を使用できることを意味します。Railsでは、すべてのもの(テンプレートから制御フロー、ビジネス・ロジックまで)がRubyで書かれています。Railsでは、構成ファイルと注釈よりも、リフレクションとランタイム拡張が好んで用いられます。

この記事では、Railsのコンポーネントを説明し、その仕組みを示します。

Railsについて

Railsについて最初に理解すべきことは、そのモデル/ビュー/コントローラー(MVC)アーキテクチャーです。このアプローチはRailsに固有のものではなく、他のプログラムとは対照的にWebアプリケーションにも見られるものですが、RailsのMVCの考え方は非常に明確です。開発者がMVCアプローチから脱線すると、そのパラダイムに従った場合に比べて、Railsの有用性は著しく損なわれます。

モデル

Railsアプリケーションのモデル部分は、基本的に、使用するデータベースです。事実、いろいろな意味で、Railsアプリケーションはリレーショナル・データベース管理システム(RDBMS)内のデータに対して直截な方法で操作を加えるための手段に過ぎません。

Railsの中心コンポーネントはActiveRecordクラスです。これは、リレーショナル・テーブルをRubyオブジェクトにマップし、その結果、コントローラーによって操作され、ビューに表示されるデータにマップします。Railsアプリケーションでは、広く普及しているMySQLデータベースが使用されることが多いようですが、IBM®DB2®など、他の多くのRDBMS用のバインディングもあります。

必要であれば、アプリケーション・モデル内で追加の検証を行ったり、データ・リレーションシップを強制したり、その他のアクションをトリガーするRubyコードを追加することができます。アプリケーションのapp/models/ディレクトリー内のRubyファイルは、ActiveRecordのさまざまな検証メソッドを呼び出すことができます。ただし、モデル・コードをスタブのままにしておいて、データを保持するRDBMSの制約だけに依存することもできます。たとえば、この例で筆者が開発したアプリケーションは、次のようなスケルトン・モデル・コードしか含んでいません(少なくとも最初は)。

リスト1. スケルトン・モデルapp/models/contact.rb
class Contact < ActiveRecord::Base
end

コントローラー

コントローラーは、アプリケーション・ロジックを抽象的な形で実行します。すなわち、アプリケーションのapp/controllers/ディレクトリー内のRubyスクリプトがモデル・データを変数にロードして、再び保存し、操作します。しかし、コントローラーは、データが具体的にどのように表現され、どのようにユーザーによって入力されるかということには関知しません。一般的なMVCパラダイムでは、これにより、ユーザーは同じコントローラーと複数のスタイルの対話を行うことができます。ネイティブGUI、Webインターフェース、視覚障害者用のスピーチ・インターフェースなどのすべてが同じコントローラーと対話できます。

ただし、Railsはそのままではそれほど汎用性が高いわけではありません。Webページ内のデータの提供と収集を主な目的としています。それにもかかわらず、コントローラー・コードには関係なく、Webページのレイアウト(色、フォント、テーブル、スタイルシートなど)を変更できます。

ビュー

Railsのビューは、Rubyコードを置く場所です。Railsは、純粋なHTMLを埋め込みRubyコードに結びつける.rhtmlファイル用の非常に便利なテンプレート言語を含んでいます。Railsアプリケーション画面のごく表面的な外観は、一般にCSSスタイルシートによって制御されます。.rhtml形式は、HTMLの拡張です。実際には、単純なHTMLファイル自体も有効なRHTMLテンプレートですが、RHTMLによるスクリプティング・コントロールの省力化という点ではあまりメリットがありません。

RHTMLは、単にHTMLにコードを埋め込む手段ではなく、本当の意味でのテンプレート形式であり、はるかにパワフルなアプローチです。PHPを使い慣れている人は、PHPそのものとSmartyテンプレートの違いを考えてみてください。すなわち、埋め込みスクリプトは、インタープリタで解釈されないHTMLとコードを混ぜ合わせたものにすぎません。クライアントに対して何かを出力するときに、プリント文を発行するのは、やはりコード部分です。

これに対して、テンプレート・エンジンは、条件、ループ、その他のロジックを拡張HTMLマークアップの一部として表現できるカスタム・タグ・セットをHTMLに追加します。


コードの生成

Railsが提供するツールは、基本的にコード・ジェネレーターのセットです。筆者は、厳格なワークスペースとIDEの使用を余儀なくされる開発環境よりも、このアプローチの方がはるかに好きです。Railsは開発者のやり方に口を挟むことがなく、しかも人手によるプログラミングの作業の大部分を省力化してくれます。あるいは、少なくとも、「無料」の足場(scaffold)を提供してくれるので、必要な部分だけ人手でコーディングすれば済みます。

足場の概念は、Railsの中心的概念です。ごく単純なアプリケーションであれば、RailsにクライアントHTMLページを実行時に動的に生成させることによって、カスタム・コーディングをほとんどなくすことができます。コード生成の最初のパスでは、生の足場だけを作成します。後で、より具体的なコントローラー、ビュー、およびモデルを生成して、カスタマイズできます。しかし、始めからそれほど多くのものを生成する必要はありません。

Railsは、固定した、かなり常識的なファイル編成に依存していますが、この編成は比較的厳格です。他のファイル編成やコード編成を使おうとするのは、Rails環境にけんかを売るようなものです。Railsが提供する編成を受け入れるべきでない理由はありません。Rubyファンが好んで言うように、その大部分は「脳にフィット」します。たとえば、ディレクトリーの名前と編成は、あなたがゼロからフレームワークを設計する場合に選ぶ編成にかなり近いはずです(少なくとも、「Ruby流」の考え方をした場合は)。


単純なアプリケーションの構築

Ruby on RailsのWebサイトには、単純なRailsアプリケーションの作成方法を手順を追って説明したチュートリアルがいくつかあります(参考文献を参照)。Railsアプリケーション構築の正しい始め方には一定の作法があるので、ここで示すサンプル・アプリケーションもチュートリアルに似ています。この紹介記事は比較的短いので、まとまったチュートリアルに沿って基礎の理解を固めることをおすすめします。

このサンプル・アプリケーションは、基本的なアドレス・ブックの例です。アプリケーションを作成するために一般的な以下のステップを示しています。

  1. モデルを生成します(MySQLデータベースとテーブルを作成します)。
  2. アプリケーションを生成します(基本コードとディレクトリーの生成を含みます)。
  3. Railsを実行します(データベース・アクセスを設定します)。
  4. コンテンツを作成します(足場モデルおよびコントローラーの生成と、足場を使用するようにコントローラーに指示することも含みます)。

では、各ステップを詳しく見ていきましょう。

AddressBookモデルの生成

どんなアプリケーションについても、最初にしなければならないことは、データを入れるデータベースの作成です。実際には、このステップを最初に行う必要はありませんが、すぐに必要になります。たとえ、コードが自動的に生成される場合でも、アプリケーション・コードの前にデータベースを作成すべきなのは明らかです。まず、MySQLでデータベースを作成して、このデータベース内に最初のテーブルを作ります。(MySQLまたは別のRDBMSを稼働させる方法については、他の資料を参照してください。)

ここでは、MySQLがインストールされていて、使用可能になっていると仮定します。

リスト2. MySQLデータベースおよびテーブルの作成
[~/Sites]$ cat AddressBook.sql
CREATE DATABASE IF NOT EXISTS AddressBook;
USE AddressBook;
CREATE TABLE IF NOT EXISTS contacts (
  id smallint(5) unsigned NOT NULL auto_increment,
  name varchar(30) NOT NULL default '',
  created_on timestamp(14) NOT NULL,
  updated_on timestamp(14) NOT NULL,
  PRIMARY KEY (id),
  UNIQUE KEY name_key (name)
) TYPE=MyISAM COMMENT='List of Contacts';
[~/Sites]$ cat AddressBook.sql | mysql

この最初のテーブルでは、注意しなければならないことがいくつかあります。最も重要なことは、すべてのテーブルにidという名前のid列が必要なことです。Railsは、さまざまな記録管理タスクや参照タスクに主キー列idを使用します。created_onフィールドおよびupdated_onフィールドは必須ではありませんが、これらのフィールドを指定すると、Railsが自動的に保持します。ほとんどの場合、これらのタイムスタンプを使用しても問題はありません。したがって、ここで追加する唯一の「本当の」データは、アドレス・ブックの連絡先の名前です。

Railsでは、さまざまなものの単数形と複数形の名前の使い方も少し変わっています。さまざまな項目は、その用途とコンテキストに応じて、単数形と複数形で名前が変わります。テーブル名には複数形を使用する必要があります。筆者は不規則変化の複数形の単語で実験したことはありませんが、datumとdataのような単語を使用すると、Railsがエラーになるかもしれません。

AddressBookアプリケーションの生成

対話の相手であるデータベースができたので、次にAddressBookアプリケーションを作成します。最初のステップは、Railsを実行して、基本的なディレクトリーと足場コードを生成することです。

リスト3. 基本コードとディレクトリーの生成
[~/Sites]$ rails AddressBook
create
create  app/apis
create  app/controllers
create  app/helpers
create  app/models
create  app/views/layouts
create  config/environments
create  components
[...]
create  public/images
create  public/javascripts
create  public/stylesheets
create  script
[...]
create  README
create  script/generate
create  script/server
[...]

Railsの実行

AddressBook/ディレクトリーと必要な子ディレクトリーを作成したら、最小限の初期設定を行う必要があります。まず、YAML構成ファイルを次のように変更して、データベースを設定します。

リスト4. データベース・アクセスの構成
[~/Sites]$ cd AddressBook
[~/Sites/AddressBook]$ head -6 config/database.yml # after editing
development:
  adapter: mysql
  database: AddressBook
  host: localhost
  username: some_user
  password: password_if_needed

最後に、データを提供する必要があります。Railsには独自の単機能WebサーバーWEBrickが付属していて、この実験に最適です。Apacheやその他のサーバーを構成して、FCGI(またはプレーンCGI、ただし、プレーンCGIは低速です)経由でRailsアプリケーションを提供するには、Rubyon Rails Webサイトの説明に従ってください。

リスト5. WEBrickサーバーの起動
[~/Sites/AddressBook]$ ruby script/server -d
=> Rails application started on http://0.0.0.0:3000
[2005-03-21 17:57:38] INFO  WEBrick 1.3.1
[2005-03-21 17:57:38] INFO  ruby 1.8.2 (2004-12-25) [powerpc-darwin7.8.0]

小さなコンテンツの作成

ここまでのステップで、WEBrickポート上のウェルカム・ページを表示するには十分のはずです。たとえば、筆者のローカル・システムでは、http://gnosis-powerbook.local:3000/を見ることができます。しかし、カスタム・データベースを操作するために、もう少しだけコードを生成する必要があります。これはgenerateスクリプトで行うことができます。このスクリプトは、AddressBook/アプリケーション・ディレクトリーに作成されています。

リスト6. 足場モデルおよびコントローラーのコード生成
[~/Sites/AddressBook]$ ruby script/generate model contact
      exists  app/models/
      exists  test/unit/
      exists  test/fixtures/
      create  app/models/contact.rb
      create  test/unit/contact_test.rb
      create  test/fixtures/contacts.yml
[~/Sites/AddressBook]$ ruby script/generate controller contact
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/contact
      exists  test/functional/
      create  app/controllers/contact_controller.rb
      create  test/functional/contact_controller_test.rb
      create  app/helpers/contact_helper.rb

ここでは、該当するテーブル名に複数形であるcontactsではなく単数形のcontactを使用する必要があるので注意してください。

次に、生成されたもう1つのファイルを少しだけ編集して、コントローラーに足場を使用するように指示する必要があります。

リスト7. コントローラーに対する足場の使用の指示
[~/Sites/AddressBook]$ cat app/controllers/contact_controller.rb
class ContactController < ApplicationController
  model :contact
  scaffold :contact
end

これで、http://rails.server/contact/などのURL(筆者のテスト・ケースでは、http://gnosis-powerbook.local:3000/contact/)でデータベースの内容を表示したり変更することができるようになります。小さなデータを入力した後は、図1と図2のようになります。

図1. 連絡先のリスト
図1. 連絡先のリスト
図2. 連絡先の編集
図2. 連絡先の編集

カスタマイズ可能なコンテンツの作成

前のコードで、データベースの表示と変更のための十分に実用的なインターフェースが作成されますが、(前の例に示されているような)書式化、プレゼンテーション、およびビジネス・ロジックのすべては、高度な知識がなくても、Railsによって動的に行われます。もう少しカスタムなものを作成するためには、もう少しコードを生成する必要があります。ここで必要なことは、Railsが自動的・暗黙的に生成する足場を明示的に書き出させて、変更を加えられるようにすることです。

リスト8. 明示的なコントローラーおよびビューのコード生成
[~/Sites/AddressBook]$ ruby script/generate scaffold Contact
  dependency  model
      [...]
      create  app/views/contacts
      exists  test/functional/
      create  app/controllers/contacts_controller.rb
      create  test/functional/contacts_controller_test.rb
      create  app/helpers/contacts_helper.rb
      create  app/views/layouts/contacts.rhtml
      create  public/stylesheets/scaffold.css
      create  app/views/contacts/list.rhtml
      create  app/views/contacts/show.rhtml
      create  app/views/contacts/new.rhtml
      create  app/views/contacts/edit.rhtml

さて、もう少し作業が必要なので、少しだけ手を加えてみましょう。(このコードでは複数形のcontactsに戻っています。理由はよくわかりません。とりあえず、そういうものだと思うしかありません。)CSSで色とフォントを変えてみましょう。

リスト9. カスケーディング・スタイルシートの構成
[~/Sites/AddressBook]$ head -8 public/stylesheets/scaffold.css
body { background-color: #ffe; color: #338; }
body, p, ol, ul, td {
  font-family: verdana, arial, helvetica, sans-serif;
  font-size:   13px;
}
td { border: 1px solid; }
a { color: #eef; background-color: #446; }
a:hover { color: #fff; background-color:#000; }

コードはできましたが、contacts_controller.rbは何をするのでしょう。前のコードで見たcontact_controller.rbよりも、アクションが明示的かつ構成可能です。部分的に、コントローラーは次のようになります。

リスト10. コントローラーapp/controllers/contacts_controller.rb
class ContactsController < ApplicationController
  def list
    @contacts = Contact.find_all
  end
  def show
    @contact = Contact.find(@params['id'])
  end
  def create
    @contact = Contact.new(@params['contact'])
    if @contact.save
      flash['notice'] = 'Contact was successfully created.'
      redirect_to :action => 'list'
    else
      render_action 'new'
    end
  end

約束どおり、コントローラーの主な仕事は、データを変数にロードすることです。オブジェクトContactは、モデルが提供するActiveRecordオブジェクト/リレーショナル・マッピングです。変数@contactsまたは@contactには、適切なメソッドでデータが与えられます。メソッド自体は、http://rails.server/contacts/show/2などのURLによって参照されます(このURLは、idが「2」の連絡先を表示します)。

この例のコントローラーは、最終的にビューに接続します。すなわち、コントローラーによって変数にロードされたデータを利用するRHTMLファイルに接続します。たとえば、listビューの一部を以下に示します。

リスト11. リスト・ビューapp/views/contacts/list.rhtml
[...]
<% for contact in @contacts %>
  <tr>
  <% for column in Contact.content_columns %>
    <td><%=h contact.send(column.name) %></td>
  <% end %>
    <td><%= link_to 'Show', :action => 'show', :id => contact.id %></td>
    <td><%= link_to 'Edit', :action => 'edit', :id => contact.id %></td>
    <td><%= link_to 'Destroy', :action => 'destroy', :id => contact.id %></td>
  </tr>
<% end %>
[...]

メソッドContactsController.listは変数@contactsをロードして、RHTML内のフロー制御タグが配列から個々のレコードを抽出します。


モデルの変更

最初のモデルに含まれていたのは、連絡先の名前だけでした。あいにく、この記事では、電話番号、住所、電子メールなど、実際の連絡先データを含むようにモデルを拡張する紙面の余裕がありません。一般に、このようなデータは、子テーブルに格納されて、外部キーでcontactsテーブルと関連付けられます。Railsモデルは、次のようなカスタム・コードによってリレーションを示します。

リスト12. カスタム・コードapp\models\phone.rb
class Phone < ActiveRecord::Base
  belongs_to :contact
end

最後に、データ・モデルに少しだけ手を加えて、それがアプリケーションにどのような影響を与えるかを見てみましょう。まず、列を追加します。

リスト13. first_met日付をモデルに追加する
$ cat add-contact-date.sql
USE AddressBook;
ALTER TABLE contacts ADD first_met date;
$ cat add-contact-date.sql | mysql

基本モデルhttp://rails.server/contact/(足場の舞台裏バージョン)を変更したので、後は簡単な調整を加えるだけです。コントローラーとビューは、モデルに基づいて完全に自動生成されます。しかし、http://rails.server/contacts/にあるアプリケーション・バージョンには、カスタマイズしたファイルがあるので、完全自動化はできません。

listビューは、テンプレート・ループの一部としてContact.content_columnsを含んでいるので、どんな列であれ、すべての列を自動的に探し出します。しかし、editなど、他のビューはすでに生成されているので、新しいデータ・フィールドを追加する必要があります。たとえば、次のようにします。

リスト14. editビューapp/views/contacts/edit.rhtml
<h1>Editing contact</h1>
<%= error_messages_for 'contact' %>
<%= start_form_tag :action => 'update' %>
<%= hidden_field 'contact', 'id' %>
<p><label for="contact_name">Name</label><br/>
  <%= text_field 'contact', 'name'  %></p>
<p><label for="first_met">Known Since</label><br/>
  <%= date_select "contact", "first_met", :use_month_numbers => false %></p>
<input type="submit" value="Update" />
<%= end_form_tag %>
<%= link_to 'Show', :action => 'show', :id => @contact.id %> |
<%= link_to 'Back', :action => 'list' %>

さて、カスタマイズしたアプリケーションはどうなったでしょうか。デフォルトとの違いはそれほどありませんが、図3と4で変更箇所を見ることができます。

図3. 変更後の連絡先のリスト
図3. 変更後の連絡先のリスト
図4. 変更後の連絡先の編集
図4. 変更後の連絡先の編集

まとめ

Railsを使用すると、柔軟性のあるWebアプリケーションを非常に短時間で開発することができます。この記事では、Railsでの作業がどのようなものか、ほんの少しだけ紹介しました。完全なフレームワークには、Webベースのアプリケーションでよく使用されるアクションを実行するための便利なクラスとメソッドが多数含まれています。

Railsの最もよい点は、必要なサポート・コードのすべてが付属しているので、「Rails流の考え方」を身につけられることです。これは、作業対象となる生の材料を与えるだけの他のツールキットやフレームワークにはない大きな利点です。Rails開発は、漠然としたアイデアから完全に機能するWebアプリケーションへの明確な道筋を示してくれます。

参考文献

  • Deploy an application with Cerise Web server」(developerWorks, 2005年2月)は、Cerise WebサーバーとRubyを使ってゲストブックWebアプリケーションを作る方法を解説しています。
  • Ruby on Railsのホームページには、入門用のチュートリアルや案内、ダウンロード可能なソースやドキュメンテーションなどが用意されており、Rubyの手始めとして最適です。
  • Ruby on Railsがサポートするデータベース(IBM DB2も含まれています)のリストを見るためには、Database Driversのページを見てください。
  • この10分間のビデオは、誰かがRubyベースのWebアプリケーションを開発する場合の、実際の様子を紹介しています。
  • Wikipediaには、MVC方式のアーキテクチャーに関して、素晴らしい項目が挙げられています。
  • developerWorksのLinuxゾーンには、Linux開発者のための資料が他にも豊富に用意されています。
  • developerWorks blogsに参加して、developerWorksのコミュニティーに加わってください。
  • Developer BookstoreのLinuxセクションでは、Linux関係の書籍が割り引きで購入できますので、ぜひご利用ください。
  • 皆さんの次期Linux開発プロジェクトを、IBM trial softwareを使って革新してください。developerWorksから直接ダウンロードすることができます。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Linux, Open source, Web development
ArticleID=230508
ArticleTitle=Ruby on RailsによるWebアプリケーションの高速開発
publish-date=06242005