DB2 と Ruby on Rails: 第 1 回 DB2 と Ruby on Rails の導入

Rails アプリケーションを開発するための IBM_DB アダプターおよびドライバーのセットアップ

強力な Rails フレームワークを備えた Ruby 言語の登場により、Web ソリューションの開発には数え切れないほどの可能性が生まれています。さらに IBM_DB アダプターおよびドライバーが導入されたことから、今では Rails アプリケーションと IBM データ・サーバーとのシームレスな相互作用も可能になっています。連載「DB2® と Ruby on Rails」の第 1 回目となるこの記事では、Starter Toolkit for DB2 on Rails を紹介し、IBM_DB ドライバーをインストールするさまざまな方法、そして DB2 での Rails のマイグレーションについて説明します。

John Chun, DB2 Advanced Support Specialist, IBM

John Chun は、アプリケーション開発およびツールの分野で活躍する DB2 Advanced Support チームのスペシャリストです。IBM DBT Toronto Lab でこれまで 7 年間、Java、C、C++、Perl、REXX、C# をはじめとする各種言語での DB2 アプリケーション問題の解決に取り組んできました。DB2 CLI および OLEDB ドライバー、そして .NET データ・プロバイダー関連の多数のプロジェクトにも参加しています。彼は DB2 認定ソリューション・エキスパート、認定 Websphere アドミニストレーターでもあります。



Alex Pitigoi, Advisory Software Engineer, IBM

Alex Pitigoi は、IBM Toronto Lab の顧問ソフトウェア・エンジニアです。1998年以来、Web 技術とデータベース管理を専門に、情報管理の分野でのさまざまなソフトウェア開発プロジェクトに携わっています。最近では、SQLModel プロジェクトの開発を指揮しました。この開発は現在、Eclipse Data Tools プロジェクトならびに複数の IBM データ・サーバーで、データベース管理 Web ツールの全体的アーキテクチャーに組み込まれています。彼は DB2 Satellite Administration Center、IBM Express Runtime にも取り組んでおり、DB2 を対象とした最初の Web Tools セットの開発も主導しています。現在重点的に取り組んでいるのは、新しいオープン・ソース技術 (Ruby、Python、PHP) へのIBM データ・サーバー対応化です。



Naomi Ngan, Senior Software Engineer, Autonomy

Naomi Ngan は 2000年、カナダの University of Toronto でコンピューター・サイエンスと統計学の優等卒業学位を終了しました。卒業と同時に IBM に入社した彼女は、アプリケーション開発環境における IBM DB2 RDBMS 製品の欠点および問題の解決を担当しました。約 4 年間 IBM に在籍した後は UCSF の Ernest Gallo Clinic and Research Center に移り、バイオインフォマティクス・ソフトウェアの開発に携わっています。これには、Linux および Windows プラットフォームの XML 環境内でのデータベース・オブジェクト、JSP、Java スタンドアロン・アプリケーション、およびストアード・プロシージャーの設計と開発も含まれます。現在 Autonomy Corporation のシニア・ソフトウェア・エンジニアとして取り組んでいるのは J2EE エンタープライズ・ソフトウェアの開発です。DB2 のアプリケーションおよびツールに関する深い知識を持つ彼女は、DB2、XML、WebSphere、Java/J2EE の分野で数々の IBM および Sun 開発者認定を取得しています。



Christine Law, DB2 Advanced Support Specialist, IBM

Christine Law は、IBM Toronto Lab のシニア DB2 スペシャリスト兼 IBM 認定エキスパートです。JDBC、SQLJ、ストアード・プロシージャー、そして組み込みSQL を専門とする彼女は、さまざまなプログラミング言語とスクリプト言語を使った Linux、UNIX、Windows プラットフォームでの広範なアプリケーション開発経験を持っています。最近では、AJAXや Ruby などのオープン・ソース技術にも関心を寄せています。



2007年 5月 16日

はじめに

