leftovers...

about grails groovy

IDMLをごねごねする超手抜きなGrailsアプリ作った話

先日、PAGE2010という展示会にいろいろと印刷系な内容を出展してまして・・・。
展示会では、外回り担当・・・わかりやすく言うと他のブースを見て調査とかしたり。
まあ、暇ではなかったのですが、微妙にやることが無くなったので、印刷系の展示会と言うことで、今話題の(話題か?)InDesign CS4のIDMLとやらをちょいとごねごね。

さて、idmlGrailsで何を作ろうかと。
ちょうどTwitter4jでも遊んでみたかったし。
GrailsのBuildConfig.groovyでの依存性管理とかも使ってみたかったのでその辺も一緒に。
題して「微妙なTwitterカードメーカー」

  • twiter アカウントを入力
  • ユーザ情報を取得
  • ユーザ情報を使って微妙なカードを作る。
  • イコン画像とidmlファイルを含めたzipファイルを生成。
  • ダウンロード・解凍してidmlInDesignで開くと、以下のように組まれた内容が完成している。

はい、タイトルにもあるように内容も微妙です。
そのわりに内容が長くなりそうなのでポイントだけ。
では、最初にgrailsの適当なプロジェクトを新規作成

grails create-app cards

BuildConfig.groovyでの依存性管理
その昔(ほんの最近まで)は自分でlibフォルダに必要なライブラリのjarファイルをコピーしてました。その方法しかなかっただけに問題も結構おきました。自分ビルドの適当なライブラリを使ったりとか、わけもわからず必要も無いライブラリを入れまくりとか、そんな輩がプロジェクトに参加してると、もう大変です!
で、Grailsでは、conf/BuildConfig.groovyに、grails.project.dependency.resolutionを定義することで、Maveのpom.xmlみたいな感じに、ライブラリの依存性管理をしてくれます。実際裏っかわではivyを使っとる。
今回はTwitter4jを使いたいので次の手順でBuildConfig.groovyファイルに追加します。

grails-app/conf/BuildConfig.groovyをエディタで開き、grails.project.dependency.resolution =のブロックを探す。多分5行目くらい。
最初に、repositories ブロックの中の、mavenCentral()をコメントの//を外して。ほぼ19行目くらい。

repositories {
  grailsPlugins()
  grailsHome()
  ...
  //mavenLocal()
  mavenCentral()
}

そして、dependenciesブロックにruntimeスコープでtwitter4jを追加。28行目付近。

dependencies {
  //runtime 'mysql:mysql-connector-java:5.1.5'
  runtime 'net.homeip.yusuke:twitter4j:2.0.10'
}

これで完了です。
さてちゃんと動くか確認。。と、その前に若干下準備。
grails-app/conf/Config.groovyの下の方に、実験に使う自分のTwitterアカウントのユーザ名・パスを追加。これを追加しておくとGrailsのいろんな所から対象の内容が参照できる。

twitter{
  user="your twitter account"
  pass="your twitter password"
}

例えば、ConfigurationHolderをインポートしておき
import org.codehaus.groovy.grails.commons.ConfigurationHolder as CH
コードのどこかで、以下のように呼び出す。

println CH.config.twitter.user

では確認のために。Grailsコンソールを起動。

grails console

こんが画面が表示されるので、テスト用コードを入力して。

テスト用コード

import twitter4j.*
import org.codehaus.groovy.grails.commons.ConfigurationHolder as CH

def twitter = new Twitter(CH.config.twitter.user,CH.config.twitter.pass)
def timeline = twitter.friendsTimeline
timeline.each{
    println it.text
}

return 0

一番右にある実行ボタンをクリック。

設定したTwitterアカウントのタイムラインが表示されたら成功です。

画面の流れとかをつくる。
コントローラを作成
grails create-controller net.xmldo.Home
そして編集。
vi grails-app/controllers/net/xmldo/HomeController.groovy
流れが、

  1. twitterユーザ名を入力するページ
  2. twitterユーザ内容を確認するページ
  3. 生成されたidmlファイル等をダウンするページ

