<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>http://erik.hollensbe.org/</id>
  <title>Atom Feed: Whole Site</title>
  <updated>2008-11-27T11:28:02Z</updated>
  <link rel="alternate" href="http://erik.hollensbe.org"/>
  <link rel="self" href="http://erik.hollensbe.org/feed/atom.xml"/>
  <author>
    <name>Erik Hollensbe</name>
    <uri>http://erik.hollensbe.org/</uri>
  </author>
  <entry>
    <id>tag:erik.hollensbe.org,2008-11-27:/writings/1226263095/</id>
    <title type="html">An attempt at a Ruby 1.9p1 porting guide</title>
    <published>2008-11-27T11:28:02Z</published>
    <updated>2008-11-27T11:28:02Z</updated>
    <link rel="alternate" href="http://erik.hollensbe.org/writings/1226263095/"/>
    <content type="html">&lt;p&gt;
&lt;a href="http://www.ruby-lang.org/en/news/2008/10/28/ruby-1-9-1-preview-1-released/"&gt;Ruby 1.9p1&lt;/a&gt; has been 
out for a few weeks, and bringing some of the libraries I maintain into
compliance with it has been the focus of my free time recently.
&lt;/p&gt;

&lt;p&gt;
I have collected a few things here which may help others in my position save a
bit of time debugging and bug reporting. This does not cover the changes that
were made between 1.8.6 and 1.8.7, many of which were "staging changes" for
1.9.
&lt;/p&gt;

&lt;p&gt;
This is also a work in progress, and will likely change at least once or twice
over the next month; I will note here what has changed.
&lt;/p&gt;

&lt;h3&gt;Module/Class Changes&lt;/h3&gt;

&lt;h4&gt;Low-hanging fruit:&lt;/h4&gt;

&lt;ul&gt;
    &lt;li&gt;The 'parsedate' stdlib package no longer exists; this functionality has been rolled into the date/time packages.&lt;/li&gt;
    &lt;li&gt;UnboundMethod now pulls some functionality out of Method, and as a result rebinding or calling methods via Object#method may yield unexpected results. Read the docs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Date/DateTime/Time .parse changes&lt;/h4&gt;

These now try a more international &lt;em&gt;DD/MM/YYYY&lt;/em&gt; format first when
parsing than the previously U.S.-centric &lt;em&gt;MM/DD/YYYY&lt;/em&gt; format. As a
result, you may have issues like this:

&lt;pre class="code"&gt;
&lt;span class="hl line"&gt;    1 &lt;/span&gt;&lt;span class="hl slc"&gt;# old&lt;/span&gt;
&lt;span class="hl line"&gt;    2 &lt;/span&gt;d &lt;span class="hl sym"&gt;=&lt;/span&gt; Date&lt;span class="hl sym"&gt;.&lt;/span&gt;&lt;span class="hl kwd"&gt;parse&lt;/span&gt;&lt;span class="hl sym"&gt;(&lt;/span&gt;&lt;span class="hl str"&gt;&amp;quot;10/11/2008&amp;quot;&lt;/span&gt;&lt;span class="hl sym"&gt;)&lt;/span&gt;
&lt;span class="hl line"&gt;    3 &lt;/span&gt;d&lt;span class="hl sym"&gt;.&lt;/span&gt;&lt;span class="hl kwd"&gt;strftime&lt;/span&gt;&lt;span class="hl sym"&gt;(&lt;/span&gt;&lt;span class="hl str"&gt;&amp;quot;%Y-%m-%d&amp;quot;&lt;/span&gt;&lt;span class="hl sym"&gt;)&lt;/span&gt;
&lt;span class="hl line"&gt;    4 &lt;/span&gt;&lt;span class="hl slc"&gt;# &amp;quot;2008-10-11&amp;quot;&lt;/span&gt;
&lt;span class="hl line"&gt;    5 &lt;/span&gt;d &lt;span class="hl sym"&gt;=&lt;/span&gt; DateTime&lt;span class="hl sym"&gt;.&lt;/span&gt;&lt;span class="hl kwd"&gt;parse&lt;/span&gt;&lt;span class="hl sym"&gt;(&lt;/span&gt;&lt;span class="hl str"&gt;&amp;quot;10/11/2008 10:01:02&amp;quot;&lt;/span&gt;&lt;span class="hl sym"&gt;)&lt;/span&gt;
&lt;span class="hl line"&gt;    6 &lt;/span&gt;d&lt;span class="hl sym"&gt;.&lt;/span&gt;&lt;span class="hl kwd"&gt;strftime&lt;/span&gt;&lt;span class="hl sym"&gt;(&lt;/span&gt;&lt;span class="hl str"&gt;&amp;quot;%m/%d/%Y %H:%M:%S&amp;quot;&lt;/span&gt;&lt;span class="hl sym"&gt;)&lt;/span&gt;
&lt;span class="hl line"&gt;    7 &lt;/span&gt;&lt;span class="hl slc"&gt;# &amp;quot;10/11/2008 10:01:02&amp;quot;&lt;/span&gt;
&lt;span class="hl line"&gt;    8 &lt;/span&gt;
&lt;span class="hl line"&gt;    9 &lt;/span&gt;&lt;span class="hl slc"&gt;# new&lt;/span&gt;
&lt;span class="hl line"&gt;   10 &lt;/span&gt;d &lt;span class="hl sym"&gt;=&lt;/span&gt; Date&lt;span class="hl sym"&gt;.&lt;/span&gt;&lt;span class="hl kwd"&gt;parse&lt;/span&gt;&lt;span class="hl sym"&gt;(&lt;/span&gt;&lt;span class="hl str"&gt;&amp;quot;10/11/2008&amp;quot;&lt;/span&gt;&lt;span class="hl sym"&gt;)&lt;/span&gt;
&lt;span class="hl line"&gt;   11 &lt;/span&gt;d&lt;span class="hl sym"&gt;.&lt;/span&gt;&lt;span class="hl kwd"&gt;strftime&lt;/span&gt;&lt;span class="hl sym"&gt;(&lt;/span&gt;&lt;span class="hl str"&gt;&amp;quot;%Y-%m-%d&amp;quot;&lt;/span&gt;&lt;span class="hl sym"&gt;)&lt;/span&gt;
&lt;span class="hl line"&gt;   12 &lt;/span&gt;&lt;span class="hl slc"&gt;# &amp;quot;2008-11-10&amp;quot;&lt;/span&gt;
&lt;span class="hl line"&gt;   13 &lt;/span&gt;d &lt;span class="hl sym"&gt;=&lt;/span&gt; DateTime&lt;span class="hl sym"&gt;.&lt;/span&gt;&lt;span class="hl kwd"&gt;parse&lt;/span&gt;&lt;span class="hl sym"&gt;(&lt;/span&gt;&lt;span class="hl str"&gt;&amp;quot;10/11/2008 10:01:02&amp;quot;&lt;/span&gt;&lt;span class="hl sym"&gt;)&lt;/span&gt;
&lt;span class="hl line"&gt;   14 &lt;/span&gt;d&lt;span class="hl sym"&gt;.&lt;/span&gt;&lt;span class="hl kwd"&gt;strftime&lt;/span&gt;&lt;span class="hl sym"&gt;(&lt;/span&gt;&lt;span class="hl str"&gt;&amp;quot;%m/%d/%Y %H:%M:%S&amp;quot;&lt;/span&gt;&lt;span class="hl sym"&gt;)&lt;/span&gt;
&lt;span class="hl line"&gt;   15 &lt;/span&gt;&lt;span class="hl slc"&gt;# &amp;quot;11/10/2008 10:01:02&amp;quot;&lt;/span&gt;
&lt;/pre&gt;


