ダウンロード サンプルファイル (19.7 KB)
ブラウザとCometで接続するCometTwit Snippet
次に、ブラウザとCometで接続するCometTwit Snippetを作成します。LiftでCometを利用するSnippetは、プロジェクトで指定したパッケージ以下の「comet」パッケージ内に作成する必要があるので注意が必要です。
プロジェクトディレクトリ以下の 「src/main/scala/demo/twitterclone/comet/」ディレクトリに、「CometTwit.scala」というファイル名で新しいファイルを、以下のリスト5の通りに作成します。
package demo.twitterclone.comet
import _root_.scala.actors._
import _root_.scala.actors.Actor._
import _root_.scala.xml.{NodeSeq, Text }
import _root_.net.liftweb.http._
import _root_.net.liftweb.http.S._
import _root_.net.liftweb.http.SHtml._
import _root_.net.liftweb.util.Helpers._
import _root_.net.liftweb.util.{Box, Full}
import _root_.net.liftweb.http.js.JsCmds._
import _root_.net.liftweb.http.js.JE._
import _root_.net.liftweb.http.js.jquery.JqJsCmds._
import _root_.demo.twitterclone.model._
/**
* ブラウザとComet接続し、非同期にメッセージを
* 表示させるSnippet。
* CometActorを継承し、他のListenerManagerを継承した
* Actorに登録するため、CometListeneeトレイトを継承する。
*/
class CometTwit extends CometActor with CometListenee { // *1
// このSnippetのNameSpace
override def defaultPrefix = Full("twit")
// 非同期にメッセージを表示させるタグのID
private lazy val spanId = uniqueId + "_messages_span"
// SinpetがTemplateから呼び出された時、
// <Twit:messages/>タグの内容を出力する
def render = bind("messages" -> // *2
<span id={spanId}><div></div></span>)
// このActorを他のActorに登録する。
// ここでは、TwitServer Actorに登録
protected def registerWith = TwitServer // *3
// このActorがメッセージを受け取った時の処理
override def highPriority = { // *4
// caseクラス Messagesを受け取る
case Messages(msgs) =>
// partialUpdate関数にをPrependHtmlオブジェクト渡すことで、
// htmlを部分的に書き換えるJavaScrpitが生成される
partialUpdate( PrependHtml(spanId, // *5
<xml:Group>
{ msgs.map( m =>
<ul class="status">
<li class="message">{ m.status.is }</li>
<li class="user">{ userName( m.user.obj )}</li>
<li class="dateOf">{ m.dateOf.is.toString }</li>
<hr/>
</ul> )
}
</xml:Group>
))
}
/**
* Userモデルオブジェクトからユーザー名を取得するユーティリティ関数
*/
def userName( user:Box[User] ) = user.dmap( "Guest" ){ user =>
user.shortName
}
}
このCometTwit Snippetは、CometActorを継承し、CometListeneeトレイトを継承します。CometListeneeトレイトを継承しておくことで、他のListenerManagerを継承したActorに登録できるようになります。このCometTwitは、投稿されたメッセージを受信するために、先ほど作成したTwitServer Actorに登録する必要があるからです。
*2のreder関数は、このSnippetがテンプレートから呼び出された際に、表示するHTMLを生成するためのものです。Cometでメッセージを表示するため、初期表示では空の<span>タグを出力しているだけです。ただし、ここで出力している<span>タグは、spanIdフィールドで定義されたIDを、タグのIDにしています。このようにすることで、メッセージ受信時の処理でspanIDのタグに対して追加でメッセージを表示させることができるようになります。
*3のregisterWith関数では、このActorを他のActorに登録しています。先ほども述べた用に、TwitServerに登録する必要があるため、このように記述しています。実際の登録処理は継承しているCometListeneeトレイトが行います。
*4のhighPriority関数は、メッセージ受信時の処理です。関数の書き方は、先ほどのTwitServerクラスのhighPriority関数と同じ形式です。
このCometActorでは、メッセージとしてはcaseクラスMessagesを受信します。TwitServerに登録することで、TwitServerでupdateListeners()関数を呼び出されると、このActorにMessageモデルを内容として持つcaseクラスMessagesが送信され、最終的にこの関数が呼び出されます(この呼び出しは非同期です)。
では、メッセージ受信時の処理について解説します(*5)。
partialUpdate関数(CometActorトレイトがもつ関数)を呼び出すことで、指定したIDのタグの内容を部分的に書き換えることができます。
引数は、書き換える内容を渡します。直接HTMLを返してもよいのですが、ここでは<span>タグの先頭にメッセージを次々と追加していくために、PrependHtmlオブジェクトを渡しています。
PrependHtmlオブジェクトの第1引数には、書き換え対象のタグのIDを渡します。ここでは、表示の時に生成しておいた<span>タグのID(spanIDフィールドで定義)を渡します。
第2引数は、追加するHTMLです。受信したcaseクラスMessagesから、登録されたMessageモデルオブジェクトを取り出して、表示する内容を生成しています。
PrependHtmlオブジェクトは、Ajaxの例のところで説明したSetHtmlオブジェクトと同じく、JavaScriptを生成します。このように、partialUpdate関数にPrependHtmlオブジェクトのようなJavaScriptを生成するオブジェクトを渡すと、CometによりブラウザにJavaScriptが送信されて実行されます。
この記事は参考になりましたか?
- Scala+Liftによる実践Webアプリケーション開発連載記事一覧
-
- AjaxとCometを利用したLiftのアプリケーションを作る
- Twitterのクローン作成で学ぶLiftによる開発の流れ
- Scala+LiftフレームワークのModel
- この記事の著者
-
山田 祥寛(ヤマダ ヨシヒロ)
静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数。
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
-
WINGSプロジェクト 尾崎 智仁(オザキ トモヒト)
<WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書、記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
この記事は参考になりましたか?
この記事をシェア