2004年にリリースされた Ruby on Rails は、瞬く間に Web アプリケーション開発で最もよく使用されるフレームワークの 1 つとなりました。Rails、あるいは RoR としても知られるこのオープン・ソース・プロジェクトでは、モデル・ビュー・コントローラー (MVC) アーキテクチャー、Ruby オブジェクト指向スクリプト言語、そして「設定より規約 (Convention over Configuration)」や「DRY (同じことを繰り返し記述しない: Don't Repeat Yourself)」などのわかりやすい原則を採り入れています。そのため開発者はアプリケーションを素早く簡単に、しかも冗長コードと構成ファイルを減らして作成できると同時に、それぞれのアプリケーションのニーズに応じて柔軟にカスタム拡張を作成することもできます。さらに Rails はデータベース・パーシスタンスのサポートを備えているため、このフレームワークを使用した Web アプリケーションはデータベース・サーバーと組み込み WEBrick Web サーバーを使って容易に開発することができます。

IBM_DB が Rails の世界にもたらすものとは

RubyForge コミュニティー・ポータルにリリースされた IBM_DB Rails アダプターおよび Ruby ドライバーは簡単に入手できることから、Ruby on Rails フレームワークはすべての DB2 データ・サーバーで正式にテストされ、サポートされています。驚かれる方もいるかもしれませんが、このコミュニティーでは DB2 Express-C という DB2 9 データベースの無料バージョンも使用できます。自由に開発、デプロイ、配布できる DB2 Express-C データ・サーバーにはサイズ、時間、それにユーザーに関する制限はありません。この DB2 Express-C も付属している Starter Toolkit for DB2 on Rails パッケージは、DB2 を使用した RoR 環境で開発者が素早く、そして難なく Web アプリケーションをセットアップし、作成できるようにします。

Rails フレームワークで構成できるデータ・ストアはさまざまにありますが、なかでも DB2 データ・サーバーは独特の卓越したメリットをもたらします。DB2 9 には pureXML™ が導入されていることから、IBM データ・サーバーで使用する場合には IBM_DB アダプターおよびドライバーがネイティブ XML データ型をサポートするという大きなメリットがあります。

DB2 on Rails の準備

DB2 を使用した Rails 開発環境をセットアップするには、現在 2 つの方法があります。DB2 環境の初心者には、Rails アプリケーション開発で最も簡単に DB2 を起動できるように設計された Starter Toolkit for DB2 on Rails が使いやすいはずです。alphaWorks からダウンロードできる Starter Toolkit バージョン 2.1 は、多少古いバージョンの IBM_DB アダプターをインストールします。このバージョンは i5 および zOS プラットフォームでは DB2 をサポートしませんが、現在更新が進んでいる最中なので間もなく最新のバージョンをダウンロードできるようになるはずです。

一方、既存の DB2 環境で Rails アプリケーションを開発する場合でも、IBM_DB アダプターおよびドライバー gem とプラグインがリリースされているため、同じく簡単な「手動」による方法を使えるようになっています。最新バージョンについては、RubyForge の rubyibm プロジェクトを参照してください (Production/Stable リリース 0.6.0 は 4月 30日から入手可能)。

DB2 Express-C 9 を使用したステップバイステップの手動インストール

まずは、DB2 Express-C データ・サーバーと Rails ランタイム環境をダウンロードして構成するところから始めましょう。IBM_DB アダプターおよびドライバーの最新バージョンには、DB2 9 の FixPack 2 または DB2 8 の FixPack 15 が必要です。以下の手順に従って、DB2 Express-C データ・サーバーと Rails ランタイム環境をダウンロードし、構成してください。

  • 次の Web サイトのリンクをクリックして DB2 Express-C 9 FixPack 2 をダウンロードします。
  • One-click Ruby Installer をダウンロードします (Ruby と Rubygems の両方が含まれています)。
  • Rails gem および、Rails gem と依存関係を持つファイルをインストールします。

    gem install rails --include-dependencies

注意

注 1: DB2 Client 9 FP2 は CLI (Call Level Interface) の修正 (数値の引用に関連) に必要なファイルです。この修正を適用すると、IBM_DB ドライバーおよびアダプターの双方に重要な変更が加えられます。

注 2: DB2 9 でのほとんどの Rails アプリケーションには、1024 以上の APPLHEAPSZ が必要です。

db2 update db cfg for <database_name> using APPLHEAPSZ 1024

db cfg を更新した場合は、DB2 を再起動してください (db2stop に続いて db2start を実行)。

最新の Starter Toolkit for DB2 on Rails では上記の値がデフォルトとなっているので、この注はIBM_DB アダプターおよびドライバーを手動でインストールする場合 (2番目のインストール方法) にのみ適用されます。

IBM_DB アダプターおよびドライバーを Ruby gem または Rails プラグインとしてインストールした場合の比較

Ruby gem インストールと Rails プラグイン・インストールとの違いを理解できるよう、ここでランタイム環境について簡単に説明しておきます。

RubyGems は、Ruby ランタイム環境内でのライブラリーとアプリケーションの標準パッケージ化およびインストール・フレームワークです。バンドルごとに gem という名前のファイルが 1 つあります。gem はパッケージ・フォーマットにコンパイルされてから中央のリポジトリーに配布されるので、そこに保管された gem を使って、あるライブラリーの複数バージョンまたは、あるアプリケーションの複数バージョンを同時にデプロイすることができます。Linux ディストリビューションのパッケージ管理およびバンドル (.rpm、.deb) と同じく、これらの gem も、クエリーの実行や、インストール、アンインストール、操作などを行う際に gem エンド・ユーザー・ユーティリティーを使用することができます。gem ユーティリティーは、リームレスにリモートの RubyForge 中央リポジトリーにクエリーを実行することもできますし、Rails 開発者の作業を楽にするために用意されている数々のユーティリティーを検索してインストールすることもできます。IBM_DB gem がインストールされるとすぐに、その機能には Ruby ランタイム環境のどのスクリプト (したがってアプリケーション) からでもアクセスできるようになります。そのために使用するコマンドは以下のとおりです。

  • require 'rubygems'
  • gem 'ibm_db' (Rubygems 0.9 で require_gem が非推奨となり、gem に置き換えられています。)

ActiveRecord アダプターである IBM_DB gem は、抽象アダプターによって RAILS_CONNECTION_ADAPTERS (active_record.rb) という ActiveRecord アダプターのリストに登録されてからでないと Rails フレームワークでは使用できません。IBM_DB gem が登録されると、IBM_DB gem はその依存関係ファイル ((ibm_db Ruby ドライバー、および IBM Driver for ODBC and CLI) とともにロードされ、それによって Ruby 環境内のあらゆるアプリケーション (Rails を含む) が IBM データ・サーバーと相互作用できるようになります。IBM_DB gem の README ファイル (この記事の「参考文献」セクションを参照) で説明しているように、いくつかの単純なステップに従うだけで、IBM データ・サーバーへのアクセスに Ruby ランタイムを使用できるようになります。

注意

注 3: Windows 環境では「gem install ibm_db」の実行中に、各リリース (mswin32 または ruby) につき 2 つの選択肢が提示されます。Windows 用にあらかじめビルドされたバイナリー・ファイルをインストールするには、「mswin32」を選択してください。

例:

D:\>gem install ibm_db
Bulk updating Gem source index for: http://gems.rubyforge.org
Select which gem to install for your platform (i386-mswin32)
 1. ibm_db 0.6.0 (mswin32)
 2. ibm_db 0.6.0 (ruby)
 3. ibm_db 0.4.6 (ruby)
 4. ibm_db 0.4.6 (mswin32)
 5. Skip this gem
 6. Cancel installation

IBM_DB アダプターおよびドライバーを Ruby Gem としてインストールする方法

  1. gem コマンドを実行して IBM_DB アダプターおよびドライバーをインストールします。

    D:\>gem install ibm_db
  2. Rails フレームワークの接続アダプター・リストに「ibm_db」を登録します。

    ibm_db を手動で gems\1.8\gems\activerecord-1.15.3\lib\active_record.rb に追加します。

    RAILS_CONNECTION_ADAPTERS = %w( mysql postgresql sqlite ... ibm_db )

Rails プラグインにはフレームワーク独自の拡張メカニズムがあります。Rails はこのメカニズムを利用して、その機能を個々の Rails アプリケーションのスコープ内で拡張します。したがって、Ruby ランタイム環境に IBM_DB gem がデプロイされていない場合には、このプラグインが IBM データ・サーバーにアクセスするための別の方法を提供します。Rails プラグインには Ruby gem 専用のバージョン管理機能はありませんが、Rails レジストリーの初期化中に IBM_DB プラグインを Rails レジストリーに自動挿入する便利な初期化メカニズムが備わっています。そのため IBM_DB をプラグインとしてアプリケーションにインストールした場合には、Rails フレームワークに IBM_DB プラグインをロードさせるための手動ステップを行う必要はありません。IBM_DB プラグインの README ファイル、そして RubyForge の rubyibm プロジェクトのドキュメントにも記載されているように、IBM_DB プラグインのソースを登録して Rails アプリケーション・インストール・スクリプトを実行するだけで、Rails アプリケーションが IBM データ・サーバーにアクセスできるようになります。RubyForge ではまだ SVN (Subversion) リポジトリーへの HTTP アクセスができないので (このプロジェクトでサポートしているのは現在、SVN プロトコルのみです)、Windows での Rails プラグイン・インストールには SVN クライアント・インストールが必要です。Linux® ディストリビューションと UNIX® ディストリビューションのほとんどでは SVN クライアントがデフォルトで利用可能になっているので、IBM_DB プラグインはかなりシームレスにインストールすることができます。


クライアント環境

IBM_DB アダプター (ibm_db_adapter.rb) が直接依存関係を持つ ibm_db ドライバーは、IBM Driver for ODBC (Open Database Connectivity) and CLI (Call Level Interface) を使って IBM データ・サーバーに接続します。IBM CLI は、IBM データ・サーバーに対する呼び出し可能な SQL インターフェースであり、ODBC に準拠しています。

このことが IBM_DB アダプターおよびドライバーに及ぼす影響は以下のとおりです。

  1. IBM Driver for ODBC and CLI がインストールされたシステムは IBM_DB 要件に適合しなければなりません。

    IBM Driver for ODBC and CLI は、完全な DB2 データベース・インストールによって入手することも、「IBM DB2 Driver for ODBC and CLI の概要」から個別のコンポーネントとして取得することも可能です。

  2. Ruby アプリケーション外部でのドライバーの振る舞いは、CLI キーワードを使って変更することができます。

    Rails アプリケーション外部でのトランザクションの振る舞いは、CLI キーワードを使って変更することができます。CLI キーワードを使用して、例えば現行のスキーマを設定したり、トランザクションの要素を変更 (自動コミット動作をオフにするなど) したりすることができます。CLI キーワードについての詳細は、以下の DB2 インフォメーション・センターの資料に記載されています。

    バージョン 8

    バージョン 9

  3. 診断を収集するには CLI ドライバーのトレース機能が必要です。

    IBM_DB ドライバーを介した要求はすべて、IBM Driver for ODBC and CLI が提供する API を使って実装されるため、IBM_DB アダプターおよびドライバーを使用するアプリケーションでの問題を特定するには、CLI トレースが重要なトレース・メカニズムとなります。

    CLI トレースでは、アプリケーションが IBM Driver for ODBC and CLI に対して行ったすべての API 呼び出し (すべての入力パラメーターを含む) が取り込まれるとともに、ドライバーからアプリケーションに返されたすべての値が取り込まれます。アプリケーションと IBM Driver for ODBC and CLI とのやりとりを取り込むことを目的に設計されたこのインターフェース・トレースにより、ドライバーの内部動作についての情報がわかります。

    バージョン 8

    バージョン 9


データベース・スキーマの進化

絶え間なく変化する環境では、新しい要件と問題にアプリケーションが動的に適応しなければなりません。アプリケーション開発者が、例えば新しいオブジェクトまたはクラスを追加するなどしてアプリケーションを変更するときには、基礎となるパーシスタンスを変更してデータベースを確実にアプリケーションと同期させる必要が生じます。データベース・スキーマを変更する従来の方法は、新しい SQL スクリプトを生成することですが、アプリケーションとデータベースの両方を SQL スクリプトによってバージョン順に維持するのは困難です。その上、データベース開発者がアプリケーションの変更に伴ったデータベース・スキーマの変更を元に戻すための SQL スクリプトを作成することはめったにありません。変更を元に戻す場合、大抵の開発環境ではすべてのデータベース・オブジェクトを削除し、SQL (DDL (Data Definition Language)) スクリプトの前のバージョンを使ってデータベース・オブジェクトを一から作成しなおすという方法が採られています。

多くの Web 開発者が Rails に驚かされる点は、マイグレーションによるスキーマ進化のサポートが組み込まれていることです。データベース開発者は当然、DDL や DML (Data Manipulation Language) で SQL を使用することを好みますが、その一方、ほとんどのアプリケーション開発者は自分たちのツールである Ruby 言語とそのライブラリーを使用することにこだわります。これがまさに、Rails がマイグレーションによって可能にすることです。つまり、ActiveRecord という抽象ライブラリーを利用して、バージョン順に表や列などのデータベース・オブジェクトを作成および変更する、単純かつ効率的なインフラストラクチャーを実現するということです。Rails マイグレーションは、スキーマの進化に関連するデータベース管理タスクの大部分を引き受けます。開発を単純化するのは Rails フレームワークですが、データベースの変更を制御し、アプリケーション・コードをその表構造に同期させる上では関連するツール (rake タスク) も非常に効果的です。

Rails マイグレーションによる DB2 スキーマの進化

Ruby on Rails マイグレーションは、上記で説明したデータベースとデータ構造の変更に関わる問題のいくつかを解決します。このセクションでは、Rails マイグレーションがデータベース・スキーマの変更を容易にする仕組みを検討します。

ここで取り上げる Rails マイグレーションの例では、IBM_DB アダプターを使用して、Rails アプリケーションの進化に合わせたデータベース・オブジェクトの変更を行います。ただしその前に、DB2 on Rails 開発環境が前述の手順に従ってインストールされ、構成済みであることを確認してください。

この例で作成する Team Room は、登録されたメンバーが画像、実行可能ファイル、プレゼンテーションやその他の媒体を含めたテキストまたはバイナリー・フォーマットの各種文書を共有できるようにするためのホスト・アプリケーションです。この例には XML 文書の共有も含まれており、pureXML データ型を使用すると XML 文書をそのまま簡単に DB2 9 に保管できることを説明します。また、この例から、組み込み階層化構造を賢く利用する方法もわかるはずです。

  1. まず始めに、「teamroom」という名前の Rails プロジェクトを作成します。

    リスト 1. Rails プロジェクト、Team Room の作成
    D:\rails>rails teamroom
          create
          create  app/controllers
          create  app/helpers
          create  app/models
          create  app/views/layouts
          create  config/environments
          create  components
          create  db
          
    <etc ......>
    
          create  log/server.log
          create  log/production.log
          create  log/development.log
          create  log/test.log

    Rails フレームワークはプロジェクトのディレクトリー構造を自動的に作成します。ここから先は現行ディレクトリーを D:\rails\teamroom という前提にし、以降に記載するすべてのパスは Team Room プロジェクト・ディレクトリー内での相対パスになります。

  2. 既存の DB2 データベースがある場合は、このステップを抜かしてステップ 3 まで進み、データベース接続の構成に取り掛かってください。

    Rails プロジェクトとデータベース

    Rails プロジェクトごとに新しくデータベースを作成する必要はありません。プロジェクトとデータベースを 1 対 1 で対応付けるという要件は設定されていないからです。

    ある時点で、XML を DB2 にネイティブに保管する必要が出てくることを見越し、UTF-8 コードセットを使用して XMLDB データベースを作成します。UTF-8 コードセットは、XML 列を DB2 の表に定義するために必要です。

    DB2 Command Line Processor から以下のコマンドを実行します。

    リスト 2. XMLDB データベースの作成
    db2 create db xmldb using codeset utf-8 territory us
  3. D:\rails\teamroom\config\database.yml ファイルを編集して、DB2 9 XMLDB データベースに接続できるようにします。

    リスト 3. database.yml ファイルの編集
    # IBM DB2 Database configuration file
    #
    # Install the IBM DB2 driver and get assistance from:
    # http://www.alphaworks.ibm.com/tech/db2onrails
    development:
      adapter:      ibm_db
      database:     xmldb
      username:     user
      password:     secret
      schema:       teamroom
      application:  TeamRoom
      account:      devuser
      workstation:  devbox
    # == remote TCP/IP connection (required when no local database catalog entry available)
    # host:         bigserver     // fully qualified hostname or IP address
    # port:         50000         // data server TCP/IP port number

以下の表に、DB2 の各接続属性についての説明を記載します。

表 1. database.yml で使用可能な DB2 接続属性
接続属性説明必要性
adapterRuby アダプターの名前。DB2 の場合は「ibm_db」です。必須
databaseRails プロジェクトが接続するデータベース必須
usernameDB2 データベースに接続するために使用するユーザー ID必須
password指定したユーザー ID に対応するパスワード必須
schema名前付きオブジェクトのコレクション。スキーマは、データベース内でオブジェクトを論理的にグループ分けする手段です。この例では、Rails Team Room プロジェクトのすべてのデータベース・オブジェクトを「teamroom」データベース・スキーマとしてグループ化します。このようにすることで、複数の Rails プロジェクトが 1 つのデータベースを共有できるようになります。オプション。現行セッションのユーザーが持つ許可 ID には、デフォルトのスキーマを設定できます (注 4 を参照)。
applicationDB2 Connect の使用時にホスト・データベース・サーバーに送信される、クライアント・アプリケーション名を識別するための文字列。DB2 Connect で「db2 list applications」を実行すると、Ruby 実行可能ファイルの代わりに、この属性で指定した「application」の名前が表示されることになります。オプション
accountDB2 Connect の使用時にホスト・データベース・サーバーに送信される、クライアントのアカウント情報ストリングを識別するための文字列オプション
workstationDB2 Connect の使用時にホスト・データベース・サーバーに送信される、ワークステーション名を識別するための文字列オプション
hostデータベースが常駐するリモート・サーバーのホスト名オプション (注 5 を参照)
portこのパラメーターには、データベース・サーバーがリモート・クライアントからの通信を待機するために使用する TCP/IP ポートの名前が設定されます。オプション (注 5 を参照)

注意

注 4: 必ず明示的にスキーマを指定すること

スキーマを明示的に指定してデータベース・オブジェクトを論理的にグループ化することを強くお奨めします。スキーマが明示的に指定されていないと、多くの Rails プロジェクトで共有する 1 つのデータベースに同じ許可 ID で接続した場合、複数の Rails プロジェクトが同じ <AuthID>.schema_info 表に書き込んでしまうことによって、予期せぬ結果がもたらされるおそれがあります。Schema_info はマイグレーション・バージョンを追跡するための表です。詳細は、以下の「Team Room の例」で説明します。

注 5: リモート TCP/IP 接続に関連付けられたオプションの接続属性である host 属性と port 属性は、DB2 カタログ情報が利用できず、DB2 CLI の db2cli.ini 構成ファイルにデータ・ソースが 1 つも登録されていない場合にのみ必須となります。このような設定は、ローカル側にインストールされた完全な DB2 Client ではなく、IBM Driver for ODBC and CLI を使用する場合に考えられます。

Team Room の例

ここからは、いよいよ実際のマイグレーション・ステップを実行していきます。

ステップ 1: DOCUMENTS 表を作成する

最初に必要なのは、このホスト対象アプリケーションのユーザーがすべての文書とメディア・ファイルを共有するためのストレージ領域です。そこで、DOCUMENTS 表を作成して、チームのメンバーが共有したいと考えるすべてのメディア・ファイルを保管できるようにします。

共有ファイルの内容を記述するために、以下の列を定義します。

表 2. DOCUMENTS 表の列とその説明
列名データ型説明
IDInteger主キー
NameVARCHAR文書の名前
SizeIntegerファイルのサイズ
DataBLOBバイナリー・モードで保管されたファイル (最大サイズは 2 メガバイト)
Content_typeVARCHAR文書タイプ (.doc、.ppt、.pdf、.sw、.exe、.a、.so、.gif、.jpeg、.mov、.avi、.mpeg、.bmp などのファイル・タイプを含みます)

a) この表をマイグレーションによって作成するには、ruby script\generate migration create_docs_store を実行して DOCUMENTS 表のマイグレーションを生成します。すると Rails が DOCUMENTS 表のマイグレーションを生成するとともに、db/migrate/001_create_docs_store.rb を作成します。UNIX の場合には ruby script/generate migration create_docs_store と入力します (スラッシュ「/」は Windows と UNIX の両方で有効です)。

リスト 4. ruby script/generate migration create_docs_store の実行
D:\rails\teamroom>ruby script/generate migration create_docs_store
      create  db/migrate
      create  db/migrate/001_create_docs_store.rb

db/migrate に 001_ create_docs_store.rb. が作成され、その番号が「001」であることに注目してください。このステップ以降は、マイグレーションのステップを行うたびに順番に番号が付けられたファイルが db/migrate 内に作成されます。つまり、マイグレーションの順序は Rails によって自動的に管理されるということです。

b) create_docs_store.rb を以下のように編集します。

