Rake Tasks

4 Min. Read
Oct 15, 2020

Tasks

Before starting, let us understand what tasks are in general.

To put it in simple terms, a task is piece of work to be done, usually assigned piece of work often to be finished within a certain time.

Rake Tasks

According to wiki, Rake is a software task management and build automation tool. It allows the user to specify tasks and describe dependencies as well as to group tasks in a namespace.

From the defination itself we can understand that Rake is simply a software that allows user to define and then run those tasks.

Any file that ends with an extension .rake is a Rake Task. These files/tasks can then be called and executed. All of this is possible using Rake.

You can call the defined Rake tasks, simply by using the command:

1
rake "your_rake_file"

Since version 5.0 Rails, rails allows you to call most rake commands with rails instead.

So, both the commands works perfectly to fire your tasks.

1
2
rake 'your_rake_file'
rails 'your_rake_file'

You don’t have to worry about installing Rake. Rake is itself a gem, that is installed as soon as you install Rails Gem.

Below we will discuss some examples on how to create rake tasks, how to define many rake tasks under a same namespace, and many more.

Creating a simple Rake Task

All the rake tasks that you create, should be put under the /lib/tasks/ directory of your project.

As mentioned earlier, the file should end with .rake extension.

From there on, creating a Rake task is quite simple.

1
2
3
4
task :print_hello_world do
  desc "This task prints hello world"
  puts "Hello World"
end

As you can see in the example above, I created a task named print_hello_world. The name of the task can also be a string, in the above example I have used symbol instead.

Inside the block, we can write any valid ruby code. In the example above, I have used desc to describe the use of the task, and then printed Hello World in the next line.

Now, to execute this task, we simple use the command:

1
2
3
rake print_hello_world
# OR
rails print_hello_world

Grouping many tasks within the same namespace

Suppose, instead of using a single rake tasks, we have the need of many rake tasks, that serve the same purpose.

You may have encountered this use case if you’ve ever used rake commands such as:

1
2
rails db:create
rails db:migrate

In this case, both the create and migrate are rake tasks that both belong to the same namespace db.

When triggering a task that belongs to a specific namespace, we use the command in the following format:

1
rake your_namespace:your_rake_task

So, now let us learn how to create various tasks that belong to a same namespace.

1
2
3
4
5
6
7
8
namespace :mytask do
  task :first_task do
    puts "Hello World from First Task"
  end
  task :second_task do
    puts "Hello World from Second Task"
  end
end

Here, we have created two tasks first_task and second_task under the namespace mytask. Now, let’s run the tasks and and inspect the output.

1
2
rake mytask:first_task #=> Hello World from First Task
rake mytask:first_task #=> Hello World from Second Task

Passing arguments to a Task

Let’s talk about the cases when you want to pass arguments to a task. In our example, let us suppose that we want to print a variable that is passed while executing the rake command.

1
2
3
4
5
6
7
8
namespace :mytask
  desc "This task takes arguments"
  task :taskA, [:arg_1,:arg_2] do |task,args|
    puts args
    puts args[:arg_1]
    puts task
  end
end

We have defined a new task taskA, and then also defined that the task takes two arguments arg_1 and arg_2.

This time the block takes two arguments task and args. The task arguments stores the information of the task itself, and args stores the arguments that are passed while executing the task, we can see this in the example below:

1
2
3
4
rails mytask:taskA["A","B"]
#=> #<Rake::TaskArguments arg_1: A, arg_2: B>
#=> A
#=> mytask:taskA

The first output shows all the passed arguments while executing the task, the second output prints a specific argument, and the final output prints the task itself.

NOTE: Sometimes your zsh might throw an error while executing rake commands that take arguments. zsh might not recognize the command. In that case you will have to escape the box brackets, i.e. use

1
rake mytask:taskA\["A","B"\]

Executing one task before another

Suppose you have two tasks, task_1 and task_2, and wish to execute task_2 before task_1, you can accomplish it in the following way:

1
2
3
4
5
6
7
8
9
10
11
12
13
namespace :mytask do

  desc "Executing some task_2 before task_1 within the same namespace"
  task task_1: [:task_2] do
    puts "Hello from Task 1"
  end

  task :task_2 do
    puts "Hello from Task 2"
  end

end

The tasks that you want to execute before task_1, must be put inside the box bracket int the order you want them to execute.

The output for the above example will be as follows:

1
2
3
rails task_1
#=> Hello from Task 2
#=> Hello from Task 1

The contents of task_2 is printed before the contents of task_1.

If you want to execute a task that belongs to a different namespace then use the following syntax:

1
2
3
  task task_1: ["different_namespace:task_2"] do
    puts "From Nothing Task"
  end

Now, this will execute the task_2 in the “different_namespace” namespace before executing task_1.

Managing task execution order and passing arguments at the same time

If you want to pass arguments to your current task, and also call other tasks before executing your own task, the syntax will look as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
namespace :mytask do

  # Using  arguments, and before calls together
  task :final_task, [:args_1,:args_2] => [:task_2,"different_namespace:task_2"] do |task,args|
    puts args[:args_1]
  end

  task :task_2 do
    puts "Hello World from Task 2 in the same namespace"
  end

end

namespace :different_namespace do
  task :task_2 do
    puts "Hello World from Task 2 in a different namespace"
  end
end

When you run the final_task, you will get output as follows:

1
2
3
4
5
rails mytask:final_task["Hello World from task arguments"]

#=> Hello World from Task 2 in the same namespace
#=> Hello World from Task 2 in a different namespace
#=> Hello World from task args