#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 28 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. 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


23. 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)


24. Sharon Apr 12, 2009 at 06:29

Thanks for this Railscast. I am trying to parse an RSS feed to add data to a new Rails site and this has been a big help.


25. chaitanya Jun 07, 2009 at 21:26

Thanks Ryan, writing rake tasks is so easy!!! :-)


26. RNR Tom Dec 15, 2009 at 17:25

Of all the supposedly-easy tips for Rails development, this one REALLY DID WORK as simply and easily as advertised, even on our complex database.

This has saved me hours.


27. job search Mar 01, 2010 at 17:45

ok, I am learning it.


28. Anaheim Mar 08, 2010 at 01:43

thanks for your guiding.


29. Pratik Khadloya Mar 13, 2010 at 09:38

How we we migrate only one migration file using rake. Meaning i have a migration file named 20100628999998_load_moduls_data.rb
It has various factories which create data. I want to run only that migration/ruby file everytime, how do it do that ?


30. Pratik Khadloya Mar 13, 2010 at 09:49

Got it!

  desc "Raise an error unless the RAILS_ENV is development"
  task :development_environment_only do
    raise "Hey, development only you monkey!" unless RAILS_ENV == 'development'
  end

task :test_data => [:environment, :development_environment_only] do
    #file = Dir["db/migrate/#{ENV["VERSION"]}_*.rb"].first
    file = Dir["db/migrate/*load_test_data.rb"].first
    require(file)
    migration_class = file.scan(/([0-9]+)_([_a-z0-9]*).rb/)[0][1].camelize.constantize
    migration_class.migrate(:down) unless ENV["DIRECTION"] == 'up'
    migration_class.migrate(:up) unless ENV["DIRECTION"] == 'down'
  end

References:
1. Justin French for dev env only
http://justinfrench.com/notebook/a-custom-rake-task-to-reset-and-seed-your-database

2. bmihelac Blog http://source.mihelac.org/2007/02/21/running-database-migration-individually/


31. Sid May 05, 2010 at 14:15

Hey Guys, I'm getting the following errors in Rails 2.3.5 and gte the following error when trying to access the RAND method the way Ruan does..

undefined method `RAND'

Any ideas?


32. education degree | Jun 30, 2010 at 23:10

Very nice site and article..


33. bathroom vanities Jul 11, 2010 at 00:41

This is a good project that I know. I appreciate to you, so good luck to you!


34. Louis Vuitton Petite Noe Black M42230 Jul 16, 2010 at 08:13

nice !@@@


35. Steam Showers Jul 29, 2010 at 21:50

The society is full of wealth and other good things. They won;t realize how hard it could be when they were in the same situation.


36. error fix Aug 16, 2010 at 04:40

An alternative would be using something like BackgroundRB or AP4R, and both requires you to run an additional server in the background.


37. cheap air jordans Aug 19, 2010 at 22:45

Very nice site and article.. This is a good project that I know. I appreciate to you, so good luck to you!


38. iPhone repair Aug 23, 2010 at 04:42

Of course the taxes will have to go up elsewhere. In my opinion, all these do-gooders trying for a total ban on smoking are actually shooting themselves in the foot as they will eventually be out of pocket..


39. Promotional merchandise Aug 25, 2010 at 23:54

I think a person must be aware of the world outside of american media to be aware of this.


40. louis vuitton shoes Aug 26, 2010 at 21:14

Thanks for sharing your article. I really enjoyed it. I put a link to my site to here so other people can read it. My readers have about the same interets


41. snow boots Aug 31, 2010 at 01:00

I have this nasty aversion to cron jobs and being able to automate a custom Rake would be insanely useful.


42. Canon Zubeh?r Sep 01, 2010 at 18:15

Efox-shop Grosshandel Tablet Laptop, Tablet PC, und Touchscreen Tablet Laptop in <b><a href="http://www.efox-shop.com/dc-camcorder-canon-zubeh?r-c-133_134.html">http://www.efox-shop.com/dc-camcorder-canon-zubeh?r-c-133_134.html</a></b>
Efox-shop Grosshandel<b><a href="http://www.efox-shop.com/dc-camcorder-canon-zubeh?r-c-133_134.html"> Canon Zubeh?r</a></b>, Handy ohne Vertrag, Handy ohne Simlock,Sciphones i68, Touchscreen Handys und Handy Zubeh?re von Elektronik- Grosshandel in http://www.efox-shop.com/dc-camcorder-canon-zubeh?r-c-133_134.html


43. louis vuitton sunglasses Sep 01, 2010 at 21:28

Intimately, the post is actually the best on this laudable topic. I harmonize with your conclusions and will eagerly look forward to your future updates. Saying thanks will not just be adequate, for the fantastic lucidity in your writing.

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
Give Back to Open Source