リスト 5. create_docs_store.rb の編集
class CreateDocsStore < ActiveRecord::Migration
  def self.up
    create_table :documents do |t|
      t.column :name,         :string,  :null  => false
      t.column :size,         :integer, :null  => false
      t.column :content_type, :string,  :null  => false
      t.column :data,         :binary,  :limit => 2.megabytes
    end
  end

  def self.down
    drop_table :documents
  end
end

注意

注 6: デフォルトでは、表の名前は複数形になります

Rails のデフォルトでは、複数形で表の名前が付けられます。したがって、上記のマイグレーションを実行すると、DB2 に作成される表の名前はDOCUMENT ではなく、DOCUMENTS となります。

注 7:rake db:migrate はまだ適用されていないすべてのマイグレーションを実行します。ただし、この例で適用するマイグレーションは 1 つしかありません。

Rails アプリケーションでは、スキーマの変更はマイグレーションによって行われます。データベース・スキーマに対するそれぞれの変更にはバージョン番号が付けられ、Ruby スクリプトに定義されます。これらの Ruby スクリプトには、ベンダーに依存しない構文が含まれます。さらに変更を取り消すのも、変更するのと同じくらいに簡単です。それは、各マイグレーション・スクリプトには up メソッドと down メソッドという 2 つのクラス・メソッドがあるからです。論理データベース・スキーマの 1 回の変更ごとに必要なすべてのコードは self.up メソッド内に配置され、変更の取り消しに必要なあらゆるコードは self.down メソッド内に配置されます。