&lt;h4&gt;delegate.rb changes&lt;/h4&gt;

&lt;p&gt;
The bad news is that a great deal of code that uses this stdlib addition just
had the rug pulled out from under it. The good news is that all the changes are
intended to be for the better, and you can reap a great deal more flexibility
from them.  The good news is, deep copies are no longer required to properly
clone the managed object over a &lt;code&gt;#clone&lt;/code&gt; or &lt;code&gt;#dup&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
Marshal and DelegateClass play together very differently than they used to; if
you were using the old &lt;code&gt;Marshal.load(Marshal.dump(self))&lt;/code&gt; trick to
do deep copies on delegates, you will run into problems. This is because 1.9
Marshal now has dump/load hooks, and the new delegate.rb takes advantage of
them, and they operate differently than you'd think. Good for us that they're
easy to overload. Look into Marshal, or Marshal.dump for how to perform this.
&lt;/p&gt;

&lt;p&gt;
Additionally, the new 1.9 delegate.rb includes two methods on each class of
delegate (DelegateClass, Delegator, etc) named &lt;code&gt;__getobj__&lt;/code&gt; and
&lt;code&gt;__setobj__&lt;/code&gt;, which act as accessors for the underlying object. So,
this idiom no longer works:
&lt;/p&gt;

&lt;pre class="code"&gt;
&lt;span class="hl line"&gt;    1 &lt;/span&gt;&lt;span class="hl kwa"&gt;class&lt;/span&gt; Foo &lt;span class="hl sym"&gt;&amp;lt;&lt;/span&gt; &lt;span class="hl kwd"&gt;DelegateClass&lt;/span&gt;&lt;span class="hl sym"&gt;(&lt;/span&gt;Array&lt;span class="hl sym"&gt;)&lt;/span&gt;
&lt;span class="hl line"&gt;    2 &lt;/span&gt;    &lt;span class="hl kwa"&gt;def&lt;/span&gt; initialize
&lt;span class="hl line"&gt;    3 &lt;/span&gt;        &lt;span class="hl kwb"&gt;&amp;#64;arr&lt;/span&gt; &lt;span class="hl sym"&gt;= [&lt;/span&gt;&lt;span class="hl num"&gt;1&lt;/span&gt;&lt;span class="hl sym"&gt;,&lt;/span&gt;&lt;span class="hl num"&gt;2&lt;/span&gt;&lt;span class="hl sym"&gt;,&lt;/span&gt;&lt;span class="hl num"&gt;3&lt;/span&gt;&lt;span class="hl sym"&gt;]&lt;/span&gt;
&lt;span class="hl line"&gt;    4 &lt;/span&gt;        &lt;span class="hl kwa"&gt;super&lt;/span&gt;&lt;span class="hl sym"&gt;(&lt;/span&gt;&lt;span class="hl kwb"&gt;&amp;#64;arr&lt;/span&gt;&lt;span class="hl sym"&gt;)&lt;/span&gt;
&lt;span class="hl line"&gt;    5 &lt;/span&gt;    &lt;span class="hl kwa"&gt;end&lt;/span&gt;
&lt;span class="hl line"&gt;    6 &lt;/span&gt;
&lt;span class="hl line"&gt;    7 &lt;/span&gt;    &lt;span class="hl kwa"&gt;def&lt;/span&gt; reset
&lt;span class="hl line"&gt;    8 &lt;/span&gt;        &lt;span class="hl kwb"&gt;&amp;#64;arr&lt;/span&gt;&lt;span class="hl sym"&gt;.&lt;/span&gt;&lt;span class="hl kwd"&gt;replace&lt;/span&gt;&lt;span class="hl sym"&gt;([])&lt;/span&gt;
&lt;span class="hl line"&gt;    9 &lt;/span&gt;    &lt;span class="hl kwa"&gt;end&lt;/span&gt;
&lt;span class="hl line"&gt;   10 &lt;/span&gt;&lt;span class="hl kwa"&gt;end&lt;/span&gt;
&lt;span class="hl line"&gt;   11 &lt;/span&gt;
&lt;span class="hl line"&gt;   12 &lt;/span&gt;f &lt;span class="hl sym"&gt;=&lt;/span&gt; Foo&lt;span class="hl sym"&gt;.&lt;/span&gt;new
&lt;span class="hl line"&gt;   13 &lt;/span&gt;f2 &lt;span class="hl sym"&gt;=&lt;/span&gt; f&lt;span class="hl sym"&gt;.&lt;/span&gt;dup
&lt;span class="hl line"&gt;   14 &lt;/span&gt;f2&lt;span class="hl sym"&gt;.&lt;/span&gt;reset
&lt;span class="hl line"&gt;   15 &lt;/span&gt;f2&lt;span class="hl sym"&gt;[&lt;/span&gt;&lt;span class="hl num"&gt;0&lt;/span&gt;&lt;span class="hl sym"&gt;]&lt;/span&gt; &lt;span class="hl slc"&gt;# 1? wtf?&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;
This is because now, the value @arr holds is &lt;code&gt;#dup&lt;/code&gt;'d and assigned
to an underlying instance var (&lt;code&gt;@delegate_dc_obj&lt;/code&gt; in this case)
controlled by these new methods. When &lt;code&gt;#dup/#clone&lt;/code&gt; are called, they
are treated as separate objects (as it should be). However, dispatch is only
implicitly given to the one created during the &lt;code&gt;super()&lt;/code&gt; call, so
while we've cleared out &lt;code&gt;@arr&lt;/code&gt;, methods on this class and the ones
in Array will be working with the different data in
&lt;code&gt;@delegate_dc_obj&lt;/code&gt;. Quick thinkers may notice the common thread
between the deep copy problem and this one.
&lt;/p&gt;

&lt;p&gt;
To fix this issue with minimal impact, have the object accessors produce the object we want, like so:
&lt;/p&gt;

&lt;pre class="code"&gt;
&lt;span class="hl line"&gt;    1 &lt;/span&gt;&lt;span class="hl kwa"&gt;class&lt;/span&gt; Foo &lt;span class="hl sym"&gt;&amp;lt;&lt;/span&gt; &lt;span class="hl kwd"&gt;DelegateClass&lt;/span&gt;&lt;span class="hl sym"&gt;(&lt;/span&gt;Array&lt;span class="hl sym"&gt;)&lt;/span&gt;
&lt;span class="hl line"&gt;    2 &lt;/span&gt;    &lt;span class="hl kwa"&gt;def&lt;/span&gt; initialize
&lt;span class="hl line"&gt;    3 &lt;/span&gt;        &lt;span class="hl kwb"&gt;&amp;#64;arr&lt;/span&gt; &lt;span class="hl sym"&gt;= [&lt;/span&gt;&lt;span class="hl num"&gt;1&lt;/span&gt;&lt;span class="hl sym"&gt;,&lt;/span&gt;&lt;span class="hl num"&gt;2&lt;/span&gt;&lt;span class="hl sym"&gt;,&lt;/span&gt;&lt;span class="hl num"&gt;3&lt;/span&gt;&lt;span class="hl sym"&gt;]&lt;/span&gt;
&lt;span class="hl line"&gt;    4 &lt;/span&gt;        &lt;span class="hl kwa"&gt;super&lt;/span&gt;&lt;span class="hl sym"&gt;(&lt;/span&gt;&lt;span class="hl kwb"&gt;&amp;#64;arr&lt;/span&gt;&lt;span class="hl sym"&gt;)&lt;/span&gt;
&lt;span class="hl line"&gt;    5 &lt;/span&gt;    &lt;span class="hl kwa"&gt;end&lt;/span&gt;
&lt;span class="hl line"&gt;    6 &lt;/span&gt;
&lt;span class="hl line"&gt;    7 &lt;/span&gt;    &lt;span class="hl kwa"&gt;def&lt;/span&gt; reset
&lt;span class="hl line"&gt;    8 &lt;/span&gt;        &lt;span class="hl kwb"&gt;&amp;#64;arr&lt;/span&gt;&lt;span class="hl sym"&gt;.&lt;/span&gt;&lt;span class="hl kwd"&gt;replace&lt;/span&gt;&lt;span class="hl sym"&gt;([])&lt;/span&gt;
&lt;span class="hl line"&gt;    9 &lt;/span&gt;    &lt;span class="hl kwa"&gt;end&lt;/span&gt;
&lt;span class="hl line"&gt;   10 &lt;/span&gt;
&lt;span class="hl line"&gt;   11 &lt;/span&gt;    &lt;span class="hl kwa"&gt;if&lt;/span&gt; &lt;span class="hl kwc"&gt;RUBY_VERSION&lt;/span&gt; &lt;span class="hl sym"&gt;=&lt;/span&gt;~ &lt;span class="hl kwc"&gt;/^1\.9/&lt;/span&gt;
&lt;span class="hl line"&gt;   12 &lt;/span&gt;        &lt;span class="hl kwa"&gt;def&lt;/span&gt; __getobj__
&lt;span class="hl line"&gt;   13 &lt;/span&gt;            &lt;span class="hl kwb"&gt;&amp;#64;arr&lt;/span&gt;
&lt;span class="hl line"&gt;   14 &lt;/span&gt;        &lt;span class="hl kwa"&gt;end&lt;/span&gt;
&lt;span class="hl line"&gt;   15 &lt;/span&gt;
&lt;span class="hl line"&gt;   16 &lt;/span&gt;        &lt;span class="hl kwa"&gt;def&lt;/span&gt; &lt;span class="hl kwd"&gt;__setobj__&lt;/span&gt;&lt;span class="hl sym"&gt;(&lt;/span&gt;obj&lt;span class="hl sym"&gt;)&lt;/span&gt;
&lt;span class="hl line"&gt;   17 &lt;/span&gt;            &lt;span class="hl kwb"&gt;&amp;#64;delegate_dc_obj&lt;/span&gt; &lt;span class="hl sym"&gt;=&lt;/span&gt; &lt;span class="hl kwb"&gt;&amp;#64;arr&lt;/span&gt; &lt;span class="hl sym"&gt;=&lt;/span&gt; obj
&lt;span class="hl line"&gt;   18 &lt;/span&gt;        &lt;span class="hl kwa"&gt;end&lt;/span&gt;
&lt;span class="hl line"&gt;   19 &lt;/span&gt;    &lt;span class="hl kwa"&gt;end&lt;/span&gt;
&lt;span class="hl line"&gt;   20 &lt;/span&gt;&lt;span class="hl kwa"&gt;end&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;
You may notice the assignment to &lt;code&gt;@delegate_dc_obj&lt;/code&gt; in
&lt;code&gt;__setobj__&lt;/code&gt;, which is a dispatcher bug.
&lt;a href="http://redmine.ruby-lang.org/issues/show/704"&gt;Here is the ticket.&lt;/a&gt;
As of this writing it has been closed, but the bug still exists.
&lt;/p&gt;

&lt;p&gt; 
For Ruby/DBI's DBI::Row (which unsurprisingly has both of these issues), this
is working and well-exercised in the test suite, passing on both 1.8.7 and 1.9: 
&lt;/p&gt;

&lt;pre class="code"&gt;
&lt;span class="hl line"&gt;    1 &lt;/span&gt;&lt;span class="hl kwa"&gt;if&lt;/span&gt; &lt;span class="hl kwc"&gt;RUBY_VERSION&lt;/span&gt; &lt;span class="hl sym"&gt;=&lt;/span&gt;~ &lt;span class="hl kwc"&gt;/^1\.9/&lt;/span&gt;
&lt;span class="hl line"&gt;    2 &lt;/span&gt;    &lt;span class="hl kwa"&gt;def&lt;/span&gt; __getobj__
&lt;span class="hl line"&gt;    3 &lt;/span&gt;        &lt;span class="hl kwb"&gt;&amp;#64;arr&lt;/span&gt;
&lt;span class="hl line"&gt;    4 &lt;/span&gt;    &lt;span class="hl kwa"&gt;end&lt;/span&gt;
&lt;span class="hl line"&gt;    5 &lt;/span&gt;
&lt;span class="hl line"&gt;    6 &lt;/span&gt;    &lt;span class="hl kwa"&gt;def&lt;/span&gt; &lt;span class="hl kwd"&gt;__setobj__&lt;/span&gt;&lt;span class="hl sym"&gt;(&lt;/span&gt;obj&lt;span class="hl sym"&gt;)&lt;/span&gt;
&lt;span class="hl line"&gt;    7 &lt;/span&gt;        &lt;span class="hl kwb"&gt;&amp;#64;delegate_dc_obj&lt;/span&gt; &lt;span class="hl sym"&gt;=&lt;/span&gt; &lt;span class="hl kwb"&gt;&amp;#64;arr&lt;/span&gt; &lt;span class="hl sym"&gt;=&lt;/span&gt; obj
&lt;span class="hl line"&gt;    8 &lt;/span&gt;    &lt;span class="hl kwa"&gt;end&lt;/span&gt;
&lt;span class="hl line"&gt;    9 &lt;/span&gt;&lt;span class="hl kwa"&gt;else&lt;/span&gt;
&lt;span class="hl line"&gt;   10 &lt;/span&gt;    &lt;span class="hl kwa"&gt;def&lt;/span&gt; clone
&lt;span class="hl line"&gt;   11 &lt;/span&gt;        Marshal&lt;span class="hl sym"&gt;.&lt;/span&gt;&lt;span class="hl kwd"&gt;load&lt;/span&gt;&lt;span class="hl sym"&gt;(&lt;/span&gt;Marshal&lt;span class="hl sym"&gt;.&lt;/span&gt;&lt;span class="hl kwd"&gt;dump&lt;/span&gt;&lt;span class="hl sym"&gt;(&lt;/span&gt;&lt;span class="hl kwa"&gt;self&lt;/span&gt;&lt;span class="hl sym"&gt;))&lt;/span&gt;
&lt;span class="hl line"&gt;   12 &lt;/span&gt;    &lt;span class="hl kwa"&gt;end&lt;/span&gt;
&lt;span class="hl line"&gt;   13 &lt;/span&gt;
&lt;span class="hl line"&gt;   14 &lt;/span&gt;    &lt;span class="hl kwa"&gt;alias&lt;/span&gt; dup clone
&lt;span class="hl line"&gt;   15 &lt;/span&gt;&lt;span class="hl kwa"&gt;end&lt;/span&gt;
&lt;/pre&gt;


&lt;h3&gt;Syntax/Core changes&lt;/h3&gt;

&lt;strike&gt;&lt;h4&gt;Method prototypes&lt;/h4&gt;&lt;/strike&gt;

&lt;p&gt;&lt;b&gt;This was poorly researched and I am sorry if I have mislead anyone.&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Explicitly prototyped blocks are now required in the call. For example:&lt;/p&gt;

&lt;pre class="code"&gt;
&lt;span class="hl line"&gt;    1 &lt;/span&gt;&lt;span class="hl slc"&gt;# explicit block...&lt;/span&gt;
&lt;span class="hl line"&gt;    2 &lt;/span&gt;&lt;span class="hl kwa"&gt;def&lt;/span&gt; &lt;span class="hl kwd"&gt;foo&lt;/span&gt;&lt;span class="hl sym"&gt;(&lt;/span&gt;arg1&lt;span class="hl sym"&gt;,&lt;/span&gt; arg2&lt;span class="hl sym"&gt;, &amp;amp;&lt;/span&gt;block&lt;span class="hl sym"&gt;)&lt;/span&gt;
&lt;span class="hl line"&gt;    3 &lt;/span&gt;    p &lt;span class="hl sym"&gt;[&lt;/span&gt;arg1&lt;span class="hl sym"&gt;,&lt;/span&gt; arg2&lt;span class="hl sym"&gt;]&lt;/span&gt;
&lt;span class="hl line"&gt;    4 &lt;/span&gt;    &lt;span class="hl kwa"&gt;yield&lt;/span&gt; arg1&lt;span class="hl sym"&gt;,&lt;/span&gt; arg2
&lt;span class="hl line"&gt;    5 &lt;/span&gt;&lt;span class="hl kwa"&gt;end&lt;/span&gt;
&lt;span class="hl line"&gt;    6 &lt;/span&gt;
&lt;span class="hl line"&gt;    7 &lt;/span&gt;&lt;span class="hl kwd"&gt;foo&lt;/span&gt;&lt;span class="hl sym"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;1&lt;/span&gt;&lt;span class="hl sym"&gt;,&lt;/span&gt; &lt;span class="hl num"&gt;2&lt;/span&gt;&lt;span class="hl sym"&gt;)&lt;/span&gt; &lt;span class="hl slc"&gt;# wrong&lt;/span&gt;
&lt;span class="hl line"&gt;    8 &lt;/span&gt;&lt;span class="hl kwd"&gt;foo&lt;/span&gt;&lt;span class="hl sym"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;1&lt;/span&gt;&lt;span class="hl sym"&gt;,&lt;/span&gt; &lt;span class="hl num"&gt;2&lt;/span&gt;&lt;span class="hl sym"&gt;) { }&lt;/span&gt; &lt;span class="hl slc"&gt;# right&lt;/span&gt;
&lt;span class="hl line"&gt;    9 &lt;/span&gt;
&lt;span class="hl line"&gt;   10 &lt;/span&gt;&lt;span class="hl slc"&gt;# implicit block...&lt;/span&gt;
&lt;span class="hl line"&gt;   11 &lt;/span&gt;&lt;span class="hl kwa"&gt;def&lt;/span&gt; &lt;span class="hl kwd"&gt;bar&lt;/span&gt;&lt;span class="hl sym"&gt;(&lt;/span&gt;arg1&lt;span class="hl sym"&gt;,&lt;/span&gt; arg2&lt;span class="hl sym"&gt;)&lt;/span&gt;
&lt;span class="hl line"&gt;   12 &lt;/span&gt;    p &lt;span class="hl sym"&gt;[&lt;/span&gt;arg1&lt;span class="hl sym"&gt;,&lt;/span&gt; arg2&lt;span class="hl sym"&gt;]&lt;/span&gt;
&lt;span class="hl line"&gt;   13 &lt;/span&gt;    &lt;span class="hl kwa"&gt;yield&lt;/span&gt; arg1&lt;span class="hl sym"&gt;,&lt;/span&gt; arg2 &lt;span class="hl kwa"&gt;if&lt;/span&gt; block_given&lt;span class="hl sym"&gt;?&lt;/span&gt;
&lt;span class="hl line"&gt;   14 &lt;/span&gt;&lt;span class="hl kwa"&gt;end&lt;/span&gt;
&lt;span class="hl line"&gt;   15 &lt;/span&gt;
&lt;span class="hl line"&gt;   16 &lt;/span&gt;&lt;span class="hl slc"&gt;# both of these work&lt;/span&gt;
&lt;span class="hl line"&gt;   17 &lt;/span&gt;&lt;span class="hl kwd"&gt;bar&lt;/span&gt;&lt;span class="hl sym"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;1&lt;/span&gt;&lt;span class="hl sym"&gt;,&lt;/span&gt; &lt;span class="hl num"&gt;2&lt;/span&gt;&lt;span class="hl sym"&gt;)&lt;/span&gt;
&lt;span class="hl line"&gt;   18 &lt;/span&gt;&lt;span class="hl kwd"&gt;bar&lt;/span&gt;&lt;span class="hl sym"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;1&lt;/span&gt;&lt;span class="hl sym"&gt;,&lt;/span&gt; &lt;span class="hl num"&gt;2&lt;/span&gt;&lt;span class="hl sym"&gt;) { }&lt;/span&gt;
&lt;/pre&gt;


