Los Techies : Blogs about software and anything tech!

An Alternate Way To Handle Task Dependencies In Custom Rake Tasks


Earlier today, I showed how to create a custom Rake task from the base TaskLib, so that we can use more than just simple “task :name” syntax for our rake tasks. In that example, I showed how to add explicit support for task dependencies by adding a second parameter to the initializer of our custom task:

   1: attr_accessor :name, :task_dependencies
   2:  
   3: def initialize(name = :some_name, task_dependencies = {})
   4:   @name = name
   5:   @task_dependencies = task_dependencies
   6:   yield self if block_given?
   7:   define
   8: end
   9:  
  10: def define
  11:   task name => task_dependencies do
  12:     #... some code here
  13:   end
  14: end

This code works, as shown earlier and provides the ability to execute dependency tasks prior to this one:

   1: FooTask.new :somename, [:someothertask, :andanother] do
   2:   # ... task detail here
   3: end

It turns out there is a much less explicit, much more ruby-ish way to do the same thing. It seems that rake understands that the name of the task (the :name accessor) is to be treated as if it were a method. Since all methods in ruby have an implicit lambda block, as we’ve seen, we don’t have to include the explicit version of the :task_dependencies in our code. We can simplify the custom task and remove all of the :task_dependencies usage. Then we only need to call the => lamba when setting the name of the task in our rake file.

This example task, with no explicit :task_dependencies works the same as the example from the earlier post, today:

   1: class FooTask < Rake::TaskLib
   2:     
   3:     attr_accessor :name
   4:     
   5:     def initialize(name = :test)
   6:         @name = name
   7:         yield self if block_given?
   8:         define
   9:     end
  10:     
  11:     def define
  12:         task name do
  13:             puts 'I Run Second'
  14:         end
  15:     end
  16:     
  17: end
  18:  
  19: FooTask.new :foo => [:bar] do
  20: end
  21:  
  22: task :bar do
  23:     puts 'I Run First'
  24: end

The result of running ‘rake foo’ on this code, is this:

image

As you can see, the dependency task of ‘:bar’ is executed first, as expected.

Considering everything that I’ve been learning about ruby in the last few days, I have to say that this feels more like the ruby way of coding. It is far less explicit, reduced code, still as functional, and has the syntax of a standard ‘task :foo => :bar do’ call that most rake users are familiar with.

Kick It on DotNetKicks.com
Posted Sep 17 2009, 08:30 PM by derick.bailey

Comments

Reflective Perspective - Chris Alcock » The Morning Brew #436 wrote Reflective Perspective - Chris Alcock &raquo; The Morning Brew #436
on 09-18-2009 3:36 AM

Pingback from  Reflective Perspective - Chris Alcock  » The Morning Brew #436

Brian wrote re: An Alternate Way To Handle Task Dependencies In Custom Rake Tasks
on 09-18-2009 11:37 AM

In ruby this " => " is not a lambda indicator.  It's is the delimiter between key and value in a hash.  You're right in stating you can pass ":name => [:dep1, :dep2] " to the rake task method...however, what you're passing is a single argument to that method.  The argument is a single-item hash consisting of a key (the left side of the arrow, the task's name in symbol form) and an array as the value (symbols of other names of task dependencies).  Actual lamda objects aren't incredibly common in ruby as the are in C# due to blocks, which are similar to lamdas, but not quite the same.  The task method ALSO takes a block (indicated by the do/end pair).

Copyright Los Techies 2008, 2009. All rights reserved.
Powered by Community Server (Commercial Edition), by Telligent Systems