c) rake db:migrate コマンドを使ってマイグレーションを実行します。

リスト 6. DOCUMENTS 表を作成するための最初のマイグレーションの実行
D:\rails\teamroom>rake db:migrate
(in D:/rails/teamroom)
== CreateDocsStore: migrating =================================================
-- create_table(:documents)
   -> 0.2010s
== CreateDocsStore: migrated (0.2010s) ========================================

d) 今度は DB2 コマンド・プロンプトに移動して db2 list tables for schema teamroom を実行し、DOCUMENTS 表が作成されたことを確認します。

リスト 7. 作成された DB2 表のリスト
D:\>db2 list tables for schema teamroom

Table/View                      Schema          Type  Creation time
------------------------------- --------------- ----- --------------------------
DOCUMENTS                       TEAMROOM        T     2007-04-21-21.00.18.131001
SCHEMA_INFO                     TEAMROOM        T     2007-04-21-21.00.17.740001

  2 record(s) selected.

作成された DOCUMENTS 表には期待通り、以下のデータ型が設定されているはずです。

リスト 8. DOCUMENTS 表に作成された列の確認
D:\>db2 describe table teamroom.documents

Column                         Type      Type
name                           schema    name               Length   Scale Nulls
------------------------------ --------- ------------------ -------- ----- ------
ID                             SYSIBM    INTEGER                   4     0 No
NAME                           SYSIBM    VARCHAR                 255     0 No
SIZE                           SYSIBM    INTEGER                   4     0 No
DATA                           SYSIBM    BLOB                2097152     0 Yes
CONTENT_TYPE                   SYSIBM    VARCHAR                 255     0 No

  5 record(s) selected.