Even if you don't do this in your own code, be aware that many oft-used
packages (like Rake) make heavy use of this idiom and will require code changes
on your behalf.

&lt;h3&gt;Testing changes&lt;/h3&gt;

&lt;p&gt;
One of the largest changes I've been faced with is that &lt;code&gt;Test::Unit&lt;/code&gt;
no longer exists, superceded by &lt;code&gt;MiniTest&lt;/code&gt;. MiniTest has some
compatibility layers that will likely work with most test suites, however
MiniTest is as it is named and as a result, does not include all the
functionality the packages it's compatible with contains. If you have an
unorthodox or esoteric test suite, be prepared for a little hell.
&lt;/p&gt;


&lt;p&gt;
The good news is that &lt;code&gt;Test::Unit&lt;/code&gt;, like &lt;code&gt;RSpec&lt;/code&gt;, is now
maintained separately from Ruby, and available as a gem. Here are a few test
suites that you may want to look at to get your 1.8 test suite working again:
&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;xUnit: &lt;a href="http://rubyforge.org/projects/test-unit/"&gt;test-unit 2.0&lt;/a&gt;. The developer is extremely responsive (my bug reports have been fixed within minutes), so don't hesitate because it's a gem.&lt;/li&gt;
    &lt;li&gt;BDD: &lt;a href="http://rubyforge.org/projects/rspec/"&gt;RSpec&lt;/a&gt;. The old standard. I'm not a BDD guy but you guys win this round in the "my test suite still works" department.&lt;/li&gt;
    &lt;li&gt;BDD: (Github) &lt;a href="http://github.com/chneukirchen/bacon/tree/master"&gt;Bacon&lt;/a&gt; - &lt;code&gt;gem install bacon&lt;/code&gt;. Lightweight RSpec clone, plenty I know love this.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Just to repeat myself, most people will not need to sway from the Ruby stdlib
