Rake bootstrap:all
Sometimes when I'm building a Rails application, I want to rebuild my database from scratch. No problem you say? Just provide a lil' lighting? A lil' thunder? Or perhaps:
rake db:migrate VERSION=0
rake db:migrate
Well, yeah. That works if you only need to rebuild the database structure. But I often find myself writing plenty of rake tasks to bootstrap different parts of the system. For example:
namespace :bootstrap do
desc "Bootstrap a set of admin users"
task :admins => :environment do
puts "Bootstrapping admins"
end
task :categories => :environment do
puts "Bootstrapping categories"
end
task :zip_codes => :environment do
puts "Bootstrapping zip_codes"
end
end
Now, how would I go about running all these tasks at once? I could create an :all task that called each of bootstrap tasks:
namespace :bootstrap do
desc "Call all the bootstrap tasks"
task :all do
tasks = %w[admins categories zip_codes]
tasks.each do |task|
Rake::Task["bootstrap:#{task}"].invoke
end
end
end
This is fine if you only have a few tasks. But what if you add a new bootstrap task and fail to add it to the task list in :all?
My solution was to find a way to get all the tasks in a particular namespace. After reading through the Rake rdocs and fumbling around a bit, I finally resorted to bugging Mr. Rake himself, Jim Weirich, who provided the hint I needed:
Task manager objects are just objects that respond to the protocol required to hold and manage tasks. Currently, only the Rake::Application class responds to this protocol, but the task manager responsibilities were separated out into a module to make the list of required responsibilities more clear. You can get the current rake application object via: Rake.application
Ah! Rake.application. That's the ticket! So, here is what I ended up with:
namespace :bootstrap do
desc "Call all the bootstrap tasks"
task :all do
tasks = tasks_in_namespace("bootstrap")
tasks.each do |task|
Rake::Task["#{task.name}"].invoke
end
end
end
private
def tasks_in_namespace(ns)
#grab all tasks in the supplied namespace
tasks = Rake.application.tasks.select { |t| t.name =~ /^#{ns}:/ }
#make sure we don't include the :all task
tasks.reject! { |t| t.name =~ /:all/ }
end
You can get the sample file here: bootstrap.rake
A little rake luv is all you need:
> rake bootstrap:all
Bootstrapping admins
Bootstrapping categories
Bootstrapping zip_codes
Enjoy!