Structuring rake tasks in a DRY and object oriented way

>

When writing long rake tasks, one needs to be careful so as to structure the script in a way that is easily maintainable. For this purpose, we can use object oriented programming structures to tidy-up our rake script, even though rake scripts themselves don’t appear very object oriented. Of course, as mortal coders we should never forget the ever-correct principle DRY (Don’t Repeat Yourself), either.

My suggestion is to create a class for each rake task that is lengthy, or configurable through environment variables or rake arguments. The file that contain our rake task would look like this:


module MyNameOrCompany
  module MyProjectRakeTasks
    class MyLengthyRakeTask
      # all your constants, such as defaults
      DB_USER='saruman'

      def initialize(args)
        # init your new object
      end

      # all the methods you need to make your rake task conform DRY
      def this_is_my_repeated_code
        # ... whatever
      end
    end
  end
end

# any namespace declarations you want
desc "The description for your task"
task :my_lengthy_rake_task, :arg1, :arg2, :needs => :some_other_task_or_environment do |t, args|
  task_object = MyLengthyRakeTask.new(args)
  # .. whatever your task will do
end

Creating such a class has these benefits:

  • The constants that can be used to configure how our code works can now be put in the class, very near the top of the file, without tainting the global namespace. 
  • We can move some of our code into this class as methods, to keep our code DRY.
  • We can store the arguments and the defaults in your class, and access it through the task object. This provides a clear separation between the local variables in your task, and variables that hold the arguments, and the configuration that is computed from these arguments. It also makes the configuration available to the methods that you move into this class.

May your debugger never fail…
–eg