to get &lt;code&gt;Test::More&lt;/code&gt; functionality.
&lt;/p&gt;

&lt;p&gt;
HTH! If you have corrections, additions, or just want to flame me, 
&lt;a href="mailto:erik@hollensbe.org"&gt;email me here&lt;/a&gt;.
&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>tag:erik.hollensbe.org,2008-10-11:/random/1223708859/</id>
    <title type="html">Alistair Cockburn: Reading for Management Types</title>
    <published>2008-10-11T07:28:34Z</published>
    <updated>2008-10-11T07:28:34Z</updated>
    <link rel="alternate" href="http://erik.hollensbe.org/random/1223708859/"/>
    <content type="html">&lt;p&gt;
    &lt;a
        href="http://alistair.cockburn.us/Characterizing+people+as+non-linear%2c+first-order+components+in+software+development"&gt;This
        article&lt;/a&gt; is new to me... A co-worker gave it to me, recommending I use
    it as a basis to weigh against certain process changes I've been proposing at
    work, as a lot of that is part of my job these days.
&lt;/p&gt;

&lt;p&gt;
    I find it interesting that I am certainly not the first (and definitely not
    the last) person to read this article for the first time, but so, so many
    of these things are fairly obvious notions (Mr. Cockburn doesn't deny they
    are) and are completely absent of consideration or even acknowledgement in
    many software houses.
