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


   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


  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: :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


   3:     attr_accessor :name


   5:     def initialize(name = :test)

   6:         @name = name

   7:         yield self if block_given?

   8:         define

   9:     end


  11:     def define

  12:         task name do

  13:             puts 'I Run Second'

  14:         end

  15:     end


  17: end


  19: :foo => [:bar] do

  20: end


  22: task :bar do

  23:     puts 'I Run First'

  24: end

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


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.

About Derick Bailey

Derick Bailey is an entrepreneur, problem solver (and creator? :P ), software developer, screecaster, writer, blogger, speaker and technology leader in central Texas (north of Austin). He runs - the amazingly awesome podcast audio hosting service that everyone should be using, and where he throws down the JavaScript gauntlets to get you up to speed. He has been a professional software developer since the late 90's, and has been writing code since the late 80's. Find me on twitter: @derickbailey, @mutedsolutions, @backbonejsclass Find me on the web: SignalLeaf, WatchMeCode, Kendo UI blog, MarionetteJS, My Github profile, On Google+.
This entry was posted in Craftsmanship, Lambda Expressions, Rake, Ruby. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • 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).