rakeタスク内で別のタスクを呼びたいなーと思い調べてみた。
Rake::Task#invoke
とRake::Task#execute
の2通りの呼び出し方があるみたい。
実際に使ってみると引数の扱い方が違っていてハマったのでメモしておく。
参考:
http://stackoverflow.com/questions/577944/how-to-run-rake-tasks-from-within-rake-tasks
試しにこんなタスクを書いてみた
namespace :mytask do
task :hello, [:person] do |t, args|
puts "hello #{args.person}"
end
task :execute_hello_to_paty do |t, args|
Rake::Task["mytask:hello"].execute("paty")
end
task :invoke_hello_to_paty do |t, args|
Rake::Task["mytask:hello"].invoke("paty")
end
end
引数の渡し方が違うため#invokeを使ってる方は期待通り動くが、#executeはエラーになる
$ bundle exec rake mytask:execute_hello_to_paty
rake aborted!
undefined method `person' for "paty":String
rake task内で使ってるargsはRake::TaskArguments
のインタンスを想定していて、#invoke
の場合は引数を良しなに加工してtaskを呼び出してくれる
159 def invoke(*args)
160 task_args = TaskArguments.new(arg_names, args)
161 invoke_with_call_chain(task_args, InvocationChain::EMPTY)
162 end
一方、#execute
では引数をそのままtaskに渡している
223 def execute(args=nil)
224 args ||= EMPTY_TASK_ARGS
....
232 case act.arity
233 when 1
234 act.call(self)
235 else
236 act.call(self, args)
237 end
238 end
239 end
なので、今回のような書き方で別taskを呼びたい場合、こんな感じで書くといける
task :execute_hello_to_paty do |t, args|
Rake::Task["mytask:hello"].execute(Rake::TaskArguments.new([:person], ["paty"])
end
あまり綺麗じゃないと思う・・・。
#execute
と#invoke
では他にも挙動の違いがあるので、どちらを使うかは状況次第な感じ
#execute
- 呼び出すタスクの依存タスクは実行しない
#invoke
- 呼び出すタスクの依存タスクも実行する
- 実行中は1度しか同じタスクを実行しない
- 再実行したい場合はRake::Task["task_name"].reenableを実行する必要がある
詳しくは参考リンク先に色々と書いてあるため割愛です。