注 8: 主キーの自動作成

Rails では、主キーの列のデフォルトの名前は id です。主キーの ID 列はデフォルトで Rails が定義してくれるので、明示的に定義する必要はありません。

このマイグレーションのステップでは、Rails が SCHEMA_INFO というもう 1 つの表を作成したことにも注目してください。SCHEMA_INFO は rake db:migrate コマンドによって作成された表です。SCHEMA_INFO 表にクエリーを実行すると、以下の出力が表示されます。

リスト 9. SCHEMA_INFO 表へのクエリー
D:\>db2 select * from schema_info

VERSION
-----------
          1
          
  1 record(s) selected.

VERSION 列の値「1」は、マイグレーションのバージョンが 1 であることを示します (実行したのは db/migrate/001_ create_docs_store.rb であることを思い出してください)。

このように、rake db:migrate は基本的に以下の操作すべてを行います。

  • SCHEMA_INFO 表が存在しない場合にはこれを作成し、VERSION 列に値「0」を挿入します。
  • 適用可能なすべてのマイグレーションを実行します。つまり、現行のマイグレーションより昇順で大きい番号を持つすべてのマイグレーションの up メソッドを実行するということです。最初のマイグレーションでは、バージョンの値が「1」になります。
  • SCHEMA_INFO 表を最新バージョンのマイグレーション実行で更新します。上記の例では、Rails プロジェクトの最初のマイグレーションであるため、バージョンは「1」に更新されます。

ステップ 2: 文書に関連付ける属性を追加する

DOCUMENTS 表を作成した後に、例えば各文書に関する追加情報としてオペレーティング・システム・プラットフォーム、アップロード時刻、最終変更時刻を保管することにしたとします。この場合、最終的な DOCUMENTS 表には以下の列が含まれることになります (新しく追加する列は太字で記載)。

表 3. DOCUMENTS 表の列とその説明
列名データ型説明
IDInteger主キー
NameVARCHAR文書の名前
SizeIntegerファイルのサイズ
DataBLOBバイナリー・モードで保管されたファイル (最大サイズは 2 メガバイト)
Content_typeVARCHAR文書タイプ (.doc、.ppt、.pdf、.sw、.exe、.a、.so、.gif、.jpeg、.mov、.avi、.mpeg、.bmp などのファイル・タイプを含みます)
Created_atTIMESTAMPファイルがアップロードされた時刻 (注 9 を参照)
Updated_atTIMESTAMP文書の最終更新タイムスタンプ (注 9 を参照)
PlatformVARCHARファイル・プラットフォーム固有の情報

注意

注 9: 2 つの列に選択されている created_atupdated_at という名前には、Rails の特殊なセマンティクスが含まれます。他の「マジックフィールド名」(id、type、position、lock_version、parent_id) と同じく、Rails はこれらの列名を慣例的に使用するため、この 2 つの列の値は行の作成または最終更新のタイムスタンプを使用して自動的に更新されます。この自動更新に必要なのは、基礎となるデータベース列が DATE 型、DATETIME 型、または STRING 型を受け取れるようにすることだけです。完全な Rails 規約では、日付を表す列には _on サフィックスを使用し、時刻が含まれる列には _at サフィックスを使用することになっています。

上記の属性を DOCUMENTS 表に追加するため、2 番目のマイグレーションを生成します。

a) ruby script/generate migration add_docs_attributes を実行します。

その結果、db/migrate/002_add_docs_attributes.rb ファイルが生成されます。

リスト 10. DOCUMENTS 表に列を追加するための 2 番目のマイグレーションの作成
D:\rails\teamroom>ruby script/generate migration add_docs_attributes
      exists  db/migrate
      create  db/migrate/002_add_docs_attributes.rb

注意

注 10: マイグレーションでは、永続データベース内の何かしらを変更する必要が生じた場合には、新しいマイグレーションを生成してその変更を実行します。変更を行うために既存のマイグレーションを編集することは決してありません。

b) 002_add_docs_attributes.rb を以下のように編集します。

リスト 11. SCHEMA_INFO 表へのクエリー
class AddDocsAttributes < ActiveRecord::Migration
  def self.up
    add_column :documents, :created_at, :timestamp
    add_column :documents, :updated_at, :timestamp
    add_column :documents, :platform,   :string,    :limit => 10
  end

  def self.down
    remove_column :documents, :created_at
    remove_column :documents, :updated_at
    remove_column :documents, :platform
  end
end

注意

注 11:self.up メソッドに属性を追加するには add_column を使用し、変更を元に戻すには remove_column を使用します。

c) 2 番目のマイグレーションを実行するために、ここでも rake db:migrate を実行します。

リスト 12. DOCUMENTS 表に列を追加するための 2 番目のマイグレーションの実行
D:\rails\teamroom>rake db:migrate
(in D:/rails/teamroom)
== AddDocsAttributes: migrating ===============================================
-- add_column(:documents, :created_at, :timestamp)
   -> 0.0500s
-- add_column(:documents, :updated_at, :timestamp)
   -> 0.0100s
-- add_column(:documents, :platform, :string, {:limit=>10})
   -> 0.0000s
== AddDocsAttributes: migrated (0.0600s) ======================================

注意

注 12: ここでもリスト 8 の場合と同じく db2 describe table teamroom.documents というコマンドを使って、新しい列が DOCUMENTS 表に追加されたことを確認できます。

注 13: <model_name>_id は、<model_name> で表される複数形の名前が付けられた表への外部キー参照のデフォルト名です。外部キーなどの関連は、Rails ではモデル間の関係によって設定されます。このモデル間の関係を管理するために Rails フレームワークが使用する重要な規約の 1 つは表の主キー列のデフォルト名 (id) で、表への外部キー参照のデフォルト名は <model_name>_id です (表の名前は <model_name> の複数形になります)。重要な点は、Rails マイグレーションでは外部キーの制約が定義されないということです。表同士の関係は、開発者が特定の関係にある表のキー値を列に入力すると設定されます。マイグレーションによってこのような制約もデータベースに設定し、実施することをお勧めしますが、Rails フレームワークの要件にはなっていません。

ステップ 3: ユーザーと、ユーザーからのリソースへのアクセスを管理する

これらの文書には組織やコミュニティーの多くの人々が興味を持つはずなので、そのようなユーザーと彼らのアクセスを管理する方法が必要になります。そのためにこれから追加するのが USERS 表です。また、外部キー「user_id」を DOCUMENTS 表に追加して、特定の文書をどのユーザーがアップロードしたかがわかるようにします。

この 2 つのタスクを実行するために必要なステップは以下のとおりです。

a) ruby script/generate migration create_users_table を実行します。これによって、db/migrate/003_create_users_table.rb ファイルが作成されます。