&lt;/p&gt;

&lt;p&gt;
    Really, it boils down to (for me):
    &lt;ul&gt;
        &lt;li&gt;First and Foremost, People are People&lt;/li&gt;
        &lt;li&gt;The people you work with are typically smart and have formed their own opinions about the current, and proposed development processes.&lt;/li&gt;
        &lt;li&gt;People are unique.&lt;/li&gt;
        &lt;li&gt;Simple processes cater more to people; even if the complex process is bulletproof, if no one likes or can remember all of it, it's futile&lt;/li&gt;
        &lt;li&gt;People will find a way to get out of anything they don't like, even if only temporarily.&lt;/li&gt;
        &lt;li&gt;Enough dissonance will result in a pointless process that results in wasting developer time without any tangible result.&lt;/li&gt;
    &lt;/ul&gt;
&lt;/p&gt;

&lt;p&gt;
    Which can be summarized as, "if they don't like it, it ain't gonna happen".
    It's more than that, with case studies and lots more detail, and the more
    valuable part of the article is how to shape your processes so that even if
    people don't like it, it doesn't impact them so heavily they can't deal
    with it.
&lt;/p&gt;

&lt;p&gt;
    Two of the agendas I've been trying to get kickstarted are TDD and
    releasing our web backend as a product (as opposed to just checking in
    whenever, wherever we feel like... which as much as you might cringe
    at the concept, it is how the majority, not the minority of small shops
    operate) and while I'm fairly certain the other senior agrees with me I
    think he's more worried about spending a lot of time (money) for a
    fruitless result.
&lt;/p&gt;
    
&lt;p&gt;
    So far the people I have on the wagon seem to be excited about it (we
    started converting legacy tests to something more TDD-able, static database
    between suites and whatnot) and the other ones simply haven't been affected
    by it; this is somethign I have to address in the near future, and will be
    the ultimate test.
&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>tag:erik.hollensbe.org,2008-10-09:/opinion/1223619033/</id>
    <title type="html">My Problem With Republicans and Democrats</title>
    <published>2008-10-10T06:41:52Z</published>
    <updated>2008-10-10T06:41:52Z</updated>
    <link rel="alternate" href="http://erik.hollensbe.org/opinion/1223619033/"/>
    <content type="html">&lt;p&gt;
