The Busy Rails Developer's Intro To Rake

April 20, 2009

This is just a quick 60 second intro to Rake. If you are doing development with Ruby on Rails, you undoubtedly use Rake on a daily basis. For example, you use rake db:migrate to run your migrations or rake test:units to run your unit tests. But do you know how to write your own Rake tasks? If you never have done that, you might hesitate to write a rake task instead thinking you ran just write a quick ruby script rather than take the time to figure out how to write a Rake task.

So to create a rake task, in an existing Rails app, create a file called lib/tasks/app.rake. You can name it whatever you want as long as it ends in .rake. I'm choosing to use app because we are going to write some app-specific tasks. In the file, put this:

task :hello_world

Now from the command line you can run your task with rake hello_world. Nothing happens, but it runs. Now let's have it print hello world:

task :hello_world do
  puts "Hello, World!"
end

Now when you run your task, it prints "Hello, World!". Let's add a description to our task to let people know what it does:

desc "Prints 'Hello, World!'"
task :hello_world do
  puts "Hello, World!"
end

Now if you run rake -T, you will see your helloworld task in the list of tasks. rake -T only shows tasks that have a description. You can also run `rake -D helloworld` to see the full description of the task. You should give all of your tasks that you expect users to run from the command-line a description.

Now a problem with our task is what happens if someone else wants to write a task named hello_world? Well, we would have a namespace problem. So what we want to do is put all of our tasks into the app namespace:

namespace :app do
  desc "Prints 'Hello, World!'"
  task :hello_world do
    puts "Hello, World!"
  end
end

So now we can run our task as rake app:hello_world.

So this is obviously not a real task. Let's say we want to know what the load path of our app looks like. Easy, we'll just do this:

namespace :app do
  desc "Prints load path of this app"
  task :load_paths do
    Rails.configuration.load_paths.each do |p|
      puts p
    end
  end
end

When you try to run this rake tast, you will get this error:

rake aborted!
uninitialized class variable @@configuration in Rails

The problem is that by default, a rake task doesn't load the Rails environment. It's easy to tell it to do that with this:

namespace :app do
  desc "Prints load path of this app"
  task :load_paths => :environment do
    Rails.configuration.load_paths.each do |p|
      puts p
    end
  end
end

By saying :load_path => :environment, you are saying that the load_path task depends on the environment being loaded. Or more specifically, you are saying "run the environment task before running this task". There is a task called "environment", and it loads the Rails environment. You won't see it under rake -T, because it has no description because it is not a task you should run directly, only as a dependency of other tasks.

Now that we have the Rails environment loading, when you run the rake task, you will get the output you expect. If you make your task depend on environment, you will also be able to access your models from within your task. Now that you know the basics of Rake, you can easily get going making Rake tasks for your Rails app.

Posted in Technology | Tags Ruby, Rails, Rake

Comments

1.

yeah, from stackoverflow over here and valuable posts from you on both sites. thanks!

# Posted By Tibor on Friday, May 15 2009 at 11:34 AM

2.

Exactly the right amount of info here. Thanks!

# Posted By Matthew on Monday, January 25 2010 at 12:38 AM

3.

thanks for the info, saved me a bunch of time.

# Posted By jcran on Thursday, July 22 2010 at 10:16 PM

4.

thanks! you saved my day =)

# Posted By Liang Zan on Wednesday, July 28 2010 at 2:18 AM

Comments Disabled