I’ve recently discovered a little know feature of Rake that I would like to share.
Everyone who ever used Rails knows about rake – stuff like rake db:migrate has become automatic for a lot of us. A lot of people have also written their own rake tasks. While default Rails tasks don’t take parameters you sometimes want to make a task that has them.
The usual way to do it is to use environment variables – something like this:
rake db:migrate ENV=production
And then you can access those parameters in the task like this:
desc 'my task' task :my_task => :environment do puts ENV[:ENV] end
While this works, it feels a bit hacky – environment variables were not meant to be used like that.
Turns out there is a cleaner solution.
desc 'parametrized task' task :ptask, [:param1, :param2] => [:environment] do |t, params| puts params[:param1] puts params[:param2] end
What happens here is that we used a special rake syntax that defines parameters for the task – that’s what the first array is about. The second array is for the dependencies.
To invoke this task you do:
The extra nice thing about this approach is that the parameters become part of task declaration. If you run rake -T you will see the task listed with all its parameters, so you don’t have to remember them in your head. Another cool thing is that the parameters defined in this way propagate through dependencies. For instance:
desc 'another task' task :atask, [:param1, :param2] => [:ptask, :environment] do |t, params| puts params[:param1] puts params[:param2] end
If you now call: rake atask[1,2] both the atask and the ptask will get the parameters as needed.