These links sum it up much better than I could:
&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;&lt;a href="http://themoderatevoice.com/politics/republican-party/23331/brooks-on-palin-a-fatal-cancer-to-the-republican-party/"&gt;A Fatal Cancer to the Republican Party&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://www.reddit.com/r/politics/"&gt;Dumb kids that spend more time on reddit complaining about the lack of social change instead of really building it.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;br /&gt;
&lt;br /&gt;
</content>
  </entry>
  <entry>
    <id>tag:erik.hollensbe.org,2008-10-08:/opinion/1223445893/</id>
    <title type="html">Schema management: keep your framework out of this</title>
    <published>2008-10-08T07:23:42Z</published>
    <updated>2008-10-08T07:23:42Z</updated>
    <link rel="alternate" href="http://erik.hollensbe.org/opinion/1223445893/"/>
    <content type="html">&lt;p&gt;
Fixtures (database fixtures, specifically) and migrations (database versioning)
never cease to amaze me as a powerful tool to empower testing and enhance the
quality of any application. After all, why do you treat your source code as
some sacred, version controlled scion, but the database gets the rough
equivalent of &lt;code&gt;cp $i $i.old&lt;/code&gt; version control. Really folks, how many
applications do you know of where the schema and the manipulations to the
database aren't as important, if not more important, than the code used against
them?
&lt;/p&gt;

&lt;p&gt;
However, almost all of our options today are housed in frameworks which are
mostly whole-hog; you must accept the rest of the framework (or at least, do a
good job of faking it) to get these powerful features, or you need to write
them yourself. This is the second time I've been put to task implementing these
for a company with a custom framework and I'd rather avoid it in the future; if
you're saying to yourself, "they should just use the framework", go to business
school. You are not an engineer.
&lt;/p&gt;

&lt;p&gt;
Fixtures are more important to your test suite than your web app, and while
there are basic fixtures in your various SUnit clones out there, the concept of
tying them to a database is solely in the realm of web frameworks, which do
provide some test additions, but ultimately add fixtures and a bunch of other
crap you may or may not use; there are plenty of ways to test your web
application without having to use any of those methods. I must dare to say
that they are no less effective... and often, are much more, especially when it
comes to frameworks that mock the webserver integration bits. This posting
wouldn't be the first time someone's complained that a mocking of something as
critical as mod_perl or FCGI hasn't failed them horribly.
&lt;/p&gt;

&lt;p&gt;
More importantly, fixtures provide you with a baseline set of data. Someone
that uses fixtures effectively will re-init the database, perform that ugly
mess of joins that ultimately result in an update, and examine the result. If
they get it wrong, they do it again. They may never need or want the framework
to do this, but they do need the fixtures. I recall one time one of our
tech-savvy content team members dropped an image relation table from the
database our test suite ran against, and we were down (development-wise, at
least) a whole day getting the DBA involved to get our data back. I'd be
surprised if I was the only person this has happened to.
&lt;/p&gt;

&lt;p&gt;
Migrations provide us with powerful way of versioning the database; through the
use of DDL and DML, we can create efficient and expressive manipulations of the
database which create a &lt;b&gt;record&lt;/b&gt; and &lt;b&gt;rationale&lt;/b&gt; for these changes.
If you've ever jaunted across the office to ask Joe Hacker WTF he was thinking
when he removed a constraint from the session table, you know exactly what I'm
talking about.
&lt;/p&gt;

&lt;p&gt;
Migrations not only serve the development team but the other unsung parties
responsible for the database; the DBA, the sysadmin. They can stage these
changes before they ever reach production and examine the result without the
developer-issued rose-colored glasses, something I think many developers
under-appreciate. Additionally, a standalone migration system is the staple of
pretty much every DBA I've worked with in the past, and it's almost always
homegrown. Why not make this easier on them?
&lt;/p&gt;

&lt;p&gt;
So, &lt;a href="http://search.cpan.org/~timb/DBI-1.607/DBI.pm"&gt;Perl&lt;/a&gt; users, and
&lt;a href="http://ruby-dbi.rubyforge.org"&gt;Ruby&lt;/a&gt; users, why the hell haven't
you done this yet? My hands are tied until I can talk it over with my employer,
but simple, standalone features for fixture import/export and migration schemes;
this isn't rocket science. I don't want your framework (at least, right now).
Give me something that I can use.
&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>tag:erik.hollensbe.org,2008-10-08:/news/1220858587/</id>
    <title type="html">Using nanoc</title>
    <published>2008-10-08T05:59:45Z</published>
    <updated>2008-09-14T06:07:04Z</updated>
    <link rel="alternate" href="http://erik.hollensbe.org/news/1220858587/"/>
    <content type="html">&lt;p&gt;
We're now using &lt;a href="http://nanoc.stoneship.org/"&gt;nanoc&lt;/a&gt; to replace the
wordpress installation. It's not blog software, it's a CMS that precompiles
your site on a local machine for you to upload. It's a well-designed system and
highly extensible, and I'm not going to attempt to top Denis Defreyne's
excellent work in creating a manual, so &lt;a href="http://nanoc.stoneship.org/help/"&gt;go read it&lt;/a&gt; 
if you want the basics. However, here are some examples of code I've used to
generate this site.
&lt;/p&gt;

&lt;h3&gt;Real content management&lt;/h3&gt;

&lt;p&gt;
nanoc is more than a frontend to a template system, it understands the needs of
content maintainers. I need to know about the structure of my content, I need
to be able to enable and disable content, I need to be able to create content
with as little repeated work as possible. nanoc understands this.
&lt;/p&gt;

&lt;p&gt;nanoc fills a number of instance variables with data about the content as a
whole, and the content being built; this data can then be used to build the
document structure of your choice. For instance, pages have parent and child
information, allowing you to easily create navigation that's contextual. Here's
how I gather the pages for the "siblings" section on the left:
&lt;/p&gt;

