Step3

English page

Kahua Release

kahua-web Release

Security Advisory

Event Log

Documentation

For developers

Site info

Related Site

ソーシャルブックマークを作る(1)

ソーシャルブックマークはどうあるべきか? なんてことを考え始めるとキリが ないので(いや、実際に作るときはよく考えた方がいいんですが)、いきあたり ばったりで作っていきます。

ブックマーククラスの定義

何はともあれ、ブックマークというものを格納していかなければならないわけ で、まずはそのためのクラスを定義します。ブックマークとしてどういう情報 を持たせるかもじっくり検討した方がいいんでしょうが、ここでは「タイトル」 「URL」のふたつを持たせることにしておきます。なに、足りなければ後で増や せばいいんです。

ということで、以下の定義を $HOME/work/bookmarks/bookmarks/bookmarks.kahua に書き加えます。 page-templateの次あたりにしましょうか。大事なのは、 <kahua-persistent-base> クラスを継承すること、スロットの :allocation オ プションに :persistent を指定することです。こうすることで、自動的にこの クラスのインスタンスは永続化され、:allocationスロットオプション に:persistentを指定したスロットの値がKahuaのオブジェクトデータベースに 格納されるようになります。

(define-class <bookmark> (<kahua-persistent-base>)
  ((title :allocation :persistent :init-keyword :title :init-value "")
   (url :allocation :persistent :init-keyword :url :init-value "")))

このフォームの直後にカーソルを置いた状態で、C-xC-e を打鍵すると、 フォームが別バッファで起動しているkahua-shellに送られて評価され ます。*kahua-shell*バッファを見てみましょう。

bookmarks(348:lm)> <bookmark>
bookmarks(348:lm)>

これで、実行中のbookmarksアプリケーションのプロセス内で、<bookmark> クラスが定義されたことになります。では、このクラスのインスタンスを *kahua-shell* 内でいくつか作ってみましょう。

bookmarks(348:lm)> (make <bookmark> :title "Kahua Project" :url "http://www.kahua.org/")
#<<bookmark> 0x8667688>
bookmarks(348:lm)> (make <bookmark> :title "Practical Scheme" :url "http://practical-scheme.net/")
#<<bookmark> 0x86cf2b0>
bookmarks(348:lm)>

これだけで、2つのインスタンスのデータがKahuaオブジェクトデータベース に書き込まれているはずです。

bookmarks(348:lm)> (make-kahua-collection <bookmark>)
#<<kahua-collection> 0x8217e80>

make-kahua-collection は、引数に渡したクラスのインスタンスをコレクションとして返すメソッド です。コレクションを扱うのですから、gauche.collection を use しておき ます。これはどうせプログラムの中でも使うはずなので、bookmarks.kahua の先頭部分に書いて C-xC-e しておきます。*kahua-shell*には次のように 表示されているはずです。

bookmarks(348:lm)> call-with-iterator
bookmarks(348:lm)>

では、確認してみましょう。

