#66
Aug 13, 2007

Custom Rake Tasks

Rake is one of those tools that you don't realize how powerful it is until you start using it. In this episode you will learn how to create custom rake tasks and improve them by using rake features.
Tags: tools
Download (19.9 MB, 10:06)
alternative download for iPod & Apple TV (13.3 MB, 10:06)

Resources

namespace :pick do
  desc "Pick a random user as the winner"
  task :winner => :environment do
    puts "Winner: #{pick(User).name}"
  end

  desc "Pick a random product as the prize"
  task :prize => :environment do
    puts "Prize: #{pick(Product).name}"
  end
  
  desc "Pick a random prize and winner"
  task :all => [:prize, :winner]
  
  def pick(model_class)
    model_class.find(:first, :order => 'RAND()')
  end
end

RSS Feed for Episode Comments 24 comments

1. Dougal Aug 13, 2007 at 00:38

So sweet, I was just about to write some custom rake tasks. Thanks Ryan. This is not the first time that you've published a screencast on a topic that i'm working on. Thanks once again.


2. chineseGuy Aug 13, 2007 at 03:02

Great!
I like the ":environment" to uses AR.
task :winner => :environment do
end


3. Bryce Aug 13, 2007 at 09:12

Great railscast Ryan. I miss the 3 per week fix I used to get, but still enjoy them one at a time.

Is there a way to programatically issue a rake command in a live application? There are times when I think it would be a good idea to have users invoke a generator or a rake task.

Thanks,
Bryce


4. Ryan Bates Aug 13, 2007 at 09:21

@Bryce, good question. I don't know of a way to do this but I haven't looked into it much. If you are the author of the rake task, I recommend turning it into a class and putting it in your lib directory. Then you can use that class from both your rake task and anywhere else.

If anyone else knows a solution to this problem, please comment.


5. Ho-Sheng Hsiao Aug 13, 2007 at 12:06

@Bryce, I think Ryan's suggestion of dropping it into a class is the best idea. Otherwise, you make something like a

system "cd #{RAILS_ROOT}; rake whatever"

though

system 'rake whatever'

might be sufficient.

That has its own problems, since it will block the entire request until that is done. An alternative would be using something like BackgroundRB or AP4R, and both requires you to run an additional server in the background.

Ho-Sheng Hsiao
Isshen, LLC


6. Bryce Aug 13, 2007 at 14:37

Thank you Ryan and Ho-Sheng. If I create a class, can Rails generate new files like a generator or rake task can? (should this go to the rails forum?)

The goal is to create db tables and .rhtml files programatically on the fly.

Thanks again,
Bryce


7. Ryan Bates Aug 13, 2007 at 20:51

@Bryce, the generator script is just a ruby class, so I'm sure there's some way to call it dynamically from other code, but I don't know how exactly.

However, I doubt it is the best solution to your problem. Very rarely should you need to generate tables and rhtml files dynamically. Instead I recommend adding another layer of abstraction, so you're adding rows to a table instead of tables to the database. You can store the contents of a template in the table row as well.

The forum would be a good place to make a thread about this so you can go into more detail on what you're trying to accomplish.


8. Sumit Aug 14, 2007 at 20:42

Hey Ryan. Another awesome railscast. And i concur with Bryce... Id watch every day if you made them!

Does anyone know of a way to automate a Rake to run nightly or based on some set interval? For some reason I have this nasty aversion to cron jobs and being able to automate a custom Rake would be insanely useful.


9. dudzjosh Aug 15, 2007 at 05:08

Hey Ryan great screencast.

I want to make a rake task to db:migrate both development and test databases at the same time

Just wondering if you know a way to call an exisiting rake task within a rake task and pass it a parameter?

This is what I have so far:

<pre>
namespace :db do
  desc "Migrate development & test"
  task :all do
    Rake::Task['db:migrate'].invoke
  end
end
</pre>

Also is there a way to pass variables in to a rake task and access them from the task?

eg

rake db:all VERSION=0

Cheers,

Josh


10. sam Aug 15, 2007 at 18:12

Real good screencast. I was just wondering, what theme do you use for textmate? I've only just purchased it.

Thanks


11. David Aug 16, 2007 at 09:30

@sam

Take a look at "About Railcast" for more infos about the used tools.


12. Chris Aug 16, 2007 at 10:25

Thanks for this screencast! I just subscribed and I'm loving every episode.


13. Michael Cindric Sep 17, 2007 at 21:19

This will work mate

namespace :migrate do
  desc "Migrates development and test databases"
  task :dev do
    puts "Migrating development database"
    Rake::Task["db:migrate"].invoke
    
    puts "Migrating test database"
    Rake::Task["db:test:clone"].invoke
    puts "Test migration complete"
  end
end

You just then call it like so

rake migrate:dev


14. Sumit Sep 27, 2007 at 17:32

Im just starting my research on this but does anyone know of a way to change the DB configs that :environment calls? It works fine locally but when i try to run this on my stage server its trying to use root @ localhost which is is the development block of our database.yml account. I need to it to use one of the others. Ill post if I find the solution. Thanks in advance!


15. Ryan Bates Sep 28, 2007 at 14:11

You'll have to specify the rails environment when you call your rake task. Like this:

rake pick:winner RAILS_ENV=production

It defaults to development.


16. Ben Sep 30, 2007 at 00:34

Thanks so much! I've been looking all over for a tutorial on custom rake tasks. This was a god-send.


17. Mario Nov 07, 2007 at 09:01

Very ninja like. Thanks a lot for this railscast.


18. @lfonso Nov 28, 2007 at 14:28

Lots of good info bundled in this railscast. thanks a million.


19. Mikael Høilund Feb 28, 2008 at 15:33

Very useful! I just used your tutorial to automize a huge time leech in my creation of projects. Thank you.

Is it possible to define "global" rake tasks, which are available to all projects, a la ~/.rails/generators? ~/.rails/tasks isn't searched.


20. Ryan Bates Feb 29, 2008 at 10:58

@Mikael, yep! See Sake:
http://errtheblog.com/posts/60-sake-bomb


21. Peter Michaux Apr 04, 2008 at 16:43

What a great screencast! Thanks for taking the time to put it together.


22. kino May 23, 2008 at 01:52

Since knowledge of our sense perceptions is a priori, there can be no doubt that, in accordance with the principles of our sense perceptions, applied logic excludes the possibility of the never-ending regress in the series of empirical conditions, but our experience is the mere result of the power of philosophy, a blind but indispensable function of the soul.


23. Jamie Hill Jun 11, 2008 at 05:03

I have found that as of Rails 2.1, you need to require 'environment' to be able to use models in a rake task


24. joahking Jul 11, 2008 at 04:01

@dudzjosh:
params passed like version=0 can be accessed using ENV e.g:
if ENV.include?('version') and ENV['version'].eql?(XXX)

Add your comment:

(SKIP THIS ONE)

(required)

(not shown)


(use pastie or gist for code)

sponsored by:
if you want to help:
required:
Get Quicktime Player