&lt;pre class="code" class="code"&gt;
&lt;span class="hl line"&gt;    1 &lt;/span&gt;&lt;span class="hl kwb"&gt;&amp;#64;page&lt;/span&gt;&lt;span class="hl sym"&gt;.&lt;/span&gt;parent &lt;span class="hl sym"&gt;?&lt;/span&gt;
&lt;span class="hl line"&gt;    2 &lt;/span&gt;    &lt;span class="hl kwb"&gt;&amp;#64;page&lt;/span&gt;&lt;span class="hl sym"&gt;.&lt;/span&gt;parent&lt;span class="hl sym"&gt;.&lt;/span&gt;children&lt;span class="hl sym"&gt;.&lt;/span&gt;reject &lt;span class="hl sym"&gt;{ |&lt;/span&gt;page&lt;span class="hl sym"&gt;|&lt;/span&gt; page&lt;span class="hl sym"&gt;.&lt;/span&gt;path &lt;span class="hl sym"&gt;==&lt;/span&gt; &lt;span class="hl kwb"&gt;&amp;#64;page&lt;/span&gt;&lt;span class="hl sym"&gt;.&lt;/span&gt;path &lt;span class="hl sym"&gt;} :&lt;/span&gt;
&lt;span class="hl line"&gt;    3 &lt;/span&gt;    &lt;span class="hl sym"&gt;[]&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;
Here's the ERB used; this is a part of the main layout for the site, all pages
use it. You can see how the siblings section is only generated if needed, as
well as the optional parent link.
&lt;/p&gt;

&lt;p&gt;
Apologies that this is not highlighted, I haven't taught the code highlighter
embedded ruby yet.
&lt;/p&gt;

&lt;pre class="code" class="code"&gt;
&amp;lt;% 
    siblings = @page.parent ? @page.parent.children.reject { |page| page.path == @page.path } : []
    siblings.reject! { |page| page.filename == "atom" }
    if siblings and siblings.length &amp;gt; 0
%&amp;gt;
    &amp;lt;a class="leftnav-header"&amp;gt;Siblings&amp;lt;/a&amp;gt;
    &amp;lt;div&amp;gt;
        &amp;lt;%
            if @page.parent
        %&amp;gt;
            &amp;lt;a class="leftnav-link" href="&amp;lt;%= @page.parent.path %&amp;gt;"&amp;gt;Parent: &amp;lt;%= @page.parent.title %&amp;gt;&amp;lt;/a&amp;gt;
        &amp;lt;% end %&amp;gt;
        &amp;lt;% siblings.each do |page| %&amp;gt;
            &amp;lt;a href="&amp;lt;%= page.path %&amp;gt;" class="leftnav-link"&amp;gt;&amp;lt;%= page.title %&amp;gt;&amp;lt;/a&amp;gt;
        &amp;lt;% end %&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/pre&gt;


&lt;p&gt;
This produces the document structure the &lt;a
href="http://docs.jquery.com/UI/Accordion"&gt;JQuery Accordion UI Extension&lt;/a&gt;
needs to produce the fancy menus on the left. nanoc provides all the primitives
and allows me to relate the content as I see fit; how many "real" CMS's do you
know that can do that, especially with that little custom code?
&lt;/p&gt;

&lt;p&gt;
I have other tidbits in &lt;a href="default/"&gt;lib/default.rb&lt;/a&gt; which (like all
other things in &lt;code&gt;lib/&lt;/code&gt;) is loaded before compiling starts.
&lt;/p&gt;

&lt;h3&gt;Custom processing filters&lt;/h3&gt;

&lt;p&gt;
I wanted to write a filter that highlights code, since I plan to include a lot
of it here. This was always a pain in the ass in other systems, integration and
performance being the big issues. It's trivial in nanoc, since integration can
actually mean running a command-line program without the security drawbacks,
and performance is never an issue since all content is pre-compiled. It's
written as a post-processing filter and lets me use xml-style tags to indicate
where the code is, like this:
&lt;/p&gt;

&lt;pre class="code" class="code"&gt;
&lt;span class="hl line"&gt;    1 &lt;/span&gt;&lt;span class="hl kwa"&gt;&amp;lt;highlight&lt;/span&gt; &lt;span class="hl kwb"&gt;lang&lt;/span&gt;=&lt;span class="hl str"&gt;&amp;quot;ruby&amp;quot;&lt;/span&gt; &lt;span class="hl kwb"&gt;class&lt;/span&gt;=&lt;span class="hl str"&gt;&amp;quot;code&amp;quot;&lt;/span&gt;&lt;span class="hl kwa"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="hl line"&gt;    2 &lt;/span&gt;def foo(bar)
&lt;span class="hl line"&gt;    3 &lt;/span&gt;    do_something_with(bar)
&lt;span class="hl line"&gt;    4 &lt;/span&gt;end
&lt;span class="hl line"&gt;    5 &lt;/span&gt;&lt;span class="hl kwa"&gt;&amp;lt;/highlight&amp;gt;&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;
The filter strips the "lang" attribute and uses it for the processor. The rest
of the attributes are merged with the output, allowing custom styling and other
HTML niceties. This produces:
&lt;/p&gt;

&lt;pre class="code" class="code"&gt;
&lt;span class="hl line"&gt;    1 &lt;/span&gt;&lt;span class="hl kwa"&gt;def&lt;/span&gt; &lt;span class="hl kwd"&gt;foo&lt;/span&gt;&lt;span class="hl sym"&gt;(&lt;/span&gt;bar&lt;span class="hl sym"&gt;)&lt;/span&gt;
&lt;span class="hl line"&gt;    2 &lt;/span&gt;    &lt;span class="hl kwd"&gt;do_something_with&lt;/span&gt;&lt;span class="hl sym"&gt;(&lt;/span&gt;bar&lt;span class="hl sym"&gt;)&lt;/span&gt;
&lt;span class="hl line"&gt;    3 &lt;/span&gt;&lt;span class="hl kwa"&gt;end&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;
What really impressed me was how simple this was to write; in fact, I spent
over 4 hours putting this together, due to issues with various HTML parsers
that I couldn't resolve. nanoc's handles this so simply that it didn't really
cross my mind how little effort it was to get nanoc integrated into the picture
until just now.
&lt;/p&gt;

&lt;p&gt;
Here's the basics of the filter class:
&lt;/p&gt;

