CouchDB と Bootstrap を使用して Web アプリケーションのプロトタイプを作成する

Web デザインとデータベース設計とを分離し、後で合体する

Apache CouchDB と Twitter Bootstrap とを組み合わせ、プレゼンテーション層とデータベース層とを明確に分離する形で、Web アプリケーションの開発を始めましょう。CouchDB は、手軽にデータベース (特に Web サイト用のデータベース) を作成する手段として、よく知られています。フロントエンドに関しては、サイトのプロトタイプを作成するための、さらには完全なデプロイメントまでを行える、オープンソースのツールキットが数多く登場しています。なかでも Bootstrap フレームワークは、特に Web の UI を作成する場合に役立ちます。Bootstrap と永続化用の CouchDB を使用して Web アプリケーションのプロトタイプを作成する方法を学びましょう。

Uche Ogbuji, Partner, Zepheira, LLC

Photo of Uche OgbujiUche Ogbuji は次世代の Web 技術によるソリューションを専門とする会社 Zepheira, LLC のパートナーです。Ogbuji 氏は XML、RDF、およびナレッジ・マネージメント・アプリケーション用のオープンソース・プラットフォームである 4Suite とその後継である Akara の中心的開発者です。彼はナイジェリア出身のコンピューター・エンジニア兼ライターとして米国コロラド州ボルダーに住み、そこで働いています。彼に関して詳しくは、彼のブログである Copia または Twitter を見てください。



2013年 7月 04日

Apache CouchDB は、NoSQL ムーブメントの中で新たに登場したデータベース管理システム (DBMS) の 1 つです。CouchDB では、主要な情報は JSON (JavaScript Object Notation) 文書として格納されます。もっと一般的な文書フォーマットも管理対象の添付ファイルとしてサポートしていますが、何十年にもわたって DBMS の世界を支配してきた SQL によってクエリーが行われる、従来の表形式のデータはサポートしていません。CouchDB のもう 1 つの重要な特徴は、すべての操作を単純な HTTP 呼び出しで行える点、特に REST (Representational State Transfer) 形式の HTTP 呼び出しで行える点です。このアーキテクチャーのおかげで、ホスト・プラットフォームやツールキットに何を使用していても容易に CouchDB を扱うことができるとともに、CouchDB を Web サイトやアプリケーションに永続バックエンドを提供するための有用な手段として利用することができます。

いくつかのチュートリアルには、CouchDB に組み込まれた JavaScript ライブラリーや、CouchApp などの関連ツールを使用してアプリケーション開発を開始する方法が解説されています (「参考文献」を参照)。この記事では、それらとは少し異なる方法をとり、単純で静的に提供される Web サイトの土台と CouchDB を組み合わせ、短時間でWeb サイトのプロトタイプを作成する方法を説明します。

REST とは一体何か

REST は、メッセージを利用する代わりに、例えば URL (Uniform Resource Locator)、URI (Uniform Resource Identifier)、URN (Uniform Resource Name) など、リソースの名前を指定して Web アプリケーションを緩やかに結合するアーキテクチャー・スタイルです。REST は、World Wide Web の HTTP インフラストラクチャー・プロトコルの GET リクエストや POST リクエストなどを活用します。

Web サイトのフロントエンドを短時間でセットアップするための新たな手段として、よく使用されているものの 1 つが Bootstrap です。Bootstrap システムは Twitter の技術者達によって、Web サイトの開発で使用されるさまざまなプラットフォームやツールキットを使いやすくするために開発されたものです。Bootstrap は、Web アプリケーションの UI を作成するための一貫性のあるフレームワークとして機能します。Bootstrap を使用すると、タイポグラフィー、フォーム、ボタン、表、グリッド、ナビゲーション、アラート、等々のための CSS (Cascading Style Sheets) 要素を含む見栄えの良いサイトを容易に設計することができます。この記事では、フロントエンドに Bootstrap を使用し、バックエンドに CouchDB を使用して開発プロセスを開始する方法を説明します。この方法は、複雑な Web アプリケーションにも活用することができます。