b) db/migrate/003_create_users_table.rb ファイルを以下のように編集します。

リスト 13. 003_create_users_table.rb の編集
class CreateUsersTable < ActiveRecord::Migration
  def self.up
    create_table :users do |t|      
      t.column :usertype,  :string, :limit => 5, :null => false
      t.column :firstname, :string, :limit => 30
      t.column :lastname,  :string, :limit => 30
      t.column :extension, :string, :limit => 4
    end
    add_column :documents, :user_id, :integer
  end

  def self.down
    drop_table :users
    remove_column :documents, :user_id
  end
end

c) rake db:migrate を実行して USERS 表を作成します。

リスト 14. マイグレーションによる USERS 表の作成
D:\rails\teamroom>rake db:migrate
(in D:/rails/teamroom)
== CreateUsersTable: migrating ================================================
-- create_table(:users)
-> 0.1400s
-- add_column(:documents, :user_id, :integer)
-> 0.0000s
== CreateUsersTable: migrated (0.1400s) =======================================

d) ここで ruby script/generate scaffold document を実行すれば、DOCUMENTS 表の scaffold を生成することができます。素早く scaffold を作り、クラスのオブジェクトを一覧表示、表示、作成、更新、そして破棄する標準アクションを設定することで、Active Record クラスはオンライン状態になります。リスト 15 に示すように、scaffold を生成すると /app/controllers と /app/views 内にコントローラー、そして多数のビューが作成されます。

リスト 15. 文書の scaffold の作成
D:\rails\teamroom>ruby script/generate scaffold document
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/documents
      create  app/views/layouts/
      create  test/functional/
  dependency  model
      create    app/models/
      exists    test/unit/
      exists    test/fixtures/
      create    app/models/document.rb
      create    test/unit/document_test.rb
      create    test/fixtures/documents.yml
      create  app/views/documents/_form.rhtml
      create  app/views/documents/list.rhtml
      create  app/views/documents/show.rhtml
      create  app/views/documents/new.rhtml
      create  app/views/documents/edit.rhtml
      create  app/controllers/documents_controller.rb
      create  test/functional/documents_controller_test.rb
      create  app/helpers/documents_helper.rb
      create  app/views/layouts/documents.rhtml
      create  public/stylesheets/scaffold.css

これで、scaffold がどのように役立つかを検討する準備は万全です。コマンド・プロンプトに ruby script/server と入力し、Rails の組み込み WEBrick Web サーバーを起動してください。

リスト 16: 組み込み WEBrick Web サーバーの起動
D:\rails\teamroom>ruby script/server
=> Booting WEBrick...
=> Rails application started on http://0.0.0.0:3000
=> Ctrl-C to shutdown server; call with --help for options
[2007-04-26 16:54:57] INFO  WEBrick 1.3.1
[2007-04-26 16:54:57] INFO  ruby 1.8.5 (2006-12-25) [i386-mswin32]
[2007-04-26 16:54:57] INFO  WEBrick::HTTPServer#start: pid=444 port=3000

ポート番号に注意してください。デフォルトは 3000 ですが、システムで既にポート 3000 を使用している場合には他の番号になる可能性があります。Web ブラウザーを開いて http://localhost:3000/ にアクセスするとウェルカム・メッセージ (Welcome aboard) が表示されるので、http://localhost:3000/documents までブラウズしてください。すると、以下の画面が表示されるはずです。

図 1. 文書のリスト
文書のリスト

e) 生成された /app/models/document.rb ファイルを以下のように編集します。

リスト 17. /app/models/document.rb の編集
class Document < ActiveRecord::Base
  belongs_to :user
end

belongs_to が表すのは、DOCUMENTS 表と USERS 表との 1 対 1 の外部キー関係です。この関連では、各文書には 1 人のユーザーしか関連付ける (属する) ことができません。DOCUMENTS 表に user_id 外部キー列がある場合には、文書モデルは belongs_to :user となります。

注意

注 14: 外部キーが含まれる表のモデルは常に belongs_toを宣言します。

app/models/document.rb には、実際に文書をアップロードしてファイルを DB2 9 データベースに保管できるよう、コードを追加してあります (コードの実装については、「ダウンロード」セクションを参照してください)。したがって、Team Roomに文書をいくつか追加すると、ブラウザーには以下のような画面が表示されます。

図 2. 文書のリスト
文書のリスト

f) ここでも同じく ruby script/generate scaffold user を実行して USERS 表の scaffold を生成してから、app/models/user.rb を以下のように編集します。

リスト 18. /app/models/user.rb の編集
class User < ActiveRecord::Base
   has_many :document
end

注意

注 15:has_many の関連は、ユーザーが複数の文書をアップロードできることを意味します。

注 16: ActiveRecord 関連の詳細は、 http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html を参照してください。

マイグレーションについて、最初のいくつかのステップを詳しく説明したので、残りの必要な表と関連を作成するためのマイグレーションについては簡単に説明することにします。

ステップ 4: 増え続ける共有文書のコレクションをマイグレートする

ここで当然役に立つのは、今後コミュニティーが提供する多大な数の文書をカテゴリー分けする手段です。そのような手段があれば、コンテンツのサブジェクトを基準とした分類が可能になります。そこで、文書をカテゴリー分けできるようにするための SUBJECTS 表を作成することにします。1 つのサブジェクトには多くの文書が含まれますが、それぞれの文書が属するサブジェクトは 1 つだけです。この SUBJECTS と DOCUMENTS との 1 対多の関係を表すには、Subject ID 外部キーを DOCUMENTS に追加する必要があります。

上記のタスクを実行するために必要なステップは以下のとおりです。

a) ruby script/generate migration create_subjects_table を実行します。これによって、db/migrate/004_create_subjects_table.rb ファイルが作成されます。

b) db/migrate/004_create_subjects_table.rb を以下のように編集します。

リスト 19. SUBJECTS 表の作成
class CreateSubjectsTable < ActiveRecord::Migration
  def self.up
    create_table :subjects do |t|
      t.column :name,         :string,     :limit => 20
      t.column :size,         :integer
      t.column :description,  :text
      t.column :tag,          :string,     :limit => 10 
    end
    add_column    :documents, :subject_id, :integer
  end

  def self.down
    drop_table    :subjects
    remove_column :documents, :subject_id
  end
end

c) rake db:migrate を実行して SUBJECTS 表を作成し、subject_id 外部キーを追加します。

d) ruby script/generate scaffold subject を実行して SUBJECTS 表の scaffold を生成します。

e) 新しく生成された /app/models/subject.rb ファイルに has_many :document 関連を追加します。

リスト 20. サブジェクト・モデルへの関連の追加
class Subject < ActiveRecord::Base
  has_many :document
end

f) ステップ 3 の (d) で生成された /app/models/document.rb ファイルに 2 つ目の関連として belongs_to :subject を追加します。

リスト 21. 文書モデルへの関連の追加
class Document < ActiveRecord::Base
  belongs_to :user
  belongs_to :subject

  <... code to assist with document uploading ...>
  <...                                        ...>
  
  end