&lt;pre class="code" class="code"&gt;
&lt;span class="hl line"&gt;    1 &lt;/span&gt;&lt;span class="hl kwa"&gt;module&lt;/span&gt; Nanoc&lt;span class="hl sym"&gt;::&lt;/span&gt;Filters
&lt;span class="hl line"&gt;    2 &lt;/span&gt;    &lt;span class="hl kwa"&gt;class&lt;/span&gt; Highlight &lt;span class="hl sym"&gt;&amp;lt;&lt;/span&gt; Nanoc&lt;span class="hl sym"&gt;::&lt;/span&gt;Filter
&lt;span class="hl line"&gt;    3 &lt;/span&gt;
&lt;span class="hl line"&gt;    4 &lt;/span&gt;        identifiers &lt;span class="hl sym"&gt;:&lt;/span&gt;highlight
&lt;span class="hl line"&gt;    5 &lt;/span&gt;
&lt;span class="hl line"&gt;    6 &lt;/span&gt;        &lt;span class="hl kwa"&gt;def&lt;/span&gt; &lt;span class="hl kwd"&gt;run&lt;/span&gt;&lt;span class="hl sym"&gt;(&lt;/span&gt;content&lt;span class="hl sym"&gt;)&lt;/span&gt;
&lt;span class="hl line"&gt;    7 &lt;/span&gt;            &lt;span class="hl kwa"&gt;return&lt;/span&gt; content&lt;span class="hl sym"&gt;.&lt;/span&gt;strip
&lt;span class="hl line"&gt;    8 &lt;/span&gt;        &lt;span class="hl kwa"&gt;end&lt;/span&gt;
&lt;span class="hl line"&gt;    9 &lt;/span&gt;    &lt;span class="hl kwa"&gt;end&lt;/span&gt;
&lt;span class="hl line"&gt;   10 &lt;/span&gt;&lt;span class="hl kwa"&gt;end&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;
This code obviously just removes extra whitespace (the real thing is 
&lt;a href="highlight/"&gt;here&lt;/a&gt;) but you can see how easy it
is to get started. This is what I had to do in my page definition (a YAML file)
to enable it:
&lt;/p&gt;

&lt;pre class="code" class="code"&gt;
filters_post:
    - highlight
&lt;/pre&gt;


&lt;p&gt;
These definitions have hierarchy so I can do it in my defaults file as well,
allowing this filter to run on all or some of my content.
&lt;/p&gt;

&lt;h3&gt;Content is content; Display it how you like&lt;/h3&gt;

&lt;p&gt;
One of the things I wanted to do while writing this article was produce the
code sources as separate files; highlighted with the above-described highlight
filter with a link to the raw source. Producing this wasn't as hard as it could
have been, that's for sure!
&lt;/p&gt;

&lt;p&gt;
Let's establish what needs to be done:
&lt;/p&gt;

&lt;ol&gt;
    &lt;li&gt;Code needs to be barfed into a file.&lt;/li&gt;
    &lt;li&gt;Needs to be compiled twice: once with the highlighting, once to a plain text file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
nanoc has a great feature called &lt;i&gt;page representations&lt;/i&gt; which we'll use
for this task. The same page can be represented any number of times, with
different output parameters (filters, filenames, etc).
&lt;/p&gt;

&lt;p&gt;
First, create your page and edit the YAML file to look something like this
(this is for &lt;a href="highlight/"&gt;highlight.rb&lt;/a&gt;):
&lt;/p&gt;

&lt;pre class="code" class="code"&gt;
title: highlight.rb
reps:
    raw:
        skip_output: false
        filename: "highlight"
        extension: "rb"
&lt;/pre&gt;


&lt;p&gt;
As mentioned before, nanoc allows defaults that get merged in with this
definition. Here is my defaults file:
&lt;/p&gt;

&lt;pre class="code" class="code"&gt;
filters_pre: 
    - erb
skip_output: false
filters_post: 
    - highlight
reps:
    raw:
        skip_output: true
        filters_pre:
            - erb
        filters_post: []
        layout: none
site_name: "Erik's Tub o' Bullshit"
&lt;/pre&gt;


&lt;p&gt;
&lt;code&gt;reps&lt;/code&gt; starts a representation structure which contains alternative
representations. &lt;code&gt;default&lt;/code&gt; is the page that'll be generated
automatically, and does not necessarily need to be specified: it'll exist
unless &lt;code&gt;skip_output&lt;/code&gt; is set to true, which is the default for the
&lt;code&gt;raw&lt;/code&gt; representation because we don't want to represent *everything*
that way.  
&lt;/p&gt;

&lt;p&gt;
Just like the list of pages to be compiled and the page currently being
compiled, we can get at the different representations of the current page being
compiled &lt;i&gt;and&lt;/i&gt; the representation that is currently being compiled. In
this case, I have highlight set up as a post-filter for default representations
while it does not exist for raw representations. But now we have a new problem,
how do I generate those highlight tags when I need them, but not when I don't?
&lt;/p&gt;

&lt;p&gt;
Yes, there are easier ways to do this: a separate 'highlight' filter that just
ran highlight over everything would work, certainly, and maybe sooner or later
I'll do that. Until then, I came up with this solution: generate a new layout
which builds the tags for us if they're needed, based on the page
representation. Here's what the layout looks like (which requires erb, but nothing else):
&lt;/p&gt;

&lt;pre class="code" class="code"&gt;
&amp;lt;% if @page_rep.name == :default %&amp;gt;
&amp;lt;% if @close %&amp;gt;
&amp;lt;/highlight&amp;gt;
&amp;lt;% else %&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href="&amp;lt;%= @page.reps(:raw).path %&amp;gt;"&amp;gt;Click here to download&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;% if @lang %&amp;gt;
&amp;lt;highlight lang="&amp;lt;%= @lang %&amp;gt;" class="code widecode"&amp;gt;
&amp;lt;% else %&amp;gt;
&amp;lt;highlight class="code widecode"&amp;gt;
&amp;lt;% end %&amp;gt;
&amp;lt;% end %&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/pre&gt;


&lt;p&gt;
Then our actual content looks like this:
&lt;/p&gt;

&lt;pre class="code" class="code"&gt;
&amp;lt;%= render 'code', :lang =&amp;gt; "ruby" %&amp;gt;
module Nanoc::Filters
...
end
&amp;lt;%= render 'code', :close =&amp;gt; true %&amp;gt;
&lt;/pre&gt;


&lt;p&gt;
If you've missed the other links to it, the result looks like &lt;a
href="highlight/"&gt;this&lt;/a&gt;. The &lt;code&gt;render&lt;/code&gt; method takes a layout
and a splatted hash of keys/values that are interned into instance vars
available to the ERB template loaded for the layout. Our layout then generates
the highlight tags based on the representation and the vars provided to it.
&lt;/p&gt;

&lt;h3&gt;Overall...&lt;/h3&gt;

&lt;p&gt;
nanoc still has a few rough edges, but for the most part they're able to be
hurdled with little effort. There are numerous features to make content
production easier for the less technical as well, but you should read about
those yourself. 
&lt;/p&gt;

&lt;p&gt;
I highly recommend this to anyone building a new website that
wants all the features of a CMS but doesn't need the overkill that is often
plone or slash, and doesn't want to resort to using a blogging tool
for it either.
&lt;/p&gt;
</content>
  </entry>
</feed>