なので、アクションは、ザックリだが。

class HomeController {
  /** twitterユーザ名を入力するページ */
  def index = { /* フォームを表示 */ }
  /** twitterユーザ内容を確認するページ */ 
  def user = {
    /* Twitterから情報取得する処理 */
  }
  /** 生成されたidmlファイル等をダウンするページ */
  def pack = { 
    /* 受け取った情報でIDMLを形成してパックする。 */
  }
}

ビューを作る
コントローラを作った際に、grails-app/viewのフォルダ以下にhomeというフォルダが作成されます。そこにコントローラに定義した各アクションの名称のgspファイルを作成。
Grailsが初めてな人に説明すると画面の見た目を作るhtmlを書いたりするところ。

grails-app/view/home/index.gsp
grails-app/view/home/user.gsp
grails-app/view/home/pack.gsp

そして、とりあえず画面の流れなどを作り、次にTwitterからの情報取得のコードを書くと....
...と、まあ、長くなりそうなので、細かくはソースコードを参照してください。

IDMLを使う。
DML - IDMLInDesign Markup Language)
詳しくは、きれいにまとまっている以下のサイトを参照。
http://psychocat.net/IDMLWiki/index.php/Main_Page/ja
http://d.hatena.ne.jp/seuzo/20081015/1224037162
http://www.adg7.com/takenote_b/2009/04/00idmltoolswindowsvista.html
http://www.seuzo.jp/idml/test/


展示会の会場ということもあり、いつも何かを開始するとお客様が・・・。
なのでマジメにIDMLに取り組めない状況。
ぇーぃ!ってことで、
XMLとかXSLTとか仕様だとかを無視して無理矢理強引に。
最初にInDesign CS4でTwitterカードのテンプレになるようなものを作成。
そして、ファイル→書きだし... →「InDesignマークアップ(IDML)」でIDMLファイルを書き出す。
書き出したidml(実態はいろいろ入ったzipファイル)を unzipコマンドで解凍

unzip twitter_card.idml -d twitter_card

今回は、超手抜きにIDMLを扱う為に解凍されたフォルダの中から必要なxmlファイルを取り出します。そして、それらのファイルをGroovyのSimpleTemplateEngineでサクッと置き換える処理を書きます。
前準備は、こんな流れです。

  1. 対象のxmlファイルをtemplatesフォルダを作ってその中にコピー
  2. SimpleTemplateEngineは${ほにゃらら}を置きかえ対象にするため最初からある${ほにゃらら}をエスケープ→ \${ほにゃらら}
  3. 対象のxmlの中に${usename}等の変数名を必要な場所に配置

以上。
そして処理は、

  1. フォームからパラメータ受け取る。
  2. 一時作業用フォルダを生成
  3. パラメータにアイコン画像のURLがあるので取得して一時作業用フォルダに保存
  4. 解凍したidmlのフォルダ一時作業用フォルダにコピー
  5. テンプレートを読みこんで置き換えるパラメータをあてて一時作業用フォルダにコピーしたidmlフォルダの対象箇所に保存。これで必要なファイルができあがる。
  6. 一時作業用フォルダにコピーしたidmlフォルダをパッケージ
  7. 一時作業用フォルダ全体をzipする。

詳しくはソースコードを参照してください。



ちょっと長くなってしまいましたが、まとめです。

  • GrailsのBuildConfigに記述する依存性管理結構良いね!
  • IDMLを簡単に扱う場合は検索置換的にテンプレートでサックリでも、まあまあ使える。


別に納品するシステムではなくてサックリ作って、使って、使い捨てなDTP系Webアプリはこの程度が楽しくてよいですな。ちなみにブログにまとめて欲しいとの要望があったのでまとめて見ましたが・・・・。アプリ作るよりブログ書く方が時間かかりました。