Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
460 views
in Technique[技术] by (71.8m points)

ruby - Why is Rake not able to invoke multiple tasks consecutively?

I have a Rake task which I have simplified below. I'm using Ruby 1.9 on Windows.

Perhaps you would like to guess the outcome of calling the Rake task "list_all_levels" below? It should be:

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

But for reasons unknown to me, it prints only "Hello level 1" and then stops.

That is, it always invokes only the first task. If I change the first line to pass the arg "42", it would print "Hello level 42" and then stop.

I'm wondering why does it not invoke the task 3 times and print all 3 lines? And is there any way to get it to work how I would expect?

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
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The issue is that invoke only invokes the task if it is needed. Running rake --trace shows:

(in /tmp/ruby)
** Invoke default (first_time)
** Execute default
** Invoke list (first_time)
** Execute list
Hello level 1
** Invoke list 
** Invoke list 

So you can see it's trying to invoke the task :list two more times. But one thing you can do is to change the body of the main task to:

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

then the :list task is needed again and it correctly prints out all 3 statements.

The cleaner way to do it is to use execute rather than 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

That changes your puts statement to use just args rather than args.level for some reason. There are some other caveats with using execute over invoke described in the link above.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...