なぜ CouchDB スタック上でプロトタイプ全体を作成しないのか?

多くのチュートリアルで、本番レベルの Web サイト全体を CouchDB のみで作成することがいかに容易であるかを解説していますが、それらの方法は推奨できません。そうした方法で開発プロセスを開始すると、そのサイトを公開しようとする場合にも、手間を省いて同じ方法を使用したい強い誘惑にかられてしまいます。セキュリティーや保守の観点からは、データベース用のバックエンドと表示用のフロントエンドとを分離することがより望ましい方法です。この記事では、サイトを公開する場合に機密データをセキュアに保持できるように、CouchDB インスタンスをロックダウンするためのさまざまな選択肢を示します。セキュリティーには、常に警戒心と専門知識が必要です。静的ファイルで構成される Web サイトはずっと以前からあるため、非常によく理解されており、管理ツールも十分に成熟しています。

Web 開発では、以下のようにいくつものフレームワークを使用することが一般的であるため、CouchDB を Web サイトのフロントエンドから切り離しておくことにはさらなるメリットがあります。

  • データ処理のための DBMS
  • Web サーバーまたはコンテンツ管理システム
  • Web デザイン・フレームワーク

この記事では、CouchDB、Apache HTTP Server、Bootstrap を使用します。

これらの各層を対象とした要員、スキル・セット、そして技術の選択基準はよく変わります。これらの 1 つの項目について決定すると、その決定は別の項目についての決定と緩やかに関係します。その上、コンテンツ・デリバリー・ネットワーク、テスティング・フレームワーク、セキュリティーをサポートするためのミドルウェアなど、固定されていない部分があります。これらのコンポーネントの組み合わせの柔軟性が高ければ高いほど、中長期にわたってのシステムの保守や改善は容易になります。

この記事で私が選択した技術は、データベース管理に関する私の専門を反映しています。Apache のツールと Bootstrap は、アプリケーションの基本部分を短時間で作成できるようにする上でまさに打ってつけです。基本部分が作成できたら、私は他の専門家達と協力して進めたいと思っています。ミドルウェア開発者は、Django や Ruby on Rails などの Web サーバー・フレームワークや、WordPress などのコンテンツ管理システムさえも使用して作業を続けることを望むかもしれません。そこで私は、他の層に大きな影響を与えずに置き換えられる方法で Apache を使用しています。Web デザイナーは十中八九、Bootstrap を使用せずに手作業でデザインをしたがるでしょう。そこで私は、容易に置き換えられる方法で Bootstrap を使用しています。最近のツールやフレームワークのおかげで、Web アプリケーションのプロトタイプを大きな 1 つのかたまりとして作成するのではなく、ここで説明する方法で作成しても、それほど複雑なことにはなりません。

作業を開始する

ページのコンテナーにコンテンツを追加する

このプロトタイプ・ページは、jQuery を使用して CouchDB からターゲットの div に文書をロードします。ここでは jQuery の Ajax 機能を直接使用しており、CouchDB と CouchApp による jQuery のプラグインは使っていません。jQuery のプラグインは便利なのですが、CouchDB と Web サイトとが密結合でなければならず、jQuery のプラグインを使用した場合、Web サイトのページはデータベースの添付ファイルとして追加されます。私は、開発中は特に CouchDB と Web サイトとを分離したいと思っています。何よりも、CouchDB と Web サイトとを分離することにより、必要に応じて CouchDB を別のバックエンドに置き換えることができます。この記事でページをロードするために使用する JavaScript コードは単純です。このコードは記事の「ダウンロード」に poquotes.js として含まれています。

