Rake 中命名空间的默认任务

比如:

namespace :my_tasks do
task :foo do
do_something
end


task :bar do
do_something_else
end


task :all => [:foo, :bar]
end

如何使 :all成为默认任务,以便运行 rake my_tasks将调用它(而不是必须调用 rake my_tasks:all) ?

26269 次浏览

Place it outside the namespace like this:

namespace :my_tasks do
task :foo do
do_something
end


task :bar do
do_something_else
end


end


task :all => ["my_tasks:foo", "my_tasks:bar"]

Also... if your tasks require arguments then:

namespace :my_tasks do
task :foo, :arg1, :arg2 do |t, args|
do_something
end


task :bar, :arg1, :arg2  do |t, args|
do_something_else
end


end


task :my_tasks, :arg1, :arg2 do |t, args|
Rake::Task["my_tasks:foo"].invoke( args.arg1, args.arg2 )
Rake::Task["my_tasks:bar"].invoke( args.arg1, args.arg2 )
end

Notice how in the 2nd example you can call the task the same name as the namespace, ie 'my_tasks'

Not very intuitive, but you can have a namespace and a task that have the same name, and that effectively gives you what you want. For instance

namespace :my_task do
task :foo do
do_foo
end
task :bar do
do_bar
end
end


task :my_task do
Rake::Task['my_task:foo'].invoke
Rake::Task['my_task:bar'].invoke
end

Now you can run commands like,

rake my_task:foo

and

rake my_task

I use this Rakefile for cucumber:

require 'cucumber'
require 'cucumber/rake/task'


namespace :features do
Cucumber::Rake::Task.new(:fast) do |t|
t.profile = 'fast'
end


Cucumber::Rake::Task.new(:slow) do |t|
t.profile = 'slow'
end


task :ci => [:fast, :slow]
end


task :default => "features:ci"

Then if I type just:

rake

It runs the default task, which runs both fast and slow tests.

I learned this from Cheezy's blog.

I suggest you to use this if you have lots of tasks in the namespace.

task :my_tasks do
Rake.application.in_namespace(:my_tasks){|namespace| namespace.tasks.each(&:invoke)}
end

And then you can run all tasks in the namespace by:

rake my_tasks

With this, you don't need to worry to change your :all task when you add new tasks into that namespace.

The way I'm reading obvio171's question is that he is asking1) for a systematic way to invoke a certain task in a namespace by invoking the namespace as a task.

I've frequently encountered the same need. I like to logically group tasks into namespaces. Often that grouping resembles a hierarchy. Hence the desire to invoke the group makes very much sense to me.

Here's my take:

module Rake::DSL
def group(name, &block)
ns = namespace name, &block
default = ns[:default]
task name => "#{name}:default" if default
ns
end
end


group :foo do
task :foo1 do |t| puts t.name end
task :foo2 do |t| puts t.name end
task :default => [:foo1, :foo2]
end


task :default => :foo

1)...or was asking, years ago. Nonetheless a still interesting question.

Add the following task outside of the namespace:

desc "Run all my tasks"
task :my_tasks => ["my_tasks:all"]

Keep in mind, that you can have a task with the same name as the namespace.

And hier a bigger example, that shows, how you can make use of tasks, which have the same name as the namespace, even when nesting namespaces:

namespace :job1 do
task :do_something1 do
puts "job1:do_something1"
end


task :do_something2 do
puts "job1:do_something2"
end
task :all => [:do_something1, :do_something2]
end


desc "Job 1"
task :job1 => ["job1:all"]


# You do not need the "all"-task, but it might be handier to have one.
namespace :job2 do
task :do_something1 do
puts "job2:do_something1"
end


task :do_something2 do
puts "job2:do_something2"
end
end


desc "Job 2"
task :job2 => ["job2:do_something1", "job2:do_something2"]


namespace :superjob do
namespace :job1 do
task :do_something1 do
puts "superjob:job1:do_something1"
end


task :do_something2 do
puts "superjob:job1:do_something2"
end
end


desc "Job 1 in Superjob"
task :job1 => ["job1:do_something1", "job1:do_something2"]


namespace :job2 do
task :do_something1 do
puts "superjob:job2:do_something1"
end


task :do_something2 do
puts "superjob:job2:do_something2"
end
end


desc "Job 2 in Superjob"
task :job2 => ["job2:do_something1", "job2:do_something2"]
end


desc "My Super Job"
task :superjob => ["superjob:job1", "superjob:job2"]


# Do them all just by calling "$ rake"
task :default => [:job1, :job2, :superjob]

Just copy it and try it out.

Based on Rocky's solution Default task for namespace in Rake

And this dexter's answer Is there a way to know the current rake task?

namespace :root do
namespace :foo do
end


namespace :target do
task :all do |task_all|
Rake.application.in_namespace(task_all.scope.path) do |ns|
ns.tasks.each { |task| task.invoke unless task.name == task_all.name }
end
end


task :one do
end


task :another do
end
end
end

Combining Szymon Lipiński's and Shyam Habarakada's answers, here is what I think is the most idiomatic and consise answer:

namespace :my_tasks do
task :foo do
do_something
end


task :bar do
do_something_else
end


end


task :my_tasks => ["my_tasks:foo", "my_tasks:bar"]

allows you to do rake my_tasks while avoiding cumbersome invocation of the subtasks.