end

ステップ 5: ユーザー通知の必要性を管理する

新しい文書が特定のカテゴリーにアップロードされたときに、ユーザーにそのことを通知できたら便利だと思いませんか? この種の通知要求を SUBSCRIPTIONS 表に収集すれば、ユーザーに通知するのはわけありません。この場合、ユーザー、サブジェクト、そしてサブスクリプションの関係も検討する必要があります。

まずユーザー・ケースのシナリオを説明すると、ユーザー Anthony はプログラミング、Linux、そして釣りという特定のサブジェクトに関する新しい文書がアップロードされるたびに通知を受け取りたいと思っています。彼はこれまでに作成されたすべてのサブジェクトが表示されたページをブラウズし、前述のサブジェクトに対応するボックスにチェック・マークを付けます。これ以降は、この 3 つのサブジェクトのいずれかに関する新しい文書がアップロードされるたびに、アプリケーションが通知メッセージを作成し、この 3 つのサブジェクトのいずれかをサブスクライブしているユーザーに E メールで送信されます。このシナリオはつまり、以下の関係で言い表すことができます。

  • 各ユーザーは最大で 1 つのサブスクリプションが可能ですが、サブスクリプションは必須ではありません (例えば、1 対なし、あるいは 1 対 1 の関係)。
    • SUBSCRIPTIONS 表には 外部キー user_id を追加する必要があります。
    • ユーザー・モデルとサブスクリプション・モデルの間には 1 対 1 の関係が必要です。
  • 各ユーザーのサブスクリプションにはお気に入りのサブジェクトをいくつか含めることができます (例えば、1 対多の関係)。ユーザーには有効なすべてのサブジェクトから選択するための手段が提供されます。
    • SUBJECTS 表には外部キー subscription_id を追加する必要があります。
    • サブスクリプション・モデルとサブジェクト・モデルの間には 1 対 多の関係が必要です。

上記のデータベースの設計目標は、以前使用したマイグレーション・ステップと同様の方法で達成します。

a) ruby script/generate migration create_subscriptions_table を実行して、db/migrate/005_create_subscriptions_table.rb ファイルを作成します。

b) db/migrate/005_create_subscriptions_table.rb を以下のように編集します。

リスト 22. SUBSCRIPTIONS 表の作成
class CreateSubscriptionsTable < ActiveRecord::Migration
  def self.up
    create_table :subscriptions do |t|
      t.column :name,         :string,  :limit => 20
      t.column :description,  :text
      t.column :user_id,      :integer
    end
    add_column    :subjects,  :subscription_id, :integer
  end

  def self.down
    drop_table    :subscriptions
    remove_column :subjects,  :subscription_id
  end
end

c) rake db:migrate を実行して SUBSCRIPTIONS 表を作成し、SUBJECTS 表に外部キーの列を追加します。

d) ruby script/generate scaffold subscription を実行して SUBSCRIPTIONS 表の scaffold を生成します。

e) ステップ 4 の d で生成された /app/models/subscription.rb ファイルに has_many :subject 関連を追加します。

f) 対応する belongs_to :subscription 関連を新しく生成された /app/models/subject.rb ファイルに追加します。

g) ステップ 3 の f で生成された /app/models/user.rb ファイルに has_one :subscription 関連を追加します。

h) 新しく生成された /app/models/subscription.rb ファイルに belongs_to :user 関連を追加します。

注意

注 17: 注意深い読者なら、現行のサブスクリプションに関する設計がまるで現実的でないこと、あるいは使いものにならないことにお気付きでしょう。それは、1 つのサブジェクトは 1 つのサブスクリプションにしか属せないため、Anthony が自分のサブスクリプション・ページで特定のサブジェクトにチェック・マークを付けると、Bob にはそのサブジェクトが選択できなくなるためです。当然、この関係は多対多であるべきですが、今回は単純にしておきます (例えば、今回は中間結合表を使用しません)。これについては、連載第 2 回で修正します。

ステップ 6: ユーザーの連絡先を管理する

ユーザーに Team Room の更新を通知する 1 つの方法は、E メールを使うことです。それには各ユーザーの E メール・アドレスを追加しなければならないため、別のマイグレーションによって USERS 表に email 列を追加します。

a) ruby script/generate migration addEmailToUser を実行します。これによって、db/migrate/006_add_email_to_user.rb ファイルが生成されます。

b) 006_add_email_to_user.rb を以下のように編集します。

リスト 23. USERS 表への E メール情報の追加
class AddEmailToUser < ActiveRecord::Migration
  def self.up
    add_column    :users, :email, :string, :limit => 30
  end

  def self.down
    remove_column :users, :email
  end
end

c) rake db:migrate を実行して email 列を USERS 表に追加します。

ステップ 1 からステップ 6 で行ったことを図にまとめると、以下のようになります。

図 3. さまざまなモデル間の関連
さまざまなモデル間の関連

ステップ 7: XML 文書を Team Room に保管する

今日のエンタープライズ環境では文書を XML フォーマットで保管しなければならない場合がますます増えてきています。必ずしもこのような卓越した構造化文書が一定の形を持たないバイナリー・オブジェクトと大幅に異なるものとして扱われるとは限りませんが、このアプリケーションでは敢えて、DOCUMENTS 表に定義した BLOB データ型とは異なるデータ型で XML 文書を保管してみようと思います。

DB2 9 データ・サーバーを使用すると、ネイティブ XML データ・パーシスタンスを利用できるので、整形式 XML 文書をその階層構造の形式のまま保管することができます。XML 列は、DB2 9 では XML データ型として宣言されます。新しいマイグレーションではまさにこの利点を使用します。

a) ruby script/generate migration add_xml_doc_column を実行します。

これによって、db/migrate/007_add_xml_doc_column.rb が生成されます。

b) 007_add_xml_doc_column.rb を以下のように編集します。

リスト 24. DOCUMENTS 表への XML 列の追加
class AddXmlDocColumn < ActiveRecord::Migration
  def self.up
    add_column :documents, :xmldata, :xml
  end
  
  # Currently, a column that is part of a table containing an XML column
  # cannot be dropped.  To remove the column, the table must be dropped 
  # and recreated without the previous XML column.
  def self.down
    drop_table :documents
    create_table :documents do |t|
      t.column :name,         :string,      :null  => false
      t.column :size,         :integer,     :null  => false
      t.column :data,         :binary,      :limit => 2.megabytes
      t.column :content_type, :string,      :null  => false
      t.column :created_at,   :timestamp
      t.column :updated_at,   :timestamp
      t.column :platform,     :string,      :limit => 10
      t.column :user_id,      :integer
      t.column :subject_id,   :integer
    end
  end
end

c) rake db:migrate を実行して新しい列を DOCUMENTS 表に追加します。

add_column はすでにお馴染みのものですが、remove_columnを使う代わりに、表全体を破棄してから作成しなおす必要があることには驚くことでしょう。しかし、ネイティブ・データ型としての XML がこの表にもたらす重要な変更を考えると、当然のことに思えるはずです。XML 列の削除がサポートされるまでは比較的不便と感じるかもしれませんが、次回の記事でこれとは別のデータベース・スキーマ設計を紹介するとともに、ネイティブ XML データ型サポートが代わりにもたらす主なメリットを説明します。その前に、以前は「一定の形を持たない」と考えられていたデータである BLOB に慣れてください。

