Posted at

rakeタスク内で別のタスクを呼び出す

More than 5 years have passed since last update.

rakeタスク内で別のタスクを呼びたいなーと思い調べてみた。

Rake::Task#invokeRake::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を呼び出してくれる


rake-10.1.0/lib/rake/task.rb

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に渡している


rake-10.1.0/lib/rake/task.rb

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を実行する必要がある

詳しくは参考リンク先に色々と書いてあるため割愛です。