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
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 2:</span>  </pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 3:</span> def initialize(name = :some_name, task_dependencies = {})</pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 4:</span> @name = name</pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 5:</span> @task_dependencies = task_dependencies</pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 6:</span> yield self <span style="color: #0000ff">if</span> block_given?</pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 7:</span> define</pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 8:</span> <span style="color: #0000ff">end</span></pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 9:</span>  </pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 10:</span> def define</pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 11:</span> task name => task_dependencies <span style="color: #0000ff">do</span></pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 12:</span> #... some code here</pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 13:</span> <span style="color: #0000ff">end</span></pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 14:</span> <span style="color: #0000ff">end</span></pre>
<p>
<!--CRLF--></div> </div>
<p>
This code works, as shown earlier and provides the ability to execute dependency tasks prior to this one:
</p>
<div>
<div>
<pre><span style="color: #606060"> 1:</span> FooTask.<span style="color: #0000ff">new</span> :somename, [:someothertask, :andanother] <span style="color: #0000ff">do</span></pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 2:</span> # ... task detail here</pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 3:</span> <span style="color: #0000ff">end</span></pre>
<p>
<!--CRLF--></div> </div>
<p>
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.
</p>
<p>
This example task, with no explicit :task_dependencies works the same as the example from the earlier post, today:
</p>
<div>
<div>
<pre><span style="color: #606060"> 1:</span> <span style="color: #0000ff">class</span> FooTask < Rake::TaskLib</pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 2:</span> </pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 3:</span> attr_accessor :name</pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 4:</span> </pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 5:</span> def initialize(name = :test)</pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 6:</span> @name = name</pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 7:</span> yield self <span style="color: #0000ff">if</span> block_given?</pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 8:</span> define</pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 9:</span> <span style="color: #0000ff">end</span></pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 10:</span> </pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 11:</span> def define</pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 12:</span> task name <span style="color: #0000ff">do</span></pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 13:</span> puts <span style="color: #008000">'I Run Second'</span></pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 14:</span> <span style="color: #0000ff">end</span></pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 15:</span> <span style="color: #0000ff">end</span></pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 16:</span> </pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 17:</span> <span style="color: #0000ff">end</span></pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 18:</span>  </pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 19:</span> FooTask.<span style="color: #0000ff">new</span> :foo => [:bar] <span style="color: #0000ff">do</span></pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 20:</span> <span style="color: #0000ff">end</span></pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 21:</span>  </pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 22:</span> task :bar <span style="color: #0000ff">do</span></pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 23:</span> puts <span style="color: #008000">'I Run First'</span></pre>
<p>
<!--CRLF-->
</p>
<pre><span style="color: #606060"> 24:</span> <span style="color: #0000ff">end</span></pre>
<p>
<!--CRLF--></div> </div>
<p>
The result of running ‘rake foo’ on this code, is this:
</p>
<p>
<img style="border-bottom: 0px;border-left: 0px;border-top: 0px;border-right: 0px" border="0" alt="image" src="https://lostechies.com/content/derickbailey/uploads/2011/03/image_0ABDF510.png" width="387" height="179" />
</p>
<p>
As you can see, the dependency task of ‘:bar’ is executed first, as expected.
</p>
<p>
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.
</p>