bookmarks(348:lm)> (size-of (make-kahua-collection <bookmark>))
2
bookmarks(348:lm)> (map (cut slot-ref <> 'title) (make-kahua-collection <bookmark>))
("Practical Scheme" "Kahua Project")
bookmarks(348:lm)> (map (cut slot-ref <> 'url) (make-kahua-collection <bookmark>))
("http://practical-scheme.net/" "http://www.kahua.org/")
bookmarks(348:lm)> 

ちゃんと登録されています。ちなみに、物理的にどんな具合に格納されて いるかは、以下のようにすると推測できるでしょう。

% find $HOME/work/site/database/db
/home/bizenn/work/site/database/db
/home/bizenn/work/site/database/db/%%tmp
/home/bizenn/work/site/database/db/%%id-counter
/home/bizenn/work/site/database/db/%%character-encoding
/home/bizenn/work/site/database/db/<kahua-persistent-metainfo>
/home/bizenn/work/site/database/db/<kahua-persistent-metainfo>/%%lock
/home/bizenn/work/site/database/db/<kahua-persistent-metainfo>/%%lock/lock
/home/bizenn/work/site/database/db/<kahua-persistent-metainfo>/%%alive
/home/bizenn/work/site/database/db/<kahua-persistent-metainfo>/%%alive/0
/home/bizenn/work/site/database/db/<kahua-persistent-metainfo>/%%key
/home/bizenn/work/site/database/db/<kahua-persistent-metainfo>/%%key/<bookmark>
/home/bizenn/work/site/database/db/<kahua-persistent-metainfo>/%%index
/home/bizenn/work/site/database/db/<kahua-persistent-metainfo>/0
/home/bizenn/work/site/database/db/<bookmark>
/home/bizenn/work/site/database/db/<bookmark>/%%lock
/home/bizenn/work/site/database/db/<bookmark>/%%lock/lock
/home/bizenn/work/site/database/db/<bookmark>/%%alive
/home/bizenn/work/site/database/db/<bookmark>/%%alive/1
/home/bizenn/work/site/database/db/<bookmark>/%%alive/2
/home/bizenn/work/site/database/db/<bookmark>/%%key
/home/bizenn/work/site/database/db/<bookmark>/%%key/000001
/home/bizenn/work/site/database/db/<bookmark>/%%key/000002
/home/bizenn/work/site/database/db/<bookmark>/%%index
/home/bizenn/work/site/database/db/<bookmark>/1
/home/bizenn/work/site/database/db/<bookmark>/2
%

ブックマーク一覧の表示

ブックマーククラスを定義し、手動とはいえインスタンスも登録したので、 この一覧を表示するためのエントリを定義してみましょう。

まずは<bookmark>のインスタンスのコレクションを一連の(X)HTML片に変換 する手続きを書きます。これは単なる手続きでエントリではないことに 注意。

(define (bookmark-entry/ bm)
  (li/ (a/ (@/ (href (slot-ref bm 'url))) (slot-ref bm 'title))))

書き終わったらフォームの直後でC-xC-e。これは習慣づけちゃうのがいい でしょう。*kahua-shell*には

bookmarks(348:lm)> bookmark-entry/
bookmarks(348:lm)> 

という表示が出るはずです。以降、フォームを書いたらこの繰り返しになるので、 いちいち書きません。

次に、こいつを使って一覧となる(X)HTML片を生成する手続きを書きます。

(define (bookmark-list/ bm-collection)
  (ul/ (map/ bookmark-entry/ bm-collection)))

li/ a/ ul/ は、高階タグ関数といい、名前から/を取り除いたものを要素名 とするタグ片を表す関数を返す関数です。見ると、使い方の推測はつきますよね。 引数に渡されたものを内包する要素を生成していく、一種のコンビネータという わけです。属性は (@/ (属性名 属性値) ...) という形で表現します。

map/ はmapに似た特殊な高階タグ関数で、mapした結果をまとめた特殊な高階タグ を生成します。

このように、Kahuaに含まれる高階タグ関数の命名規則に則り、高階タグを返す 手続きの名前には / を後置するという命名規則を採用しておきましょう。

最後に、この手続きを読んでブックマークの一覧をページとして表示する well known エントリを定義します。名前をどうするかちょっと悩みますが、 ここでは、全てのブックマークを表示するという意味を込めて「all」という 名前で定義します。

(define-entry (all)
  (kahua:xml-template->sxml
   page-template
   :title (title/ (@/ (id "title")) "All Bookmarks")
   :body (div/ (@/ (id "body"))
               (h1/ "All Bookmarks")
               (bookmark-list/ (make-kahua-collection <bookmark>)))))

生成されたコードに含まれていた greeting や version にそっくりですね。 やっていることはほとんど同じですから当然のことです。詳しく見ていき ましょう。

まず kahua:xml-template->sxml は、その名の通り引数に渡されたテン プレートオブジェクトとキーワード引数群からSXMLを構築して返すメソッドで す。page-template はすでに生成されたコードの中で定義されていましたね。 テンプレートに使われているXMLファイルは、$HOME/work/bookmarks/templates/page.xml です。

<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
  <head>
    <title id='title'>SAMPLE</title>
  </head>
  <body>
    <div id='body'>
      <h1>Hello Kahua</h1>
    </div>
  </body>
</html>

ここで重要なのは、title要素に「title」というID属性が、body要素直下の div要素に「body」というID属性がつけられていることです。それぞれ、 キーワード引数 :title 、:body によって置き換えることができるわけです。 ここでは、titleを

(title/ (@/ (id "title")) "All Bookmarks")

で、bodyを

(div/ (@/ (id "body"))
      (h1/ "All Bookmarks")
      (bookmark-list/ (make-kahua-collection <bookmark>)))

で置き換えています。

これで、初めてのエントリが書き上がりました。

デフォルトエントリを置き換える

普通、ソーシャルブックマークであれば、デフォルトで一覧を表示するでしょ うから、今定義した「all」エントリをデフォルトエントリにしておきましょう。

(initialize-main-proc greeting)

これを、

(initialize-main-proc all)

と書き換えます。C-xC-eしたら、ブラウザでエントリ部分のパス要素を削って、 http://localhost:8088/bookmarks にアクセスしてみましょう。

これで greeting エントリは不要になります。余計なものをいつまでもかかえて いるのはあまりよろしくないので、削ってしまいましょう。

削ったことをアプリケーションのプロセスに動的に伝える方法はありません。 作業も一段落したことですし、ここで再度インストールを行いましょう。 $HOME/work/bookmarks に移動して、make installします。

% make install
[後略]

インストールが終わったら、kahua-admin を使ってアプリケーションプロセスに コード全体を再読み込みさせます。kahua-admin は対話的に使う他に、このように サブコマンドをコマンドラインから渡してバッチ的に使うこともできます。

% kahua-admin update bookmarks
update: bookmarks(348:lm)
%

Kahuaにおけるアプリケーション開発は、基本的に以上のようなステップを繰り 返すことによって進めていきます。

Copyright (c) 2003-2007 Kahua Project Contact | About Us