ここでは詩を引用してサイトに表示する、単純な Web アプリケーションのデモを紹介します。CouchDB のインストール方法については「参考文献」を参照してください。サーバー上で CouchDB が稼働状態になったら、CSS と JavaScript のバンドルにすぎない単純な Twitter Bootstrap をダウンロードするか、またはプロジェクト全体のバンドルをダウンロードします。この記事ではプロジェクト全体のバンドルを使用しています。

私は Twitter Bootstrap バンドルの fluid.html というサンプルを使用して作業を開始しました。このファイルに少し手を加えるとともに、CSS と JavaScript のスクリプトを修正して先頭の ../assets/ を削除し、サンプル・サイトの静的コンテンツの一部を更新しました。その結果は index.html として保存してあり、このファイルは記事のコード・バンドルに含まれています (「ダウンロード」を参照)。リスト 1 は HTML ページのヘッダーの主要部分です。

リスト 1. index.html ページのヘッダーの一部
<!-- Styles -->
<link href="css/bootstrap.css" rel="stylesheet">
<style type="text/css">
  body {
    padding-top: 60px;
    padding-bottom: 40px;
  }
  .sidebar-nav {
    padding: 9px 0;
  }
</style>
<link href="css/bootstrap-responsive.css" rel="stylesheet">

<!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
  <script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>

リスト 2 は index.html の表の一部です。この表に、サイトの中心となる詩の引用が CouchDB からロードされます。

リスト 2. サイトの中心となる詩の引用がロードされる、index.html の表の一部
<div class="row-fluid">
  <div class="span4 featured-quote">
    <h2>Poet's name</h2>
    <p>Body of quote here.</p>
    <p><a class="btn" href="#">View details &raquo;</a></p>
  </div><!--/span-->
  <div class="span4 featured-quote">
    <h2>Poet's name</h2>
    <p>Body of quote here.</p>
    <p><a class="btn" href="#">View details &raquo;</a></p>
  </div><!--/span-->
  <div class="span4 featured-quote">
    <h2>Poet's name</h2>
    <p>Body of quote here.</p>
    <p><a class="btn" href="#">View details &raquo;</a></p>
  </div><!--/span-->
</div><!--/row-->

このページには、データベースを操作するためのメカニズムも含まれています。具体的には、ユーザーが新しい引用レコードを作成するために使用可能なフォームがサイドバーにあります。ユーザーがフォームにアクセスするには、リンクをクリックします。すると jQuery がトリガーされ、フォームが表示されます。リスト 3 はフォームのマークアップを示しています。(この記事のページの幅の制約から、最初の 2 つの <input> 行は分割されています。)

リスト 3. 新しい引用レコードを作成するための index.html のフォーム
<a href="#popup" id="popup">Click to create a new quote</a>
<div>
  <form id="newquote" action="index.html">
    <fieldset>
      <legend>The quote</legend>
      <label for="author">Author's Name</label>
      <input id="author" name="author" type="text" placeholder="First and last name" 
          required="required" autofocus="autofocus">
      <label for="text">Text of the quotation</label>
      <input id="text" name="text" type="textarea" placeholder="Text of the quote here" 
          required="required">
    </fieldset>
    <fieldset>
      <legend>The work</legend>
      <label for="title">Title of the work</label>
      <input id="title" name="title" type="text" required="required">
      <label for="link">Link to the work</label>
      <input id="link" name="link" type="text" required="required">
      <label for="year">Year of the work</label>
      <input id="year" name="year" type="text" required="required">
    </fieldset>
    <input id="donewquote" type="submit" value="Add quote" />
  </form>
</div>

リスト 4 は、index.html ページ本体の末尾近くのコードであり、必要な JavaScript をロードしている部分です。最後の script 行では、CouchDB の poquotes データベースを扱うための専用のコードをロードしています。

リスト 4. index.html ページ本体の末尾近くで JavaScript コードをロードする
<!-- Placed at the end of the document so the pages load faster -->
  <script src="js/jquery-1.7.1.js"></script>
  <script src="js/bootstrap.js"></script>

  <script src="js/poquotes.js"></script>

