データベースを使ってみる
前回の記事ではTitanium.App.Propertiesやファイル入出力を利用したデータの永続化について解説しましたが、今回はRDBMSを利用したデータの扱い方について解説します。具体的には、自分のホーム画面のタイムラインを取得保存し、前回起動時に取得した分のタイムラインも閲覧できたり、タイムラインの内容を検索できるようにしてみます。
タイムラインの取得
この実装のために今までのサンプルコードを一部改変します。最初の画面で自分の発言だけでなく、フォローしている人も含めたタイムラインが閲覧できるようにtable_view.jsのタイムライン取得部分に次のような変更を加えています。
今まではmessage_window.jsのほうにあったTwitterApiオブジェクトの初期化をtable_view.jsに移動しています。また、タイムラインの取得をTwitterApiオブジェクトを通して実行するようにしています。
Titanium.Database
さて、TitaniumにはTitanium.Databaseというオブジェクトを通してRDBMSにアクセスする機能が実装されており、iPhoneにもAndroidにもライブラリが搭載されているSQLiteを利用することができます。SQLiteはパブリックドメインのRDBMSで、軽量かつ高速に動作することから様々な分野でよく利用されているRDBMSです。MySQLなどほかのRDBMSに慣れている方であればそれほど苦なく扱うことができると思います。
では今回は、データベースに接続するためのオブジェクトをまず先に作ってしまいましょう。全く新しいファイルtweet_db.jsをResourcesディレクトリに作成し、次のコードを実装します。このオブジェクトを利用するときは関数TweetDBをnewして利用します。
では、先頭部分から解説していきましょう。最初に(1)の部分で接続するデータベースの名前をオブジェクのプロパティにセットします。
さらに次の部分(2), (3)でopenとcloseメソッドを定義しています。このメソッドはデータベースの処理を始めるときのTitanium.Database.openの処理と、終了するときのcloseの処理を簡単に呼び出せるようにしているだけです。openメソッドの中で使われている、Titanium.Database.openメソッドがデータベース接続を始めるメソッドで、このメソッドが返すTitatnium.Databaseオブジェクトに対して、各データベース処理を行っていくことになります。
この次に(4)で定義されているaddTweetメソッドは、タイムラインの情報をもった配列tweetsを受け取ることで、その中から保存が必要なものだけをデータベースに保存するメソッドです。まずthis.open()でデータベースに接続します。その後タイムライン中の各ツイートに対して、既に保存されていないか確認し(A)、保存されていなかった場合はデータベースに保存する(B)、という処理をしています。(A)の部分を行っているのが、(5)の
の部分で、this.dbに保存されているTi.DataBaseオブジェクトに対してSQLのSELECT文を発行しています。第一引数のSQL文に含まれる '?' は、第二引数以降に変換される、いわゆるプレースホルダです。
SQLを発行した結果なにかデータが返ってきている場合は、executeメソッドの返り値オブジェクトTitanium.Database.ResultSetのgetRowCount()メソッドで確認できます。この例ではデータが返っていた場合、つまりgetRowCount()が0より大きかった場合はすでにそのツイートが保存されている状態なので、何もせず次のツイートを確かめるように実装しています。
さらに次に続く部分が、(B)のデータベースにデータを保存している部分で、INSERT文を発行することでデータベースの各カラムにツイートの情報を保存しています。
タイムライン中の全てのツイートに対してこの処理を行った後、this.close()を呼び出して、データベースへの接続を終了しています。
もう一つ重要なのは、saveTweetメソッドの定義のあとで、
という文がある点です。この文は、このTweetDBオブジェクがnewされた時に一度だけ実行されるもので、tweetsというテーブルが存在しなかった場合にデータベースにtweetsテーブルを作るCREATE TABLE文が書かれています。テーブルの定義はここに書かれているわけです。
これでデータベースにツイートを格納する準備はできたので、タイムラインを取得する部分でツイートを保存するようにしてみましょう。
まずTweetDBオブジェクを作成し自分のタイムラインを取得したときに、その内容をaddTweetsメソッドに渡しているだけですが、これでデータベースにツイートが保存できたはずです。
ツイートを取り出してみる
ツイートをデータベースに格納できるようになったので、表示する際にはデータベースからツイートを取得するようにします。こうすることで最新のツイートと過去のツイートを連続して表示することができます。
ツイートを取得するメソッドgetSavedTweetsをtweet_db.jsに実装します。
(1)でSELECT文を発行し、保存されているツイートをすべて取得します。続いて、(2)のループで取得したデータを逐次、Twitter APIで返ってくるデータと同じ構造に変換しています。重要な点はループの一番最後のrows.next()メソッドで、このメソッドを実行することで、rowsが指しているデータの内容が次の行のものになります。次の行が存在しない場合、isValidRow()が偽値になるためループが終了します。また、Titanium.Database.ResultSetオブジェクトであるrowsはcloseすることで、それ以降結果を参照できなくなります。ツイート取得メソッドを実装したので、表示するtable_view.js側も変更します。
タイムラインを取得した後にそのデータを保存し、データベースから改めてデータを取得するようにしています。
ツイートを検索してみる
今回はさらに、ツイートの簡単な検索も実装してみます。画面左上のsearchボタンをタップすると、検索窓が現れツイートをユーザー名で検索できるようにしてみます。
tweet_db.jsに今度は与えられた文字列を含むユーザーのツイートだけを返すようなメソッドを追加します。
getSavedTweetsメソッドとほとんど同じですが、引数にqueryが受け取れる点と、実行しているSQLにWHERE節がある点が異なります。SQLのWHERE節でscreen_nameをlike探索しているので、与えられた文字列がユーザー名中に含まれていると、そのユーザーのツイートが返るようになっています。
続いてtable_view.jsでの表示を変更します。
このコードでは、(1)の部分でSearchBarオブジェクトを作成し、(2)部分でSearchBarのなかで改行が押された時の処理を登録しています。この(2)の部分で先ほど作成したsearchByScreenName()メソッドを呼び出し、入力された文字列を名前に含むユーザーのツイートだけを表示するようにしています。
(3)の部分ではSearchBarの中の文字列が変化したときの処理を登録しており、SearchBarの中の文字列が無くなった時に、表示を検索結果の表示からすべてのツイートの表示に変更するようにしています。SearchBarが常に表示されていても邪魔なので(4)で表示を消し、(5)でSearchBarを表示するためのボタンを用意しています。そして、(6)でボタンが押されたときの処理として、SearchBarオブジェクトをshow()メソッドで表示するように実装しています。
まとめ
駆け足になりましたが、SQLを使ってツイートのデータを操作し、過去のツイートについても表示したり、検索したりできるような実装を解説しました。ツイートの例でもわかるように、検索を行ったり同じデータが重複しないように保存したりといったときにSQLはとても便利です。もし、Titaniumでアプリケーションを作成するときに、大量のデータを扱う必要が出てきた時にはSQLを利用することを一度考えてみてください。