とある角度から

お腹いっぱいたべられる幸せ

rubyを実行するgruntプラグイン作るまで(2) - 非同期でのコマンド実行

rubyを実行するgruntプラグイン作るまで(1) - gruntpluginのテンプレートを実行の続きです。

実行するrbファイルを作成

cocos2d-jsを使う機会があって、ビルド時にcc.log();を全て削除したかったので、そんなrbを作りました。
grunt-cclogdelete/cclogdelete.rb at master · 1010real/grunt-cclogdelete · GitHub

以下のような感じで、引数にファイル指定すると、ファイルの中身からcc.log( … );を削除したものを標準出力に出力します。

ruby cclogdelete.rb [対象ファイル]

gruntでコマンドを実行するには

次に、gruntからruby(というかコマンド)の実行をするにはどうするか小一時間ググる。と以下の2択?

  1. require(child-process)からexecもしくはspawnを使う
  2. grunt.util.spawnを使う

後々のgulpへの移行を見据えて1を選択。
ちなみに今回はruby実行時の標準出力をそのままファイルに出力したいので、そんな書き方は以下の様になります。

gruntでコマンドの終了を待つ(非同期で実行する)には

先ほどのコードをそのままtasks/cclogdelete.jsに記述して実行しても、うまく動きません。
なんか、rubyコマンドを呼び出した後、gruntが特に何も処理することがなくなったと認識して勝手に終了してしまう。(参考:Grunt で非同期タスクを調べてみたが・・・。 - Qiita

調べてみると、非同期でのタスクの場合には var done = this.async(); を呼出して、非同期ですってことをgruntに通知&戻ってきた関数(done)を全てのタスクが終わったら呼び出せということらしい。

てことで作ったのが以下。
処理するファイル数分のspawn作って、コマンドの終了した数が処理ファイル数になったらdone()してます。

一応そんな感じでオレオレプラグインが作成できました↓
GitHub - 1010real/grunt-cclogdelete: Delete cclog() with ruby script.

(記事分けたけど、実はもうあんまり書くことなかったことに気付いて、ソース貼り付けて稼ぎました汗)

上記をもうちょっと汎用的に、コマンドを非同期実行するgruntプラグインを作成中で、
そこではテストも書いていて、Readme.mdとnpmへの登録もする予定なので、次回はその辺を書きたいと思います。