RubyMotion テンプレートの基本/作り方/gem 化

むらむらめがね (@meganemura) です。普段は朝ドラ[ごちそうさんの感想とか](http://erobaka.com/archives/category/kanso_megane)を書いています。

本日は RubyMotion のテンプレートに関連する次の3つを紹介します。

 * テンプレートの基本
 * テンプレートの作り方
 * テンプレートの gem 化

自分用のテンプレートを作っておくことで、いつも BubbleWrap を Gemfile に追加している人や、Rakefile がいつもやらの設定で複雑になる人、小さめのアプリをガンガンリリースしていこうと思ってる人は、開発スタート時の負担が楽になると思います。
わくわくしてきましたね。

# テンプレートの基本

テンプレート、使ってないんですか!?

はい。
まず、`motion create` してみましょう。利用法と、 **利用できるテンプレート** が表示されます。

    $motion create
    Usage: motion create [--template=<template_name>] <app-name>
    Available templates: ios (default), osx, gem

ここでテンプレートを指定し、実行してみましょう。`Available templates` の中から今回は osx を template オプションで指定し、アプリの名前をつづけます。

    $motion create --template=osx awesome-osx-app
        Create awesome-osx-app
        Create awesome-osx-app/.gitignore
        Create awesome-osx-app/app/app_delegate.rb
        Create awesome-osx-app/app/menu.rb
        Create awesome-osx-app/Gemfile
        Create awesome-osx-app/Rakefile
        Create awesome-osx-app/resources/Credits.rtf
        Create awesome-osx-app/spec/main_spec.rb

わー、すごい。osx 用のプロジェクトができました。

はい。
さて、[RubyMotion Project Management Guide](http://rubymotion.jp/RubyMotionDocumentation/guides/project-management/index.html#_project_templates) にも書いてあるのですが、このテンプレートは自分で追加することができます。

まずは `/Library/RubyMotion/lib/motion/project/template` にあるファイルを見てみましょう。

    $ls /Library/RubyMotion/lib/motion/project/template
    gem    ios    ios.rb osx    osx.rb

この gem, ios, osx というディレクトリが `Available templates` として表示されていたものと対応しています。厳密には、このディレクトリと `~/Library/RubyMotion/template` にある **ディレクトリ** が[テンプレートとして認識されます](https://github.com/HipByte/RubyMotion/blob/02cf8d5e1d88d58807891e9f770cf3f4020fb322/lib/motion/project/template.rb#L36)。

それでは、自分用のテンプレートを作っていきましょう。


# テンプレート作成手順

さて、テンプレートの作成手順ですが、かなりシンプルです。1, 2, 3 でサクりと作成できます。

## 1. 普通にアプリを作る
テンプレートにする前にまず普通に `motion create my-app` してアプリを作りましょう。
いつも利用している gem の追加や Rakefile に framework の設定を追加、マジックコメントで encoding の指定を追加、と短時間で終わるけれどいつも行う作業をしておくといいと思います。
動くことを確認したら次のステップにすすみます。

## 2. 再構成

さて、超簡単な作業をしましょう。
テンプレートプロジェクト用ディレクトリと `files` ディレクトリを作成します(`mkdir -p my-template/files`)。


この `files` に `my-app` ディレクトリ内のファイルを全部ブチ込みます。

そして、これがテンプレートとして認識されるように
`ln -s /path/to/my-template ~/Library/RubyMotion/template/`
します。

`motion create` して `my-template` がテンプレートとして表示されることを確かめたら次のステップにすすみます。

## 3. 抽象化

2 のステップが終わった時点で、
`motion create --template=my-template app-name`
と実行可能です。
ただし、ただ app-name のディレクトリを作成して `files` 内のファイルをそのままコピーするだけの処理となります。

もう少しちゃんとテンプレートにするために、作成したアプリを抽象化します。
とはいえ Chef や Puppet のようなものではなく、しごく簡単です。
`motion create` 実行時に与えた引数 app-name を使って次の処理が行われるだけです。

 * app-name のディレクトリがつくられます
  * `files` 内のファイルがコピーされます
  * 末尾が `.erb` のファイルはレンダリングされます
     *  `.erb` をとったファイル名で[作成されます](https://github.com/HipByte/RubyMotion/blob/02cf8d5e1d88d58807891e9f770cf3f4020fb322/lib/motion/project/template.rb#L112)
     * `name` 変数に app-name が入ります
  * ファイル名の {name} が app-name に[置換されます](https://github.com/HipByte/RubyMotion/blob/02cf8d5e1d88d58807891e9f770cf3f4020fb322/lib/motion/project/template.rb#L121)

たとえば

```erb:{name}.rb.erb
app_name = "<%= name %>"
```

というファイルがあったときに、 `motion create --template=my-template bakaure` すると

```ruby:bakaure.rb
app_name = "bakaure"
```
となるわけですね。

なんと、これでひと通りのテンプレート作成作業は終わりです。
しかし、至高のテンプレートへの道はまだ始まったばかり。
常日頃からマイテンプレートを更新していくことが必要なのでしょう...。


# gem 化について

さて、上の手順を私が行ったのが、[こちら](https://github.com/meganemura/motion-template-spritekit/tree/master/template/spritekit-ios/files) になります。

何回か SpriteKit を RubyMotion で利用していて、繰り返しプロジェクトを作ってたので、面倒だったのでテンプレートにしてみました。
このテンプレートは、Xcode の SpriteKit Game テンプレートを移植したものになっています。 SpriteKit を RubyMotion から利用している例が少なかったのと、Xcode のテンプレートという一般的な内容ということから、便利かなと思って [motion-template-spritekit](https://github.com/meganemura/motion-template-spritekit) という gem にしました。
またこのテンプレートにとっての **1. 普通にアプリを作る** に相当するアプリは [spritekit-hello-world](https://github.com/meganemura/spritekit-hello-world) です。


gem の作り方は当然普通の gem と一緒です。テンプレート作成においては特に RubyMotion 用のファイルを使うわけではないので、ひな形は `motion create --template=gem` で作っても、 Bundler でつくってもいいでしょう。

すこし特殊なのは、`motion create` から gem のテンプレートを利用可能にする方法です。
テンプレートは `~/Library/RubyMotion/template` に無いと使えないということでした。そこに gem でインストールしたテンプレートへのシンボリックリンクを作成する必要があります。
それを `extconf.rb` を利用して、(ダミーの) Makefile の作成処理中にシンボリックリンクを作成する処理を[つっこんでいます](https://github.com/meganemura/motion-template-spritekit/blob/c152327515200979549c391c8da7518b34ae411a/ext/extconf.rb#L12)。
これは Watson さんの [Watson1978/motion-doc](https://github.com/Watson1978/motion-doc) を参考にしました。
ちなみに、同様のテクニックは Cocos2d-iphone, Box2D wrapper の [Joybox](https://github.com/rubymotion/Joybox) でも `motion` コマンドの拡張やテンプレートに使われていました。


# おわりに

というわけで RubyMotion でのテンプレートの基本/作り方/gem 化、について紹介しました。
参考になればうれしいです。


# 参考
 * [Creating RubyMotion 2.0 Templates](http://www.iconoclastlabs.com/blog/creating-rubymotion-2-0-templates)
 * [RubyMotion Project Management Guide](http://rubymotion.jp/RubyMotionDocumentation/guides/project-management/index.html)
 * [Watson1978/motion-doc](https://github.com/Watson1978/motion-doc)