</body>

Bootstrap を使用することにより、Web サイトの基本部分のセットアップが 5 分もかけずにできました。この Web サイトは、古いブラウザーやモバイル機器でのグレースフル・デグラデーションを含む、最近の Web サイトの機能の大半を備えています。皆さんの Web サイトでは、サイトのデザインに合うように、色、フォント、画像、その他の詳細項目を適宜変更してください。Bootstrap のサイトには、ヒントになりそうなサンプルが数多く公開されています (「参考文献」を参照)。


データを準備する

リスト 2 に記載されている featured-quote クラスの div 要素に注目してください。これらの div 要素には CouchDB のデータがロードされます。メイン・ページには、ページのスクリプトによって動的にロードされ、現在表示されている定型部分を置き換える 6 つの有名な詩の引用が表示されます。

例えば、「http://localhost:5984/_utils/」と入力して Futon (CouchDB に含まれているブラウザー・ベースのコンソール) にアクセスし、「poquotes」という名前のデータベースを作成します (図 1)。

図 1. CouchDB の Futon ページから poquotes データベースを設定する
CouchDB の Futon ページから poquotes データベースを設定する画面のスクリーン・キャプチャー

リスト 5 は、ある引用の 1 つに関する情報を含むサンプル文書です。(この記事のページの幅に合わせて 4 行目は分割されています。)

リスト 5. ある引用の 1 つに関する情報を含む JSON 文書の例
{
    "type": "quote",
    "author": "Thomas Hardy",
    "text": "And as the smart ship grew<br>In stature, grace, and hue<br>
In shadowy silent distance grew the Iceberg too.",
    "work": {
            "title": "The Convergence Of The Twain",
            "link": "http://www.poetryfoundation.org/poem/176678",
            "year": 1915
    }
}

以下のように cURL を使用して、このファイルを q1.json として新しいデータベースにロードしました。

curl -u user:passwd -X POST http://localhost:5984/poquotes \
 -H 'Content-Type: application/json' -d @q1.json
{"ok":true,"id":"ca42f5a16ca1905978afdeda68c116c2",
"rev":"1-7fe040eb6d322a35a86d2f871b100ff0"}

