91

Given something like:

namespace :my_tasks do
  task :foo do
    do_something
  end

  task :bar do
    do_something_else
  end

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

How do I make :all be the default task, so that running rake my_tasks will call it (instead of having to call rake my_tasks:all)?

agentofuser
  • 8,987
  • 11
  • 54
  • 85
  • have you tried putting a default into the namespace (task :default => :all) – Jim Deville Oct 16 '09 at 17:10
  • Do what Jim describes, only the default task goes outside the namespace and must include the namespace and task name. (task :default => "my_tasks:all") See my answer below for a working example. – Randy Eppinger May 13 '13 at 01:02

8 Answers8

89

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'

Daithí
  • 4,717
  • 5
  • 26
  • 35
Szymon Lipiński
  • 27,098
  • 17
  • 75
  • 77
52

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
Shyam Habarakada
  • 15,367
  • 3
  • 36
  • 47
9

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.

Joshua Pinter
  • 45,245
  • 23
  • 243
  • 245
Rocky
  • 5,486
  • 8
  • 32
  • 36
  • THANK YOU!! FFS, I was looking for something like this. Manually having to update the "parent" task with any changes or additions is brutal, especially if the tasks are kept in separate files due to their length. This is so much better. Bravo. – Joshua Pinter Feb 26 '21 at 21:10
  • For what it's worth, the `x` is of `Rake::NameSpace` class. I updated your answer to reflect this and be more explicit. – Joshua Pinter Feb 26 '21 at 21:14
  • Also updated your answer to use the shorthand `.each(&:invoke)`. – Joshua Pinter Feb 26 '21 at 21:45
4

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.

Randy Eppinger
  • 1,054
  • 13
  • 23
3

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.

zor-el
  • 320
  • 2
  • 11
1

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.

tvw
  • 316
  • 3
  • 4
0

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
Community
  • 1
  • 1
x'ES
  • 554
  • 5
  • 15
0

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.

Alexander Presber
  • 6,429
  • 2
  • 37
  • 66