いつの間にかprerequisitesの型が変わっていた

自分の書いたRakeドキュメントを眺めていたら、嘘を発見してしまった。いや、嘘じゃなかったのが嘘になってしまった、というのが正しい。
巷のRake関連ドキュメントを見ていると、依存タスクをコマンドに書き入れるときに、次のようにしている。

file "hello" => ["hello.o", "message.o"] do |t|
  sh "#{CC} -o #{t.name} #{t.prerequisites.join(' ')}" #=> cc -o hello hello.o message.o
end

t.prerequisitesに依存タスクが定義されており、これをスペース区切りで繋げてコマンドの引数として渡すのである。しかし、join(' ')の部分が実に醜い。

しかし、あるときjoinを書かなくても良いことに気づいた。

file "hello" => ["hello.o", "message.o"] do |t|
  sh "#{CC} -o #{t.name} #{t.prerequisites}"
end

joinを書かない場合、t.prerequisites.to_sが呼ばれる。そして、t.prerequisitesはFileListクラスのインスタンスで、FileList.to_sは内部でjoin(' ')してくれている。従って、joinを書かなくてもよい。見た目がすっきりしてうれしいではないか。というわけで、ドキュメントにそういう修正を入れたのが昨年末のこと。

ところが、これがRake 0.8.2以降では期待したとおりに動作しない。スペースで区切られないのである。

task :default => ['xxx', 'yyy'] do |t|
  puts "#{t.prerequisites}"
end

task 'xxx'
task 'yyy'
$ rake _0.8.1_
(in /Users/idesaku/Temp)
xxx yyy
$ rake _0.8.2_
(in /Users/idesaku/Temp)
xxxyyy
$

GitHubでログをあさって、変更箇所を発見。

Prerequisites are no longer FileLists (that just seemed wrong).

Prerequisites are no longer FileLists (that just seemed wrong). · jimweirich/rake@68303da · GitHub

…prerequisitesをFileListにするのは間違っているように思える、ということで配列に置き換えたらしい。うーむ、そうかもしれない。依存先はファイルじゃなくてタスクかもしれないしな。実際、上記した例でも依存先はタスクにしているし。

ともかく、この変更でFileList.to_sの恩恵が受けられなくなったため、スペース区切りが入らなくなってしまった。試しに依存先を配列ではなくFileListにしてみたが、動きは変わらなかった。

# 事前にfoo.txtとbar.txtを作ってある
task :default => FileList['*.txt'] do |t|
  puts "#{t.prerequisites}"
end
$ rake _0.8.2_
(in /Users/idesaku/Temp)
bar.txtfoo.txt
$

そういうわけで、やっぱりt.prerequisites.join(' ')と書かねばならないようだ。マニュアルに記載されている例でもそうしてあるし、推奨されない書き方をするんじゃないよ、ってことだな。あー、ドキュメント書き直さにゃあ。