CouchDB からの応答 ({"ok" で始まります) から、この文書が追加されたこと、そしてこの新しい文書に対して ID とリビジョン番号が生成されたことがわかります。CouchDB の RESTful な性質のおかげで、サイトのデータ・セットのプロトタイプを作成することは、ファイルシステムの操作と同じくらい容易になります。また、必要に応じて、Futon を使用して文書を追加することもできます。この記事からダウンロードできるサンプル・コードには、そうした引用文書が 6 種類含まれており、ターゲット・ページのグリッドに追加するには十分です。


メインのクエリーを準備する

私は、Web ページに必要な文書をロードするためのビューを、Futon を使用してデザインしました。Futon を使用すると、一時的なビューをデザイン、テストして、それらを実際に使用するために保存することができます。可能であれば、開発サイクルの早い段階で、データベースにほんの数個の文書しか格納されていないうちにビューをデザインしてください。一時的に作成したビューはすぐに速度が遅くなる可能性があるからです。リスト 6 は、ビューの JavaScript コードです。

リスト 6. すべての引用文書を取得するために使用される CouchDB のビュー (引用元の作品の年をインデックスにしています)
function(doc) {
  if (doc.type == "quote") {
    emit(doc.work.year, doc);
  }
}

このビューはシンプルですが、目的は達成しています。ここでは作品の制作年でレコードをソートしてページ上に表示したいので、取得した結果に作品の制作年をインデックスとして付けています。このビューをデータベースに追加するには、「View (ビュー)」セレクターをクリックして「Temporary View (一時ビュー)」に切り換えます。次に、リスト 6 のコードを「Map Function (マップ関数)」ボックスに貼り付けます。「Run (実行」) をクリックすると、6 つの文書が含まれた表が表示されます。これで問題なければ、そのビューを by_year というデザイン文書名で保存します。これで、このビューはもはや一時ビューではなくなりました。次に、信頼できる cURL を再度使用してビューを確認します。

curl "http://localhost:5984/poquotes/_design/poquotes/_view/\
by_year?&descending=true&limit=6"

GET パラメーター (&descending=true&limit=6) は、データベースがクエリーに対して結果を返す際の詳細を調整しています。この場合は最新の文書 6 つのみが降順で返され、year フィールドの値が最も新しい文書が最初になるようにしています。


クロスドメイン制約

多層 Web アプリケーションのプロトタイプを疎結合の形で迅速に作成するのを難しくしている原因の 1 つが、ブラウザーにおけるクロスドメイン・リクエストの一連の制約です。つまり、ブラウザーからスクリプトによってソース・ページと同じホストの同じポート以外に HTTP リクエストを送信することは、セキュリティー上の理由から厳しく制限されているのです。この問題に対処する方法はいくつかありますが、その 1 つが JSONP (JSON with Padding) を使用する方法です (「参考文献」を参照)。リスト 7 は poquotes.js からの抜粋で、ターゲットの div にレコードをロードする部分を示しています。

リスト 7. 引用を含むターゲット・ページをロードするための JavaScript コードと jQuery コード
...
    root: "http://localhost:5984/",
...
    max_quotes: 6,

    //Invoked when the HTML page is first loaded
    loadPage: function()
    {
        var six_latest = poq.root + "poquotes/_design/poquotes/_view/by_year?&limit="
            + poq.max_quotes + "&descending=true&callback=?";
        $.getJSON(six_latest, poq.handleMainQuotes);
...
    },

    //Invoked with the result of the Ajax call to load quote documents
    handleMainQuotes: function(json)
    {
        //Load up to six records, as available
        quote_count = Math.min(poq.max_quotes, json["total_rows"])
        for (var i=0; i<quote_count; i++) {
            var doc = json["rows"][i]["value"]
            var year = doc["work"]["year"].toString()
            var title = doc["work"]["title"].toString()
            var link = doc["work"]["link"].toString()

            //Create an HTML snippet from the fields of each quote document
            qblock = $("<div class='span4 featured-quote'></div>")
              .append("<h2>" + doc["author"] + "</h2>")
              .append("<p style='font-size: 80%; height: 8em;'>" + doc["text"] + "</p>")
              .append("<p>" + year + "</p>")
              .append("<p><a href='" + link + "'>" + title + "</a></p>")
              .append("<p><a class='btn' href='#'>View details &raquo;</a></p>")
            //jQuery's eq selector to find the target div corresponding to the loop index
            $('div.featured-quote:eq(' + i.toString() + ')').replaceWith(qblock);
        }
    },

リスト 7 では、文書をロードするための URL の末尾に callback=? が追加されています。これにより、CouchDB から文書を取得するための Ajax GET クエリーには JSONP を使用することを jQuery に指示しています。データベースは Web フロントエンドの別のポート上で実行されているため、このようにする必要があります。この対策は、別のホスト上で実行されるデータベースにクエリーを実行する場合にも必要です。

GET 以外のメソッドを使用して Ajax リクエストを実行するのは、さらに難しくなります。リスト 8 は poquotes.js からの抜粋で、新しいフォームを作成してデータベースに送信する部分を示しています。

リスト 8. フォームのフィールドをレコードに変換し、CouchDB に POST で送信するための JavaScript コードと jQuery コード
...
    dbroot: "db/",
...
    //Invoked when the HTML page is first loaded
    loadPage: function()
    {
...
        $('#donewquote').click(function() {
            var db_link = poq.dbroot + "poquotes";
            var record = {
                "type": "quote",
                "author": $("#author").val(),
                "text": $("#text").val(),
                "work": {
                    "title": $("#title").val(),
                    "link": $("#link").val(),
                    "year": parseInt($("#year").val())
                }
            };
            $.ajax({
                url : db_link,
                data : JSON.stringify(record),
                contentType : "application/json", 
                type : 'POST',
                processData : false,
                dataType : "json",
                success : function(resp) {
                    alert("New document created: " + JSON.stringify(resp));
                }
            });
            return false;
        });
        //Set up the collapsible form for adding new quotes
        $('#popup').click(function(){
            $("#newquote").slideToggle();
        });
        //Start out with the create quote form collapsed
        $("#newquote").slideToggle();
    },

リスト 8 では、同じホストの同じポートに対して POST が実行されていますが、/db/ という URL に対して POST が実行されています。ここでは、その URL から CouchDB のホストとポートへのリバース・プロキシーを設定する標準的な方法を使用しています。もっと具体的に言えば、Apache HTTP Server の ProxyPass ディレクティブを使用しています。この方法の詳細は、皆さんの設定次第で変わってきますが、ブラウザー層とサーバー層とが確実に分離された Web アプリケーションのプロトタイプを作成する上で、この方法は便利です。


ルック・アンド・フィール

図 2 は実際に動作するサンプル・ページを最初にロードした状態を示しており、ターゲットの div にはデータベースから取得したレコードの内容が追加されています。

図 2. Apache Web サーバーから index.html をロードした後のブラウザーの画面
Apache Web サーバーから index.html をロードした後のブラウザーの画面のスクリーン・キャプチャー

ユーザーが「Click to create a new quote (クリックして新規引用を作成)」を選択すると、新しい引用を追加するためのフォームが図 3 のように表示されます。

図 3. フォームが表示された状態の index.html のブラウザー画面
フォームが表示された状態の index.html のブラウザー画面のスクリーン・キャプチャー

まとめ

この記事を通して、なぜ私が Web アプリケーションのプロトタイプを作成する場合に、特定の方法を好むのかを説明しました。この記事で説明した方法を使用することで、Web デザインとミドルウェアの開発を並行して別々に進めることができ、より自然に関心を分離することができます。私は、たとえ開発段階においても、DBMS を使用せずに専用の Web サーバーでサイトをホストしたいと思っています。

この記事では、CouchDB でのユーザー認証や承認については説明しませんでした。プロトタイプ作成のステージが終わったら、ミドルウェアを更新し、ユーザー管理、セッション等々を扱えるようにします。これらのプロセスでは、CouchDB の機能を利用することも、別のフレームワークを利用することもできますが、それはプロジェクト次第です。こうした柔軟性が重要なのです。Web アプリケーションにはログインやセッション管理に関する詳細事項がいくつかありますが、通常それらは独立した層になっています。

この記事の目的は、NoSQL プラットフォームでプロトタイプを作成する他の方法を非難することではありません。この記事では、それに代わる手段として検討に値する方法を説明しました。最も興味深いオープンソース・プロジェクトをそれぞれの中核となる長所を生かして組み合わせる方法は、楽しいものであると同時に生産的でもあります。そうしたプロセスでは、各層間の結合が緊密すぎるツールでは適当に扱われがちな、重要な詳細事項も数多く学ぶことができます。


ダウンロード

内容ファイル名サイズ
Sample web application for this articlecouchdb-dw.zip9KB

参考文献

学ぶために

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

  • Apache CouchDB: CouchDB をダウンロードしてください。
  • Bootstrap: Bootstrap をダウンロードしてください。
  • cURL: Web のテストとスクリプト統合のための究極のツールを入手してください。

議論するために

  • developerWorks コミュニティー: ここでは他の developerWorks ユーザーとのつながりを持てる他、開発者によるブログ、フォーラム、グループ、Wiki を調べることができます。

コメント

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=Web development, Open source
ArticleID=935423
ArticleTitle=CouchDB と Bootstrap を使用して Web アプリケーションのプロトタイプを作成する
publish-date=07042013