読者です 読者をやめる 読者になる 読者になる

Google CloudSQLとGoogleAppsScriptのHTMLServiceでアルクマを追いかける

GoogleAppsScript GoogleAppEngine イベント

Advent Calendar in 信州松本(だけじゃなくてもいいよ)の13日目を担当しているthinkAmiです。


さて、前回担当の 9日目の記事では、GoogleAppsScript(以下GAS)とGoogleAppEngine(以下GAE)でアルクマと遊びましたが、今回もアルクマという素材は同じで遊びます。
前回とはやり方を変えてみようということで、「今年からGASで利用できるようになった機能を使う」をメインテーマにアルクマップを作成してみました。



GASでGUI表示する方法について

従来どおりのGoogleSiteやUiServiceに加え、今年よりHTMLServiceでも表示できるようになりました。
HTMLServiceでは、HTMLのほかjQueryも使えるようなので、本当に使えるのかの検証も含め、利用してみます。



GASとGAEのデータ連携方法について

Webでよく見かけるのはGoogleスプレッドシートを使ったものです。
ただ、先月よりGASからGoogle CloudSQLへアクセスできるようになったため、今回はそちらを利用します。
参考:グーグル、MySQL互換の「Google Cloud SQL」性能強化。最大でメモリ16GBへ拡張。Google Apps Scriptからも利用可能に - Publickey



構成

以上2点を踏まえた全体の構成は以下の通りとなります。



Google CloudSQLの設定について

Google APIConsoleに設定が必要なため、事前に行なっておきます。

  • Billingに、クレジットカードの設定 (今回利用するD0インスタンスは、2013年6月1日までは無料とのこと)
  • CloudSQLサービスのAuthorized Applicationsに、GAEのアプリケーションIDを設定
  • SQLPromptなどで、databaseやtableを作成

Google CloudSQLのアクセスについて

■GAE側
公式ドキュメント通りで、簡単にアクセスできます。
Using Google Cloud SQL with the App Engine Python SDK - Google App Engine — Google Developers


delete&insert&commitという流れですが、特に問題なく動作しました*1

def _update(self, schedules):

    # (手抜きのため) 全削除後に登録する
    keys = _get_api_key()
    cn = rdbms.connect(instance=keys['instance'], database='arukuma')

    # 文字コードを指定してあげないと、開発環境では文字化けする
    # See: http://www.dasprids.de/blog/2007/12/17/python-mysqldb-and-utf-8
    # 開発環境のみ必要な設定(本番環境はutf-8化されているのか、大丈夫っぽい)
    if debug:
        cn.set_character_set('utf8')

    cursor = cn.cursor()
    self._delete(cn, cursor)
    self._insert(cn, cursor, schedules)

    cn.commit()
    cn.close()


def _delete(self, cn, cursor):
    sql = 'DELETE FROM schedule'
    cursor.execute(sql)


def _insert(self, cn, cursor, schedules):
    sql = 'INSERT INTO schedule (day, title, place) VALUES (%s, %s, %s)'
    for s in schedules:
        cursor.execute(sql, (s.day, s.title, s.place))


■GAS側
こちらも公式ドキュメント通りです。
JDBC - Google Apps Script — Google Developers


ただ、自分が探した範囲では、GAS上でCloudSQLのデータを使用する際に、列名指定ができず、indexでしか取得できませんでした。

var EventList = function(title, place, day){
  this.title = title;
  this.place = place;
  this.day = day;
}

var connectionString = "jdbc:google:rdbms://" + InstanceName + "/arukuma";
var conn = Jdbc.getCloudSqlConnection(connectionString);
var stmt = conn.createStatement();

var rs = stmt.executeQuery("select * from schedule");

var events = [];
while(rs.next()){    
events.push(new EventList(rs.getString(1),
                          rs.getString(2),
                          rs.getObject(3)
                         ));
}

GASのHTMLServiceでの制限について

HTMLServiceはGoogle Cajaの中で動作するため、いろいろと制限があります。
Introduction - Google Caja — Google Developers


今回の場合だと、動的なGoogleMAPが使えなかったため、GASのMAPsServiceのStaticMapを利用することにしました。
名前の通り静的な地図となりますが、マーカーの画像は変更できるため、今回の目的としては最低限満たせるかと思います。



GASのHTMLServiceのCSSについて

CSSファイルを配置する方法が分からなかったため、jQueryにて設定しました。
それにより、jQueryが動作することも確認できました。


デモ

以下のURLとなります。GAS自体をWebアプリケーションとして公開しているため、URLが特殊な感じです。
自分の作り方が悪いのか、作成者以外でアクセスした場合は、「This application was created by another user, not by Google.」のような警告が画面上部に出ます。
アルクマップ - HTMLService版


お願いなど

  • Google CloudSQLにおけるD0インスタンスの試用期間は2013/6/1までのようですので、それまでにはデモページを停止します。ご了承ください。
  • 静的な地図のため、場所へのリンクなどは行なっていません。
  • 場所から緯度・経度を求める際、Googleが変換できなかった場合には、アルクマの生息地へとマーカーを立てるようにしました*2
  • アルクマスケジュールのHTML構造が変わった場合には、こちらにスケジュールを反映できなくなるかもしれません。来年一月は大丈夫か不安です。
  • 前回のバージョンに比べてさらにパフォーマンスが悪化していますので、ブラウザに反映されるまで気長にお待ち下さい。

ソースコード

前回のGitHubリポジトリに、追加でコミットしています。ライセンスはApache2.0で変わりません。
thinkAmi/ac2012matsumoto · GitHub


まとめ

開発環境さえできてしまえば、予想以上にGoogle CloudSQLへの接続は簡単でした。
開発中の動作確認をするときに、「バージョン管理→Webサイトとして公開」を何度も繰り返したため、そこを省力化できればより効率的に開発ができそうです。



次は

Advent Calendar in 信州松本(だけじゃなくてもいいよ)、次はハラヒロシさんです。よろしくお願いします。

*1:トランザクションは実装せず。実装方法が分からないというのもあり

*2:日本アルプスのうち、信州松本にある一番高い山を選びました