为什么Rake无法连续调用多个任务?

40

我有一个Rake任务,如下所示我已经简化了它。 我正在使用Windows上的Ruby 1.9。

也许你想猜一下调用下面的Rake任务“list_all_levels”的结果? 应该是:

"Hello level 1"
"Hello level 2"
"Hello level 3"

但出于我不知道的原因,它只打印“Hello level 1”,然后停止。

也就是说,它总是只调用第一个任务。 如果我将第一行更改为传递参数“42”,那么它将打印“Hello level 42”,然后停止。

我想知道为什么它不会三次调用任务并打印所有三行? 是否有任何方法可以让它按照我的预期工作?

task :list_all_levels => [] do
    Rake::Task[:list].invoke 1
    Rake::Task[:list].invoke 2
    Rake::Task[:list].invoke 3
end

task :list, [:level] => [] do |t, args|
    puts "Hello level #{args.level}"
end
2个回答

60
问题在于invoke只有在需要的时候才会调用任务。运行rake --trace可以看到以下内容:
(in /tmp/ruby)
** Invoke default (first_time)
** Execute default
** Invoke list (first_time)
** Execute list
Hello level 1
** Invoke list 
** Invoke list 
所以你可以看到它试图再次调用任务:list两次。但你可以做的一件事是将主任务的内容更改为:
task :default => [] do
    Rake::Task[:list].invoke 1
    Rake::Task[:list].reenable
    Rake::Task[:list].invoke 2
    Rake::Task[:list].reenable
    Rake::Task[:list].invoke 3
end

然后需要再次运行:list任务,它会正确地打印出所有3个语句。

更加清晰的方法是使用execute而不是invoke(参考链接)

task :default => [] do
    Rake::Task[:list].execute 1
    Rake::Task[:list].execute 2
    Rake::Task[:list].execute 3
end

task :list, [:level] => [] do |t, args|
    puts "Hello level #{args}"
end

由于某种原因,这会将您的puts语句更改为仅使用args而不是args.level。在上面链接中描述了使用execute而不是invoke的一些其他注意事项。


4
将 "if changing it to execute" 改为 "如果将其改为 execute",请注意 @PandaWood,因为它们并不完全相同。可以参考 rake execute vs invoke 了解更多信息。 - Ron
1
这对我来说似乎非常违反直觉。有什么想法为什么他们会这样做? - marcovtwout
2
@marcovtwout 因为 Rake 最初是为了取代 Make 而创建的,其目的是避免重复编译。我觉得它看起来非常直观。 - Franklin Yu

8

在新执行之前,您需要重新启用任务,只需执行reenable方法即可。就像用户Mark Rushakoff提到的那样。

Rake::Task[:list].reenable

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接