d) 収集されて XML 文書にフォーマット化されたマーケティング・データを分析します。

収集されたマーケティング・データに表されている Toronto の近隣すべてを判断するため、Team Room に投稿された文書のうちの 1 つから、顧客の郵便番号情報を抽出することにします。文書の scaffold を使って http://localhost:3000/ までブラウズし、サンプル・コードに付属の teamroom/test/fixtures/CAN-Central.xml 文書をアップロードしてください。次に、以下のアクションを documents_controller.rb に追加します。

リスト 25. XML フォーマットのマーケティング・データの分析
def zips
  @id = params[:id]
  @xmldata = Document.find_by_sql "select xmlquery(\
                                      '<zipcodes>\
                                         {for $i in $t/marketinfo/sales/customer/address\
                                            where  $i/city = \"Toronto\"\
                                            return <zip>{$i/zip/text()}</zip>} \
                                      </zipcodes>'\
                                      passing c.xmldata as \"t\")\
                                   from documents c where id = #{@id}"
  p @xmldata[0]
  redirect_to :action => 'list'
end

現段階のアプリケーションでは、この複雑な SQL と組み込み XQuery の結果は、サーバー・コンソールにすでにアップロードされた CAN-Central.xml 文書の zips リンクに続いて出力されるだけです。この結果には、CAN-Central.xml 文書に含まれる Toronto の顧客に関連付けられた郵便番号エリアの一覧が含まれます。SQL 文に組み込まれた XQuery は最初、複雑に見えるかもしれませんが、ほとんどの場合、XPath クエリー式によって以下のように単純化することができます。

リスト 26. XML マーケティング・データからの Toronto 市内の郵便番号検出
Document.find_by_sql "select xmlquery('<zipcodes>\
                      {$t/marketinfo/sales/customer/address/zip[../city = \"Toronto\"]}\
                                       </zipcodes>' passing c.xmldata as \"t\")\
                             from documents c where id = #{@id}"

次回の記事では、SQL の組み込み XQuery および XPath 式を使って、Rails アプリケーションとの相互作用を単純化する、もっとよい方法を探ります。とりあえずは、XML 文書の一部分を検査するためだけに大規模な XML 文書のコンテンツ全体を取得する必要はなくなるので安心してください。これは、DB2 のネイティブ XML データ・ストア内で DB2 エンジン最適化プラグラムを利用することにより可能になります。

ステップ 7 が完了した時点で、Team Room データベース・オブジェクトは図 4 のようになっているはずです。

図 4. Team Room データベース・スキーマ
Team Room データベース・スキーマ

マイグレーションによる変更のロールバック

ついにマイグレーションは完了しましたが、今まで行った変更をすべて取り消すとしたらどうすればいいでしょう。その方法は極めて簡単で、rake db:migrate VERSION=number (number はロールバックするバーション) を実行すればいいだけの話です。例えば、XMLDB データベースに作成した Rails Team Room プロジェクトの表を破棄し、これまでに行ったすべての変更を取り消すには、rake db:migrate VERSION=0 を実行してください。Rails はまず最も大規模なマイグレーションでの変更をロールバックし、それぞれのマイグレーション・ステップを順に元に戻して、最終的には指定されたバージョン 0 にデータベースをダウングレードします。

リスト 27. マイグレーションによるすべての変更の取り消し
D:\rails\teamroom>rake db:migrate VERSION=0
(in D:/rails/teamroom)
== AddXmlDocColumn: reverting =================================================
-- drop_table(:documents)
   -> 0.0150s
-- create_table(:documents)
   -> 0.1880s
== AddXmlDocColumn: reverted (0.2030s) ========================================

== AddEmailToUser: reverting ==================================================
-- remove_column(:users, :email)
   -> 0.1250s
== AddEmailToUser: reverted (0.1250s) =========================================

== CreateSubscriptionsTable: reverting ========================================
-- drop_table(:subscriptions)
   -> 0.0000s
-- remove_column(:subjects, :subscription_id)
   -> 0.1560s
== CreateSubscriptionsTable: reverted (0.1560s) ===============================

== CreateSubjectsTable: reverting =============================================
-- drop_table(:subjects)
   -> 0.0000s
-- remove_column(:documents, :subject_id)
   -> 0.1570s
== CreateSubjectsTable: reverted (0.1570s) ====================================

== CreateUsersTable: reverting ================================================
-- drop_table(:users)
   -> 0.0000s
-- remove_column(:documents, :user_id)
   -> 0.1400s
== CreateUsersTable: reverted (0.1400s) =======================================

== AddDocsAttributes: reverting ===============================================
-- remove_column(:documents, :created_at)
   -> 0.1250s
-- remove_column(:documents, :updated_at)
   -> 0.1870s
-- remove_column(:documents, :platform)
   -> 0.1260s
== AddDocsAttributes: reverted (0.4380s) ======================================

== CreateDocsStore: reverting =================================================
-- drop_table(:documents)
   -> 0.0000s
== CreateDocsStore: reverted (0.0000s) ========================================

まとめ

今回の記事では、IBM_DB アダプター/ドライバーと DB2 データ・サーバーを使って Rails アプリケーション開発に取り掛かる方法を紹介しました。DB2 と Ruby on Rails に馴染みのない方には Starter Toolkit for DB2 on Rails が最も簡単な手段になる一方、経験のある DB2 開発者にとっては IBM_DB アダプターおよびドライバー gem、あるいはプラグインのインストールが同じく取り組みやすい方法となるはずです。

この記事では Rails のマイグレーションについても詳しく説明しました。データベース・スキーマの変更を管理するのは厄介な仕事です。Rails マイグレーション機能はアプリケーション開発者がスキーマの進化を管理しやすくし、アプリケーション・コードとデータベース・オブジェクトとの間で変更を簡単に同期できるようにします。Rails のマイグレーションを利用して Ruby ファイルにデータベース・スキーマの変更を定義すれば、変更のバージョン管理は論理的に行われます。さらに、Rails の ActiveRecord はベンダーに依存しないため、開発者は Ruby マイグレーション・ファイルを 1 個作成するだけで、さまざまな ActiveRecord アダプターを使って複数のデータベース・プラットフォームに対して同じ変更を処理することができます。

連載「DB2 と Ruby on Rails」の第 2 回では、DB2 on Rails と XML サポートを次のレベルにまで引き上げる方法を紹介し、Ruby on Rails により XML 操作について詳しく説明するのでお見逃しなく。


ダウンロード

内容ファイル名サイズ
Team room sample codeteamroom1.zip10KB

参考文献

学ぶために

製品や技術を入手するために

議論するために

コメント

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=Information Management, Open source
ArticleID=293864
ArticleTitle=DB2 と Ruby on Rails: 第 1 回 DB2 と Ruby on Rails の導入
publish-date=05162007