Seaside チュートリアル(その2)

本コーナーは A Seaside tutorial さんをテキストに使っての あたしのSeaside独習ノートです。2回目の今日は 4項 Anchors を勉強します。


前回 では、静的HTMLレンダリングしかやっていないのでSeaside の「継続サーバ」の凄さというのはさっぱりだったと思います。というわけで、今回はちょっと Webアプリケーションらしいネタで攻めてみようと思います。

アンカーの使い方

HTMLのアンカー要素は別の文書へのハイパーリングを作る、Webナビゲーションの基本的な要素です。このアンカを使って作られるWebアプリケーションは、ASP だと本当に別スクリプトへのリンクだったり、クエリー文字列付きでポストバックさせて、スクリプト内で処理を分岐させたり等、それなりに面倒くさい儀式が必要なことも多いです。

では Seaside だとどうかというと、アンカーをクリックされた時の処理をブロックで渡すだけの、GUIアプリケーションのコールバックの様な実にお手軽な実装で実現できます。百聞は一見に如かず、まずはこんなコードです。

renderContentOn: html
    html anchorWithAction: [self sayHello] text: 'Say hello'.
sayHello
    self inform: 'Hello!'

この二つのメソッドが定義された WAComponentのサブクラスを作り、 registAsApllication するだけでとりあえず完成です。

anchorWithAction:text: で、A要素のレンダリングとコールバック時の処理を渡すことが出来ます。ちなみに sayHello メソッド内で使われている inform: ですが、ちょうど GUI の OK ダイアログのような組み込みの 画面を表示します。

(Seaside にはこのような コモンダイアログのようなモノが幾つかあります)

状態管理のしくみ

「ん〜、これじゃまだまだ静的HTMLでただジャンプしてるのと変わらないじゃん」と言うことで、今度はもうちょっと面白い実験をしてみましょう。

まずインスタンス変数 name を作ります。

WAComponent subclass: #HelloComponent
    instanceVariableNames: 'name'
    classVariableNames: ''
    poolDictionaries: ''
    category: 'MySeasideTutorial'

次に以下のインスタンスメソッドを定義します。

initialize
    super initialize.
    name := '名無しさん'

gikoIsHere
    name := 'ギコ'

monaIsHere
    name := 'モナー'

renderContentOn: html
    html heading: 'ようこそ ' , name  level: 1.
    html anchorWithAction: [self gikoIsHere] text: 'ギコ'.
    html br.
    html anchorWithAction: [self monaIsHere] text: 'モナー'

どうでしょう。最初見出しは「ようこそ 名無しさん」だったのが、「ギコ」「モナー」のリンクをクリックするたびに、「ようこそ ギコ」「ようこそ モナー」と変わります。

しばらく遊んだら(w)、今度は、画面下の "New Session" をクリックしてください。これはこれまで使ってきた古い(操作を覚えている)コンポーネントを捨てて、新たな生まれたてのコンポーネント取得するっていう意味です。なのでリフレッシュされているので「ようこそ 名無しさん」と言う表示に戻っているハズ。

さてここで問題です。Seaside は現存するルートコンポーネントインスタンスを使うべきか、新しくつくったインスタンスを使うべきかをどうやって判断するのでしょうか? 実は、この情報は基本的にアンカーの中に含まれているのです。「ギコ」か「モナー」をクリックした後のURL を見れば、"_s" と言う名前のパラメータがURLに含まれているのに気づくでしょう。また、生成されたHTMLソースを読んでも以下のようになっているはずです。

<a href="/seaside/helloLink?_s=yVABHwkQVbjqIMWu&amp;2&amp;_k=ZymTPorp">モナー</a><br />

これは、リクエストの間を超えてユーザのセッションを追跡するために Seasideが使うものです。ちなみにセッション変数無しのURLでリクエストしたときには、アプリケーションのルートコンポーネントの新たなインスタンスが生成される、という仕組みになっています。

もうすこし詳しく突っ込むと、ユーザセッションは、それぞれのアクティブセッションに結びついた WASession クラスのインスタンス によって実現されます。そしてレンダラーは、コールバックされるタイプのアンカーやフォーム生成メソッド(xxxxWithAction: みたいな奴)でそれらをレンダリングする際、同時にセッションIDの生成まで面倒みてる、と言うわけです。

普通のアンカーを貼るには

もちろんセッション情報を作らないでフォームやアンカーをレンダリングする低レベルメソッドも存在します。これらは、外部ウェブサイトへのリンクを張るようなとき(つまり、普通のHTMLのアンカー等として使いたいとき)に利用します。以下に例を示します。

renderContentOn: html
    html anchorWithUrl: 'http://mineko.fc2web.com/' 
            do: '三猫OnLine'.
    html br.
    html anchorWithPopupUrl: 'http://d.hatena.ne.jp/minekoa/'
            extent: 400@350 
            text: 'みねこあ'

HTMLレンダリング結果:

<a href="http://mineko.fc2web.com/">三猫OnLine</a><br />

<a onclick="window.open('http://d.hatena.ne.jp/minekoa/','''',  'width=400,height=350,menubar=yes,resizable=yes,scrollbars=yes'  ); return false"   href="http://d.hatena.ne.jp/minekoa/">みねこあ</a>

ぐちゃっ見にくくて申し訳ありませんが、見ての通りどちらもセッション情報が含まれまれない、単純なリンクとしてレンダリングされています。
ちなみに後者の anchorWithPopupUrl:extent:text は、Javascriptでポップアップウインドウを開いてそこに画面を表示するものですが、今のご時世では使わないほうがいいかも(^^;


以上、今回は アンカーのレンダリングを例に Seaside のセッション管理の基本について勉強しました。今回の内容も、A Seaside tutorial のAnchors を参考にしましたが、前回に増してそのまんまです。殆ど超訳といった体。ちょっと不味いかなぁ(どうなんだろ)。


関連記事