<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title><![CDATA[Jordan Ritter]]></title>
  <link href="http://www.darkridge.com/~jpr5/atom.xml" rel="self"/>
  <link href="http://www.darkridge.com/~jpr5/"/>
  <updated>2017-10-13T09:20:05-07:00</updated>
  <id>http://www.darkridge.com/~jpr5/</id>
  <author>
    <name><![CDATA[Jordan Ritter]]></name>
    <email><![CDATA[jpr5@darkridge.com]]></email>
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
    <entry>
      




<title type="html"><![CDATA[Why we do what we do]]></title>
<link href="http://www.darkridge.com/~jpr5/2013/02/14/why-we-do-what-we-do/"/>
<updated>2013-02-14T07:42:00-08:00</updated>
<id>http://www.darkridge.com/~jpr5/2013/02/14/why-we-do-what-we-do</id>

      <content type="html"><![CDATA[<p>Recently I came across some old nostalgic bits from one of <a href="http://www.cloudmark.com/">my companies</a>.
One of those bits was an email I wrote to the entire company, following a
particularly large website and product launch the night before.  An incredible
amount of time and effort had gone into making that launch successful, and
succeed it did.</p>

<p>What stands out to me now, reading this again, is how well it speaks to why I
love what I do, and why the great people I&#8217;ve been privileged to work with did
so alongside me.</p>

<p>This <em>is</em> what <a href="http://www.brepettis.com/blog/2009/3/3/the-cult-of-done-manifesto.html">all companies should be about</a>:</p>

<pre><code>Everyone,

        I just wanted to share with you some feelings I had from last
night, which relate to the very core of what I think makes Cloudmark
so great.

It was only a short few years ago that we were trying to decide how to
"launch" our products and services, and settled on creating an Outlook
plugin that would establish us commercially in the consumer market.
At the time, SpamNet was about as Beta as you can get -- we had no QA
beyond development itself -- and quite frankly it really wasn't ready
for prime-time.  But, we set an aggressive goal for ourselves, a firm,
finite deadline for us to work towards.  PR/Marcom aimed all the
reviews and newspaper articles and press releases for that date, Web
had gotten all the content prepped and ready to go, and like it or not
we had to ship or otherwise lose the tremendous groundswell of
interest and buzz that most startups only dream of.

Then came the night of shipping.

Most people were still in the office as the 12:00am deadline
approached, huddled around computers, watching and waiting.  There was
a palpable anxiety in the air, but it was the good kind -- everyone
could sense how well we would be received, and we were about to make
our first concerted mark upon the world -- us against those who
doubted us, our technology and even the viability of an anti-spam
industry.  There were last minute compiles, last minute bug fixes,
last minute web content tweaks, last minute server configuration
changes, last minute adjustments to any and every thing that was going
out.  Articles from the Wall Street Journal and LA Times were waiting
to go live, our press release and web site were almost literally under
a big red button, ready to hit the wire at a moment's notice.  And
while we were dashing back and forth to make everything as perfect as
possible, the deadline loomed.  Under an impossible time constraint,
we weren't calmly waiting for it, we were frantically trying to beat
it.

And we did.  We came together as a Team, under immense pressure and
Great Expectations, and we did it -- we shipped, we shipped, we
shipped!  That single moment culminating into release is still as
intoxicating to me now as it was that very night.

And now I am once again proud, almost awed to see that same relentless
energy and unbreakable spirit alive and well.  Huddled around
computers, one group focused on QA, another on development/bugfixing,
yet others working on website content and deployment, all in unison
and everyone pitching in where possible -- hey try this, whoops we
missed that, wow that looks great!  Our deadline loomed, lots of last
minute changes right up until the end, and due to the inevitable
problems from such tight deadlines there was an ever-so-slight patina
of despair in the air -- but nothing broke our determination.  We
would be damned if anything was going to keep us from our goal, come
hell or high water we were going to ship our new website and 4 -- 4!!
products -- all in one night.  No one left until their job was done,
and even then some stayed longer to help, if not in function then in
presence and spirit.  And those that weren't there, either polling the
website, providing suggestions on SILC, or just thinking about
shipping, well, they were there too.

Folks, this is who we are, what we stand for -- as a united team of
talented, passionate, determined people we are a force to be reckoned
with, and one that is easily underestimated.  We can achieve anything
we put our efforts towards so long as we work hard, work smart, and
work together.  While late nights against impossible deadlines
shouldn't be the norm, I consider it a privilege to share in them and
hope that this great spirit of ours never dies.

Cheers, and I hope you all have a festive, restful 4th of July
weekend.

--jordan
</code></pre>

<p>Indeed, the great spirit does live on.</p>
<p><a rel="bookmark" href="http://www.darkridge.com/~jpr5/2013/02/14/why-we-do-what-we-do/">&#9875; Permalink</a></p>]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[A Real Ruby 1.8.7 → 1.9.3 Migration]]></title>
<link href="http://www.darkridge.com/~jpr5/2012/10/03/ruby-1.8.7-1.9.3-migration/"/>
<updated>2012-10-03T23:47:00-07:00</updated>
<id>http://www.darkridge.com/~jpr5/2012/10/03/ruby-1.8.7-1.9.3-migration</id>

      <content type="html"><![CDATA[<p>Recently it came to pass that my company needed to update its Platform Framework
and Applications, which was based on Ruby 1.8.7 (<a href="http://www.rubyenterpriseedition.com/">Ruby Enterprise Edition</a>).
New features required new gems which required newer versions of existing gems
which either broke existing conventions/APIs or were no longer supported on
1.8.7.  Then we learned REE had reached <a href="http://blog.phusion.nl/2012/02/21/ruby-enterprise-edition-1-8-7-2012-02-released-end-of-life-imminent/">End of Life</a>.  Nuts!</p>

<p>I&#8217;ll save a deeper analysis of the why for a separate post.  The short of it is
that we were already faced with a full regression test impact to get the changes
we needed, so it made sense to invest a few more weeks and bite the whole
bullet: hop onto the next <a href="https://wiki.ubuntu.com/LTS">Ubuntu LTS</a> release in production, upgrade all of
the (mature) gems, and upgrade the VM to the now-stable <a href="http://www.ruby-lang.org/en/news/2012/04/20/ruby-1-9-3-p194-is-released/">Ruby 1.9.3</a>.  This
was a Big Deal.</p>

<p>How to go about this, then?  Well, the <a href="http://svn.ruby-lang.org/repos/ruby/tags/v1_9_3_194/ChangeLog">ChangeLog</a> could be enlightening, and
of course there&#8217;s tons of blog posts about 1.9.3 itself.  But when it came to
actual conversions, the wisdom was surprisingly scarce.  My sense is that the
Ruby community is still relatively small overall, only a small subset of the
community has ever (successfully) built stable, mature, long-lived platforms on
the language, and maybe only a tiny fraction of <em>them</em> have ever had to work
through the EOL of their particular VM and get on a new version.</p>

<p>So, here&#8217;s the skinny on converting a large, mature Ruby codebase from 1.8.7
(REE) to 1.9.3.  While it&#8217;s not exhaustive, it will be representative of the
sort of things to look out for.  To be fair, a number of the problems
encountered were due to &#8220;liberties&#8221; we had taken with the syntax &#8211; a core value
of Ruby, and a big reason why so many love it.  But that&#8217;s harsh criticism that
misses the practical reality of a team of developers working hard and fast
through the evolution of a large codebase over an extended period of time.</p>

<p>This post is by no means an indictment of 1.9.3.  No, 1.9.3 is Better, and in
many cases also Faster.  But it ain&#8217;t perfect, and you&#8217;ll do better if you have
some idea of what to expect.</p>

<h3>Syntax</h3>

<p>First up, syntax.  While some of this was expected, some things were pretty
subtle (e.g. array splat behavior).</p>

<ul>
<li><code>rescue</code> gains higher precedence than <code>not</code></li>
</ul>


<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">foo</span> <span class="ow">and</span> <span class="ow">not</span> <span class="p">(</span><span class="kp">nil</span><span class="o">.</span><span class="n">nonexistant_method</span> <span class="k">rescue</span> <span class="kp">nil</span><span class="p">)</span> <span class="c1"># =&gt; raises exception</span>
</span><span class='line'><span class="n">foo</span> <span class="ow">and</span> <span class="o">!</span><span class="p">(</span><span class="kp">nil</span><span class="o">.</span><span class="n">nonexistant_method</span> <span class="k">rescue</span> <span class="kp">nil</span><span class="p">)</span>    <span class="c1"># =&gt; works</span>
</span></code></pre></td></tr></table></div></figure>


<ul>
<li>parenthesis generally required where precedence gets confused</li>
</ul>


<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">raise</span> <span class="no">Foo</span><span class="p">,</span> <span class="s2">&quot;bar&quot;</span>  <span class="k">unless</span> <span class="n">blort</span> <span class="c1"># =&gt; works on 1.8.7</span>
</span><span class='line'><span class="k">raise</span> <span class="no">Foo</span><span class="p">,</span> <span class="s2">&quot;bar&quot;</span>  <span class="k">unless</span> <span class="n">blort</span> <span class="c1"># =&gt; raises exception on 1.9.3</span>
</span><span class='line'><span class="k">raise</span><span class="p">(</span><span class="no">Foo</span><span class="p">,</span> <span class="s2">&quot;bar&quot;</span><span class="p">)</span> <span class="k">unless</span> <span class="n">blort</span> <span class="c1"># =&gt; works on 1.9.3</span>
</span></code></pre></td></tr></table></div></figure>


<ul>
<li>can&#8217;t use multi-value assignment as conditional anymore</li>
</ul>


<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">if</span> <span class="n">foo</span> <span class="ow">and</span> <span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="c1"># =&gt; raises exception</span>
</span></code></pre></td></tr></table></div></figure>


<ul>
<li>can&#8217;t use instance variables as formal block params</li>
</ul>


<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">foo</span><span class="o">.</span><span class="n">inject</span><span class="p">({})</span> <span class="p">{</span> <span class="o">|</span><span class="vi">@h</span><span class="p">,</span> <span class="n">v</span><span class="o">|</span> <span class="o">.</span><span class="n">.</span> <span class="p">}</span> <span class="c1"># =&gt; raises exception</span>
</span></code></pre></td></tr></table></div></figure>


<ul>
<li>splat Array/List deref remains Array regardless of # elements</li>
</ul>


<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span> <span class="n">bar</span> <span class="o">=</span> <span class="o">*</span><span class="n">args</span> <span class="k">end</span>
</span><span class='line'><span class="n">a</span> <span class="o">=</span> <span class="n">foo</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="n">a</span> <span class="c1"># =&gt; 1     (1.8.7)</span>
</span><span class='line'><span class="n">a</span> <span class="o">=</span> <span class="n">foo</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="n">a</span> <span class="c1"># =&gt; [1]   (1.9.3)</span>
</span></code></pre></td></tr></table></div></figure>


<ul>
<li>splat behavior exception: when assigning to list of lvalues</li>
</ul>


<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span> <span class="n">bar</span> <span class="o">=</span> <span class="o">*</span><span class="n">args</span> <span class="k">end</span>
</span><span class='line'><span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">foo</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="n">a</span> <span class="c1"># =&gt; 1     (1.8.7)</span>
</span><span class='line'><span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">foo</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="n">a</span> <span class="c1"># =&gt; 1     (1.9.3)</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Encoding</h3>

<p>Anyone who has worked with non-ASCII character sets in 1.8.7 will know of Ruby&#8217;s
shortcomings when it comes to other encodings and codepages.  1.9 improves the
situation significantly, and actually deprecates the <code>iconv</code> library.</p>

<ul>
<li>embedded UTF-8 chars/strings require explicit file-wide encoding

<ul>
<li>insert <code># encoding: UTF-8</code> at top of each affected file</li>
</ul>
</li>
</ul>


<!-- -->


<ul>
<li>manual &#8220;guards&#8221; against invalid byte sequences require forced binary encoding</li>
</ul>


<p>We had several cases using a <code>Regex</code> to check a <code>String</code> for invalid byte
sequences, as in user-provided inputs or validating email addresses.  It
simplifies to this:</p>

<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">foo</span> <span class="o">=</span> <span class="s2">&quot;</span><span class="se">\xff</span><span class="s2">&quot;</span>   <span class="c1"># =&gt; &quot;\xFF&quot;</span>
</span><span class='line'><span class="n">bar</span> <span class="o">=</span> <span class="sr">/</span><span class="si">#{</span><span class="n">foo</span><span class="si">}</span><span class="sr">/</span> <span class="c1"># =&gt; ArgumentError: invalid multibyte character</span>
</span><span class='line'>
</span><span class='line'><span class="n">foo</span><span class="o">.</span><span class="n">force_encoding</span><span class="p">(</span><span class="s1">&#39;binary&#39;</span><span class="p">)</span>
</span><span class='line'><span class="n">bar</span> <span class="o">=</span> <span class="sr">/</span><span class="si">#{</span><span class="n">foo</span><span class="si">}</span><span class="sr">/</span>               <span class="c1"># =&gt; /\xFF/</span>
</span></code></pre></td></tr></table></div></figure>


<p><em>Note</em>: You&#8217;ll get a <code>SyntaxError</code> exception instead if you run this in <code>irb</code>.
 <!-- --></p>

<ul>
<li><code>$KCODE</code> is gone; <code>ruby -K</code> is not its equivalent - <code>__ENCODING__</code> is

<ul>
<li><code>__ENCODING__</code> only set by shell locale encoding (*nix) or codepage (Win32)</li>
</ul>
</li>
</ul>


<figure class='code'><figcaption><span>*nix</span></figcaption><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">LC_CTYPE</span><span class="o">=</span>en_US.iso8859-1 ruby -e <span class="s2">&quot;puts __ENCODING__&quot;</span> <span class="c"># =&gt; &quot;ISO-8859-1&quot;</span>
</span><span class='line'><span class="nv">LC_CTYPE</span><span class="o">=</span>en_US.utf-8     ruby -e <span class="s2">&quot;puts __ENCODING__&quot;</span> <span class="c"># =&gt; &quot;UTF-8&quot;</span>
</span></code></pre></td></tr></table></div></figure>




<figure class='code'><figcaption><span>Win32</span></figcaption><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>ruby -e <span class="s2">&quot;puts __ENCODING__&quot;</span> <span class="c"># =&gt; &quot;IBM437&quot;</span>
</span><span class='line'>chcp 60001
</span><span class='line'>ruby -e <span class="s2">&quot;puts __ENCODING__&quot;</span> <span class="c"># =&gt; &quot;UTF-8&quot;</span>
</span></code></pre></td></tr></table></div></figure>


<p><em>Beware</em>: Win32 Ruby gets unstable quickly when default codepage is UTF-8 (aka crash)</p>

<!-- -->


<ul>
<li>(Win32) <code>win32console</code> completely breaks <code>$stdout</code> encoding

<ul>
<li>given the right encoding, UTF-8 chars will display to <code>$stdout</code> correctly</li>
<li>after loading <code>win32console</code>, UTF-8 is garbled again</li>
</ul>
</li>
</ul>


<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="nb">puts</span> <span class="s2">&quot;</span><span class="si">#{</span><span class="n">foo</span> <span class="o">=</span> <span class="no">File</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="s1">&#39;foo.txt&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">chomp</span><span class="si">}</span><span class="s2"> -&gt; </span><span class="si">#{</span><span class="n">foo</span><span class="o">.</span><span class="n">force_encoding</span><span class="p">(</span><span class="s1">&#39;utf-8&#39;</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span>
</span><span class='line'><span class="nb">require</span> <span class="s1">&#39;win32console&#39;</span>
</span><span class='line'><span class="nb">puts</span> <span class="s2">&quot;</span><span class="si">#{</span><span class="n">foo</span> <span class="o">=</span> <span class="no">File</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="s1">&#39;foo.txt&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">chomp</span><span class="si">}</span><span class="s2"> -&gt; </span><span class="si">#{</span><span class="n">foo</span><span class="o">.</span><span class="n">force_encoding</span><span class="p">(</span><span class="s1">&#39;utf-8&#39;</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span>
</span><span class='line'><span class="c1"># FIXME: update with better example</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Threading (Win32)</h3>

<ul>
<li><code>Thread</code> is no longer Green - it&#8217;s now a native thread</li>
</ul>


<p>We wrap Microsoft Word with an asynchronous control channel using OLE and
Eventmachine-driven AMQP, primarily for high fidelity split/combine &amp;
track-changes operations on Word documents.</p>

<p>Each AMQP message spawns off in a new <code>Thread</code>.  With green threads in 1.8.7, we
were effectively isolated from the vaguaries of various COM threading models
underlying OLE.  Under 1.9.3 however, each <code>Thread</code> is native and thus needs its
own OLE object handle, otherwise you get a <code>WIN32OLERuntimeError</code> exception with
the following message:</p>

<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='plain'><span class='line'>The application called an interface that was marshalled for a different thread</span></code></pre></td></tr></table></div></figure>


<p>We found a <a href="https://groups.google.com/forum/?fromgroups=#!topic/rubyinstaller/zaa_haj2KYA">good discussion</a> on the topic and a potential solution involving
calling <code>CoInitialize</code>/<code>CoUninitialize</code> per-<code>Thread</code>, however it didn&#8217;t solve
our problem.</p>

<p>Instead, we simply memoized the OLE object handle in <code>Thread</code>-local storage:</p>

<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">def</span> <span class="nf">msword</span>
</span><span class='line'>    <span class="no">Thread</span><span class="o">.</span><span class="n">current</span><span class="o">[</span><span class="ss">:msword</span><span class="o">]</span> <span class="o">||=</span> <span class="no">WIN32OLE</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="s1">&#39;word.application&#39;</span><span class="p">)</span> <span class="k">rescue</span> <span class="no">WIN32OLE</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s1">&#39;word.application&#39;</span><span class="p">)</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<h3><code>Kernel</code></h3>

<ul>
<li><code>Kernel</code> method enumerators produce an <code>Array</code> of <code>Symbol</code>, not <code>String</code></li>
</ul>


<h3><code>Module</code></h3>

<ul>
<li><code>Module.constants</code> produces an <code>Array</code> of <code>Symbol</code>, not <code>String</code></li>
</ul>


<h3><code>Enumerable</code></h3>

<ul>
<li><code>Enumerable.map</code> behavior changes

<ul>
<li>implications on a loop that expects the yielded value to work like a <code>String</code> (e.g. <code>value#[]</code>)</li>
</ul>
</li>
</ul>


<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="p">(</span><span class="s2">&quot;a&quot;</span><span class="o">.</span><span class="n">.</span><span class="s2">&quot;c&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">map</span>      <span class="c1"># =&gt; [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;]             (1.8.7)</span>
</span><span class='line'><span class="p">(</span><span class="s2">&quot;a&quot;</span><span class="o">.</span><span class="n">.</span><span class="s2">&quot;c&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">map</span>      <span class="c1"># =&gt; #&lt;Enumerator: &quot;a&quot;..&quot;c&quot;:map&gt; (1.9.3)</span>
</span></code></pre></td></tr></table></div></figure>


<h3><code>Exception</code></h3>

<ul>
<li><code>Exception#message</code> is now immutable</li>
</ul>


<p>Many of our Platform Framework libraries wrap various vendor-specific
<code>Exception</code> classes with our own, to keep our library consumers within their own
domain and to guard against coupling consumer unit tests to indirect
vendor-specific behaviors.  In some cases we add our own prefix/postfix to
existing <code>#message</code> strings.  Can&#8217;t do that in 1.9.3:</p>

<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="no">Exception</span><span class="o">.</span><span class="n">new</span><span class="o">.</span><span class="n">message</span> <span class="o">&lt;&lt;</span> <span class="s2">&quot;foo&quot;</span> <span class="c1"># =&gt; RuntimeError: can&#39;t modify frozen String</span>
</span></code></pre></td></tr></table></div></figure>




<!-- -->


<ul>
<li><code>Exception#message</code> now forces <code>#to_s</code> on value</li>
</ul>


<p>We had some cases where we wrap vendor exceptions with our own, and tunneled the
original <code>Exception</code> in <code>#message</code>.  That won&#8217;t work by default in 1.9.3, so we
added this:</p>

<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">class</span> <span class="nc">Exception</span>
</span><span class='line'>    <span class="kp">attr_reader</span> <span class="ss">:message</span>
</span><span class='line'>    <span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="o">*</span><span class="n">data</span><span class="p">)</span>
</span><span class='line'>        <span class="vi">@message</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">first</span>
</span><span class='line'>        <span class="k">super</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>




<!-- -->


<h3><code>Hash</code></h3>

<ul>
<li><code>Hash</code> now natively respects insert order

<ul>
<li>e.g. beware web tests that compare stringified JSON results</li>
</ul>
</li>
</ul>


<!-- -->


<ul>
<li>inserting into <code>Hash</code> while enumerating it raises an exception</li>
</ul>


<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">foo</span> <span class="o">=</span> <span class="p">{</span> <span class="ss">:a</span> <span class="o">=&gt;</span> <span class="ss">:b</span> <span class="p">}</span>
</span><span class='line'><span class="n">foo</span><span class="o">.</span><span class="n">each</span> <span class="p">{</span> <span class="o">|</span><span class="n">h</span><span class="o">|</span> <span class="n">foo</span><span class="o">[</span><span class="ss">:c</span><span class="o">]</span> <span class="o">=</span> <span class="ss">:d</span> <span class="p">}</span>
</span><span class='line'>  <span class="c1"># =&gt; RuntimeError: can&#39;t add a new key into hash during iteration</span>
</span></code></pre></td></tr></table></div></figure>




<!-- -->


<ul>
<li><code>Hash#merge</code> doesn&#8217;t use <code>Hash#[]=</code> anymore

<ul>
<li>e.g. stringify&#8217;ing things upon assignment doesn&#8217;t work with <code>Hash#merge</code></li>
</ul>
</li>
</ul>


<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">class</span> <span class="nc">A</span> <span class="o">&lt;</span> <span class="no">Hash</span><span class="p">;</span> <span class="k">def</span> <span class="nf">[]=</span><span class="p">(</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span> <span class="k">super</span><span class="p">(</span><span class="n">k</span><span class="o">.</span><span class="n">to_s</span><span class="p">,</span> <span class="n">v</span><span class="o">.</span><span class="n">to_s</span><span class="p">)</span> <span class="k">end</span> <span class="k">end</span>
</span><span class='line'><span class="n">foo</span> <span class="o">=</span> <span class="n">A</span><span class="o">.</span><span class="n">new</span>
</span><span class='line'><span class="n">foo</span><span class="o">[</span><span class="ss">:a</span><span class="o">]</span> <span class="o">=</span> <span class="ss">:b</span>        <span class="c1"># =&gt; {&quot;a&quot;=&gt;&quot;b&quot;}</span>
</span><span class='line'><span class="n">foo</span><span class="o">.</span><span class="n">merge</span><span class="p">(</span><span class="ss">:c</span> <span class="o">=&gt;</span> <span class="ss">:d</span><span class="p">)</span> <span class="c1"># =&gt; {&quot;a&quot;=&gt;&quot;b&quot;, :c =&gt; :d}</span>
</span></code></pre></td></tr></table></div></figure>




<!-- -->


<ul>
<li><code>Hash</code> enumerable methods now return <code>Enumerable</code></li>
</ul>


<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="no">Hash</span><span class="o">.</span><span class="n">new</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">class</span>         <span class="c1"># =&gt; Array       (1.8.7)</span>
</span><span class='line'><span class="no">Hash</span><span class="o">.</span><span class="n">new</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">flatten</span><span class="o">.</span><span class="n">uniq</span>  <span class="c1"># =&gt; works       (1.8.7)</span>
</span><span class='line'><span class="no">Hash</span><span class="o">.</span><span class="n">new</span><span class="o">.</span><span class="n">map</span><span class="o">.</span><span class="n">class</span>         <span class="c1"># =&gt; Enumerable  (1.9.3)</span>
</span><span class='line'><span class="no">Hash</span><span class="o">.</span><span class="n">new</span><span class="o">.</span><span class="n">to_a</span><span class="o">.</span><span class="n">flatten</span><span class="o">.</span><span class="n">uniq</span> <span class="c1"># =&gt; works       (1.9.3)</span>
</span></code></pre></td></tr></table></div></figure>




<!-- -->


<h3><code>Symbol</code></h3>

<ul>
<li><code>Symbol#match</code> now exists but doesn&#8217;t work like <code>String#match</code></li>
</ul>


<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="s2">&quot;foo&quot;</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="sr">/foo/</span><span class="p">)</span> <span class="c1"># =&gt; #&lt;MatchData &quot;foo&quot;&gt;</span>
</span><span class='line'><span class="ss">:foo</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="sr">/foo/</span><span class="p">)</span>  <span class="c1"># =&gt; 0</span>
</span></code></pre></td></tr></table></div></figure>




<!-- -->


<h3><code>String</code></h3>

<ul>
<li><code>String</code> no longer directly enumerable, so <code>#map</code>, <code>#grep</code> etc is gone

<ul>
<li>but you do get <code>String#each_{byte,char,codepoint,line}</code></li>
</ul>
</li>
</ul>


<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="s2">&quot;foo&quot;</span><span class="o">.</span><span class="n">map</span> <span class="c1"># =&gt; [&quot;foo&quot;]                                              (1.8.7)</span>
</span><span class='line'><span class="s2">&quot;foo&quot;</span><span class="o">.</span><span class="n">map</span> <span class="c1"># =&gt; NoMethodError: undefined method `map&#39; for &quot;&quot;:String  (1.9.3)</span>
</span></code></pre></td></tr></table></div></figure>




<!-- -->


<ul>
<li><code>String#[Symbol]</code> doesn&#8217;t (silently) work anymore</li>
</ul>


<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="s2">&quot;foo&quot;</span><span class="o">[</span><span class="ss">:a</span><span class="o">]</span> <span class="c1"># =&gt; nil                                           (1.8.7)</span>
</span><span class='line'><span class="s2">&quot;foo&quot;</span><span class="o">[</span><span class="ss">:a</span><span class="o">]</span> <span class="c1"># =&gt; TypeError: can&#39;t convert Symbol into Integer  (1.9.3)</span>
</span></code></pre></td></tr></table></div></figure>




<!-- -->


<ul>
<li><code>String#[Fixnum]</code> returns char-as-string, not ordinal</li>
</ul>


<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="s2">&quot;foo&quot;</span><span class="o">[</span><span class="mi">1</span><span class="o">]</span> <span class="c1"># =&gt; 111  (1.8.7)</span>
</span><span class='line'><span class="s2">&quot;foo&quot;</span><span class="o">[</span><span class="mi">1</span><span class="o">]</span> <span class="c1"># =&gt; &quot;o&quot;  (1.9.3)</span>
</span></code></pre></td></tr></table></div></figure>




<!-- -->


<ul>
<li><code>String#include?</code> no longer takes a <code>Fixnum</code> (as ordinal)</li>
</ul>


<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="s2">&quot;123&quot;</span><span class="o">.</span><span class="n">include?</span><span class="p">(</span><span class="s2">&quot;2&quot;</span><span class="p">)</span> <span class="c1"># =&gt; true</span>
</span><span class='line'><span class="s2">&quot;123&quot;</span><span class="o">.</span><span class="n">include?</span><span class="p">(</span><span class="mi">50</span><span class="p">)</span>  <span class="c1"># =&gt; true                                         (1.8.7)</span>
</span><span class='line'><span class="s2">&quot;123&quot;</span><span class="o">.</span><span class="n">include?</span><span class="p">(</span><span class="mi">50</span><span class="p">)</span>  <span class="c1"># =&gt; TypeError: can&#39;t convert Fixnum into String  (1.9.3)</span>
</span></code></pre></td></tr></table></div></figure>




<!-- -->


<ul>
<li><code>String#strip</code> doesn&#8217;t work on non-ASCII whitespace</li>
</ul>


<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="s2">&quot; </span><span class="se">\xc2\xa0</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">strip</span>                    <span class="c1"># =&gt; &quot;\302\240&quot; (1.8.7)</span>
</span><span class='line'><span class="s2">&quot; </span><span class="se">\xc2\xa0</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">strip</span>                    <span class="c1"># =&gt; &quot; &quot;        (1.9.3)</span>
</span></code></pre></td></tr></table></div></figure>


<p>But using the POSIX character class does:</p>

<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="s2">&quot; </span><span class="se">\xc2\xa0</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">gsub</span><span class="p">(</span><span class="sr">/[[:space:]]/</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)</span>  <span class="c1"># =&gt; &quot;\302&quot;  (1.8.7)</span>
</span><span class='line'><span class="s2">&quot; </span><span class="se">\xc2\xa0</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">gsub</span><span class="p">(</span><span class="sr">/[[:space:]]/</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)</span>  <span class="c1"># =&gt; &quot;&quot;      (1.9.3)</span>
</span></code></pre></td></tr></table></div></figure>




<!-- -->


<h3>Binding</h3>

<ul>
<li>getting an object&#8217;s <code>binding</code> requires <code>#instance_eval</code> instead of <code>#send</code></li>
</ul>


<p>A good example is the pattern of using an <code>OpenStruct</code> initialized with a <code>Hash</code>
(which provides method accessors for keys) as a Context object for template
interpolation systems like <code>Erubis</code>.</p>

<p>This used to work in 1.8.7:</p>

<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">template</span> <span class="o">=</span> <span class="no">ERB</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s2">&quot;foo.erb&quot;</span><span class="p">)</span>
</span><span class='line'><span class="n">context</span> <span class="o">=</span> <span class="no">OpenStruct</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">some_object_with_methods</span><span class="p">)</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="ss">:binding</span><span class="p">)</span>
</span><span class='line'><span class="n">output</span> <span class="o">=</span> <span class="n">template</span><span class="o">.</span><span class="n">result</span><span class="p">(</span><span class="n">context</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>This works in 1.9.3 <em>and</em> 1.8.7:</p>

<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">template</span> <span class="o">=</span> <span class="no">ERB</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s2">&quot;foo.erb&quot;</span><span class="p">)</span>
</span><span class='line'><span class="n">context</span> <span class="o">=</span> <span class="no">OpenStruct</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">some_object_with_methods</span><span class="p">)</span><span class="o">.</span><span class="n">instance_eval</span> <span class="p">{</span> <span class="nb">binding</span><span class="p">()</span> <span class="p">}</span>
</span><span class='line'><span class="n">output</span> <span class="o">=</span> <span class="n">template</span><span class="o">.</span><span class="n">result</span><span class="p">(</span><span class="n">context</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<h3><code>Fixnum</code></h3>

<ul>
<li><code>Fixnum#to_sym</code> no longer (silently) works</li>
</ul>


<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="mi">1</span><span class="o">.</span><span class="n">to_sym</span> <span class="c1"># =&gt; nil                                                    (1.8.7)</span>
</span><span class='line'><span class="mi">1</span><span class="o">.</span><span class="n">to_sym</span> <span class="c1"># =&gt; NoMethodError: undefined method `to_sym&#39; for 1:Fixnum  (1.9.3)</span>
</span></code></pre></td></tr></table></div></figure>




<!-- -->


<h3><code>Float</code></h3>

<ul>
<li>fraction-less <code>Float</code> becomes a <code>Fixnum</code> through <code>#to_s</code> (precision lost)

<ul>
<li>e.g. cucumber test with a table containing a <code>Float</code> like <code>10.0</code></li>
</ul>
</li>
</ul>


<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="nb">Float</span><span class="p">(</span><span class="mi">0</span><span class="o">.</span><span class="mi">0</span><span class="p">)</span><span class="o">.</span><span class="n">to_s</span> <span class="c1"># =&gt; &quot;0.0&quot;  (1.8.7)</span>
</span><span class='line'><span class="nb">Float</span><span class="p">(</span><span class="mi">0</span><span class="o">.</span><span class="mi">0</span><span class="p">)</span><span class="o">.</span><span class="n">to_s</span> <span class="c1"># =&gt; &quot;0&quot;    (1.9.3)</span>
</span></code></pre></td></tr></table></div></figure>




<!-- -->


<h3><code>BigDecimal</code></h3>

<p><code>BigDecimal</code> problems were among the most difficult in the conversion.  There
are differences in behavior between VM versions <em>and</em> amongst <code>BigDecimal</code>
representations within the 1.9.3 VM itself.</p>

<ul>
<li>BD init by <code>String</code> skips precision altogether</li>
</ul>


<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="nb">Float</span><span class="p">(</span><span class="mi">80</span><span class="o">.</span><span class="mi">784</span><span class="p">)</span><span class="o">.</span><span class="n">to_d</span><span class="o">.</span><span class="n">to_s</span><span class="p">(</span><span class="s1">&#39;F&#39;</span><span class="p">)</span>             <span class="c1"># =&gt; &quot;80.78400000000001&quot;</span>
</span><span class='line'><span class="no">BigDecimal</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s2">&quot;80.784&quot;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">80</span><span class="o">.</span><span class="mi">784</span><span class="o">.</span><span class="n">to_d</span>  <span class="c1"># =&gt; false</span>
</span></code></pre></td></tr></table></div></figure>




<!-- -->


<ul>
<li>BD compared to <code>Float</code> makes a BD implicitly from <code>Float</code></li>
</ul>


<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="mi">80</span><span class="o">.</span><span class="mi">784</span><span class="o">.</span><span class="n">to_d</span> <span class="o">==</span> <span class="mi">80</span><span class="o">.</span><span class="mi">784</span>              <span class="c1"># =&gt; true   (but it shouldn&#39;t!)</span>
</span><span class='line'><span class="no">BigDecimal</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s2">&quot;80.784&quot;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">80</span><span class="o">.</span><span class="mi">784</span> <span class="c1"># =&gt; false  (but you might think it should!)</span>
</span></code></pre></td></tr></table></div></figure>




<!-- -->


<ul>
<li>BD + <code>Float</code> makes a <code>Float</code></li>
</ul>


<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="no">BigDecimal</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s2">&quot;80.784&quot;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">80</span><span class="o">.</span><span class="mi">784</span>       <span class="c1"># =&gt; false  (OK we just learned that)</span>
</span><span class='line'><span class="no">BigDecimal</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s2">&quot;80.784&quot;</span><span class="p">)</span> <span class="o">+</span> <span class="mi">0</span><span class="o">.</span><span class="mi">0</span> <span class="o">==</span> <span class="mi">80</span><span class="o">.</span><span class="mi">784</span> <span class="c1"># =&gt; true   (ZOMGGGGG)</span>
</span></code></pre></td></tr></table></div></figure>




<!-- -->


<ul>
<li><code>Float#to_d</code> ignores class-level precision limit setting entirely</li>
</ul>


<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="no">BigDecimal</span><span class="o">.</span><span class="n">limit</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>  <span class="c1"># docs say this sets default precision for newly created BDs</span>
</span><span class='line'><span class="mi">80</span><span class="o">.</span><span class="mi">784</span><span class="o">.</span><span class="n">to_d</span>          <span class="c1"># =&gt; #&lt;BigDecimal:7fbe331c7e58,&#39;0.8078400000 000001E2&#39;,27(45)&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p><em>Note</em>: <code>Float#to_d</code> comes from the <code>bigdecimal</code> library.</p>

<!-- -->


<ul>
<li><code>Float#to_d</code> uses a different &#8220;default precision&#8221; than <code>BigDecimal.new</code></li>
</ul>


<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="no">BigDecimal</span><span class="o">.</span><span class="n">limit</span>                                    <span class="c1"># =&gt; 0</span>
</span><span class='line'><span class="no">BigDecimal</span><span class="p">(</span><span class="mi">80</span><span class="o">.</span><span class="mi">784</span><span class="p">,</span> <span class="no">BigDecimal</span><span class="o">.</span><span class="n">limit</span><span class="p">)</span><span class="o">.</span><span class="n">precs</span>          <span class="c1"># =&gt; [45, 54]</span>
</span><span class='line'><span class="mi">80</span><span class="o">.</span><span class="mi">784</span><span class="o">.</span><span class="n">to_d</span><span class="o">.</span><span class="n">precs</span>                                   <span class="c1"># =&gt; [27, 45]</span>
</span><span class='line'><span class="no">BigDecimal</span><span class="p">(</span><span class="mi">80</span><span class="o">.</span><span class="mi">784</span><span class="p">,</span> <span class="no">BigDecimal</span><span class="o">.</span><span class="n">limit</span><span class="p">)</span> <span class="o">==</span> <span class="mi">80</span><span class="o">.</span><span class="mi">784</span><span class="o">.</span><span class="n">to_d</span> <span class="c1"># =&gt; false</span>
</span></code></pre></td></tr></table></div></figure>




<!-- -->


<ul>
<li>BD invocation differs depending on init param type</li>
</ul>


<p>This makes writing generalized code for handling a <code>BigDecimal</code> overly
complicated.</p>

<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="no">BigDecimal</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s2">&quot;80.784&quot;</span><span class="p">)</span> <span class="c1"># =&gt; 80.784</span>
</span><span class='line'><span class="no">BigDecimal</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="mi">80</span><span class="o">.</span><span class="mi">784</span><span class="p">)</span>   <span class="c1"># =&gt; ArgumentError: can&#39;t omit precision for a Rational.</span>
</span></code></pre></td></tr></table></div></figure>




<!-- -->


<h4>A Practical Look at the Problem</h4>

<p>The <code>Float</code> vs. <code>BigDecimal</code> issue is about precision and &#8220;true representations&#8221;
of Rational numbers vs. representations that are incorrectly assumed to be
precise (like <code>Float</code>).  The story almost always ends the same way: mixing
differing-precision numbers in math calculations is just a Bad Idea.  Mixing
<code>BigDecimal</code> and <code>Float</code> certainly qualifies as this.</p>

<p>The problem in 1.9.3 is that different invocations of <code>BigDecimal</code> <em>also</em>
qualify as differing-precision numbers.  A <code>String</code>-initialized <code>BigDecimal</code>
will skip any precision.  Convenience methods like <code>#to_d</code> will produce a
<code>BigDecimal</code> using a different &#8220;default precision&#8221; than the normal <code>#new</code>.
<code>#to_d</code> doesn&#8217;t even respect <code>BigDecimal.limit</code>.</p>

<p>Sure there are ways to compare the precision of a <code>BigDecimal</code>, and it is
possible to write extra code to ensure same-precision computation and
comparison.  But on a practical level that&#8217;s terribly obnoxious and simply not
going to happen.  Your average application developer just doesn&#8217;t care, and
shouldn&#8217;t.  It&#8217;s hard enough to avoid mixing <code>Float</code> and <code>BigDecimal</code>, and
getting that right should be enough.  Almost.</p>

<h4>A Practical Solution</h4>

<p>After adhering to the &#8220;don&#8217;t mix fractional types&#8221; rule, we were left with a
bunch of broken tests around an ORM property type designed for persisting a
<code>BigDecimal</code>.  In the end, those all resolved to this simple, new behavior in
1.9.3:</p>

<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="no">BigDecimal</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s2">&quot;80.784&quot;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">80</span><span class="o">.</span><span class="mi">784</span>  <span class="c1"># =&gt; false</span>
</span></code></pre></td></tr></table></div></figure>


<p>So a <code>BigDecimal</code> is being compared against a <code>Float</code> &#8211; big surprise that a
mixed precision comparison causes problems!  But practically speaking, it&#8217;s
simply unrealistic for it to happen any other way: no one&#8217;s going to adjust
every line of their code and tests to detect+match precision, no one&#8217;s going to
update fixture loaders to know about and adjust to ORM-specific representations
of precision/scale-limited rational numbers, no one will investigate+adjust test
harnesses like Rspec and Cucumber/Gherkin to understand when a rational should
be a <code>Float</code> vs. a <code>BigDecimal</code> and at what precision.  Realistically, fuck all
of that.</p>

<p>Instead, we just changed the implicit type conversion when comparing against a
<code>Float</code> to cast to a <code>String</code> first:</p>

<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">class</span> <span class="nc">BigDecimal</span>
</span><span class='line'>    <span class="k">def</span> <span class="nf">==</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
</span><span class='line'>        <span class="n">other</span> <span class="o">=</span> <span class="no">BigDecimal</span><span class="p">(</span><span class="n">other</span><span class="o">.</span><span class="n">to_s</span><span class="p">)</span> <span class="k">if</span> <span class="n">other</span><span class="o">.</span><span class="n">kind_of?</span><span class="p">(</span><span class="nb">Float</span><span class="p">)</span>
</span><span class='line'>        <span class="k">return</span> <span class="k">super</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>Then the test cases start working again, without having hacked any
representation&#8217;s real scale/precision:</p>

<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="no">BigDecimal</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s2">&quot;80.784&quot;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">80</span><span class="o">.</span><span class="mi">784</span>  <span class="c1"># =&gt; true</span>
</span></code></pre></td></tr></table></div></figure>


<p>And just like that, the old behavior.  Awesome.</p>

<p>FYI we used <code>80.784</code> because it was a (calculated) value in some tests that
triggered the BD-related problems.  There&#8217;s nothing else special about the
value.</p>

<h3>Closures</h3>

<ul>
<li><code>lambda</code> rules about arity have changed</li>
</ul>


<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="nb">lambda</span><span class="p">{}</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="nb">self</span><span class="p">)</span> <span class="c1"># =&gt; nil                                                 (1.8.7)</span>
</span><span class='line'><span class="nb">lambda</span><span class="p">{}</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="nb">self</span><span class="p">)</span> <span class="c1"># =&gt; ArgumentError: wrong number of arguments (1 for 0)  (1.9.3)</span>
</span></code></pre></td></tr></table></div></figure>


<p>This manifested as a result of an old rspec gem (1.2.9) that wasn&#8217;t getting
upgraded with the mix.  Test <code>it</code> declaratives without closures would raise a
special <code>NotImplementedYetError</code> exception, automatically marking them as
pending.  It did so using a <code>lambda</code>, which it later called with an argument &#8211;
which doesn&#8217;t work anymore in 1.9.3.  Swapping it to <code>proc</code> with a monkey patch
solved that.</p>

<!-- -->


<ul>
<li>initializing a <code>proc</code> with a <code>proc</code> no longer catches return-from-inside-closure</li>
</ul>


<p>This was a hack originally invented to wrap our ORM&#8217;s transactional layer with
our own, in order to provide better commit/rollback semantics and deferred AMQP
message delivery (outside the transaction window).</p>

<p>In general, we try to avoid obfuscating our code paths with too much nesting by
early-exiting from subroutines whenever possible, usually by calling <code>return</code>.
And sometimes those subroutines end up being transaction closures.</p>

<p>From a pedantic POV that&#8217;s a <em>terrible</em> idea &#8211; closures aren&#8217;t methods, they
have slightly different semantics, blah blah blah.  Practically speaking, who
cares.  It should Just Work.  So we made it work.  And then it totally broke in
1.9.3.</p>

<p>It essentially resolved to this:</p>

<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">def</span> <span class="nf">orm_txn</span>
</span><span class='line'>    <span class="n">ret</span> <span class="o">=</span> <span class="k">yield</span>
</span><span class='line'><span class="k">ensure</span>
</span><span class='line'>    <span class="k">return</span> <span class="n">ret</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">transaction</span><span class="p">(</span><span class="o">&amp;</span><span class="n">block</span><span class="p">)</span>
</span><span class='line'>    <span class="n">orm_txn</span> <span class="p">{</span> <span class="nb">proc</span><span class="p">(</span><span class="o">&amp;</span><span class="n">block</span><span class="p">)</span><span class="o">.</span><span class="n">call</span> <span class="p">}</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="n">transaction</span> <span class="p">{</span> <span class="k">return</span> <span class="mi">1</span> <span class="p">}</span> <span class="c1"># =&gt; 1    (1.8.7)</span>
</span><span class='line'><span class="n">transaction</span> <span class="p">{</span> <span class="k">return</span> <span class="mi">1</span> <span class="p">}</span> <span class="c1"># =&gt; nil  (1.9.3)</span>
</span></code></pre></td></tr></table></div></figure>


<p>The idea of adhering to the Principal of Least Surprise around <code>return</code> from
closures wasn&#8217;t unique to us; Sinatra had the same concept too, just using a
different mechanism: unbound methods.</p>

<p>So we use that now, and the method works like a charm on both 1.8.7 and 1.9.3:</p>

<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">def</span> <span class="nf">orm_txn</span>
</span><span class='line'>    <span class="n">ret</span> <span class="o">=</span> <span class="k">yield</span>
</span><span class='line'><span class="k">ensure</span>
</span><span class='line'>    <span class="k">return</span> <span class="n">ret</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">transaction</span><span class="p">(</span><span class="o">&amp;</span><span class="n">block</span><span class="p">)</span>
</span><span class='line'>    <span class="n">orm_txn</span> <span class="p">{</span> <span class="no">Class</span><span class="o">.</span><span class="n">new</span><span class="o">.</span><span class="n">instance_eval</span> <span class="p">{</span> <span class="n">define_method</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span><span class="p">)</span> <span class="p">}</span><span class="o">.</span><span class="n">call</span> <span class="p">}</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="n">transaction</span> <span class="p">{</span> <span class="k">return</span> <span class="mi">1</span> <span class="p">}</span> <span class="c1"># =&gt; 1  (1.8.7)</span>
</span><span class='line'><span class="n">transaction</span> <span class="p">{</span> <span class="k">return</span> <span class="mi">1</span> <span class="p">}</span> <span class="c1"># =&gt; 1  (1.9.3)</span>
</span></code></pre></td></tr></table></div></figure>


<p>Hooray!</p>

<h3>Library / Gems</h3>

<ul>
<li><code>FasterCSV</code> renamed to <code>CSV</code> and included in the core Ruby distribution</li>
</ul>


<!-- -->


<ul>
<li><code>json</code> (v1.5.4) included in the core Ruby distribution

<ul>
<li>beware non-rubygems <code>$LOAD_PATH</code> manipulations &#8211; Ruby&#8217;s libs always come first</li>
</ul>
</li>
</ul>


<!-- -->


<ul>
<li><code>soap4r</code> no longer bundled in the core Ruby distribution

<ul>
<li>old <code>soap4r</code> gem is incompatible with 1.9 &#8211; <code>use soap4r-ruby1.9</code></li>
</ul>
</li>
</ul>


<!-- -->


<ul>
<li><code>sha1</code> library is gone

<ul>
<li>use <code>digest/sha1</code> instead</li>
</ul>
</li>
</ul>


<!-- -->


<ul>
<li><code>ruby-debug</code> gem et al. renamed to <code>debugger</code> gem et al.</li>
</ul>


<!-- -->


<ul>
<li><code>$ENV['CWD']</code> not in <code>$LOAD_PATH</code> by default anymore</li>
</ul>


<!-- -->


<ul>
<li>XML parsing is more strict

<ul>
<li>can&#8217;t embed dash-dash (&#8220;&#8211;&#8221;) inside XML comments</li>
</ul>
</li>
</ul>


<!-- -->


<ul>
<li>YAML parsing is more strict

<ul>
<li>bare regexes need to be quoted</li>
<li>bare regexes containing &#8220;escaped&#8221;-style character classes require single-quoting</li>
</ul>
</li>
</ul>


<!-- -->


<ul>
<li>YAML parsing also got a little more convenient

<ul>
<li><code>Time</code>/<code>DateTime</code>/<code>Date</code> values serialized as <code>String</code> are auto-converted to native type</li>
</ul>
</li>
</ul>


<!-- -->


<ul>
<li><code>Net::HTTP::Post.set_form_data</code> now uses <code>URI.encode_www_form</code></li>
</ul>


<p>This subtly broke signature calculation on our Oauth consumers vs. our provider.</p>

<p>Oauth consumers (<code>oauth</code> gem) use <code>Net::HTTP::Post</code> while Oauth providers
(<code>oauth-provider</code> gem) use <code>Rack::Request</code>, but param collection and
serialization for signature calculation was effectively equivalent in 1.8.7.</p>

<p>Now <code>Net::HTTP::Post</code> uses <code>URI.encode_www_form</code>, and <em>that</em> produces a
different result when given a param key with a nil value.  Thus signature
calculation on the consumer would differ from what the provider arrives at, and
request authentication would fail.</p>

<p>Our &#8220;fix&#8221; was to just guard against nil parameters before making requests.</p>

<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">params</span> <span class="o">=</span> <span class="p">{</span> <span class="ss">:foo</span> <span class="o">=&gt;</span> <span class="kp">nil</span> <span class="p">}</span>
</span><span class='line'><span class="n">post</span> <span class="o">=</span> <span class="no">Net</span><span class="o">::</span><span class="no">HTTP</span><span class="o">::</span><span class="no">Post</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s2">&quot;/&quot;</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="n">post</span><span class="o">.</span><span class="n">set_form_data</span><span class="p">(</span><span class="n">params</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="n">post</span><span class="o">.</span><span class="n">body</span> <span class="c1"># =&gt; &quot;foo=&quot;  (1.8.7)</span>
</span><span class='line'><span class="n">post</span><span class="o">.</span><span class="n">body</span> <span class="c1"># =&gt; &quot;foo&quot;   (1.9.3)</span>
</span></code></pre></td></tr></table></div></figure>




<!-- -->


<p>Evil!</p>

<ul>
<li><code>open-uri</code> is a rainbow-hating, puppy-murdering Nazi who wants to make your life harder</li>
</ul>


<p>If the <code>userinfo</code> portion of a <code>URI</code> is set, it raises an exception:</p>

<figure class='code'><div class='highlight'><table><td class='gutter'><pre class='line-numbers'><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'>    <span class="k">if</span> <span class="n">target</span><span class="o">.</span><span class="n">userinfo</span> <span class="o">&amp;&amp;</span> <span class="s2">&quot;1.9.0&quot;</span> <span class="o">&lt;=</span> <span class="no">RUBY_VERSION</span>
</span><span class='line'>      <span class="c1"># don&#39;t raise for 1.8 because compatibility.</span>
</span><span class='line'>      <span class="k">raise</span> <span class="no">ArgumentError</span><span class="p">,</span> <span class="s2">&quot;userinfo not supported.  [RFC3986]&quot;</span>
</span><span class='line'>    <span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>This turned out to be one of those tired, irritating <a href="http://www.ruby-forum.com/topic/95983">pedantic engineer
vs. practical utility arguments</a> where the pedant won.  Hooray for pedantic
idiots!</p>

<!-- -->


<h3>Conclusion</h3>

<p>Well, that&#8217;s all I got for now!  Check out <a href="http://www.getharvest.com/">Harvest</a>&#8217;s Ruby 1.9.3 upgrade
<a href="http://techtime.getharvest.com/blog/harvest-is-now-on-ruby-1-dot-9-3">blog post</a> for some additional pitfalls to watch out for.</p>
<p><a rel="bookmark" href="http://www.darkridge.com/~jpr5/2012/10/03/ruby-1.8.7-1.9.3-migration/">&#9875; Permalink</a></p>]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[5 Years Later, Why I don't blog much]]></title>
<link href="http://www.darkridge.com/~jpr5/2011/11/04/something-new/"/>
<updated>2011-11-04T22:13:00-07:00</updated>
<id>http://www.darkridge.com/~jpr5/2011/11/04/something-new</id>

      <content type="html"><![CDATA[<p>It&#8217;s been almost 5 years since the last update, and now I&#8217;ve decided it&#8217;s
finally time.  Time to update my website with a new look, time to participate in
the Public Think and make my contribution again.</p>

<p>For the record, I&#8217;ve resisted blogging anything <em>forever</em>, mainly because:</p>

<ul>
<li>Who has time?  (Not me. I spend my time applying myself to the things I love.)</li>
<li>Who can risk the exposure?  (Not me.  I&#8217;m a Professional with a Career.)</li>
<li>Who cares?  (Usually, not me.)</li>
</ul>


<p>I&#8217;m perpetually floored by how many people qualify against these criteria.
<em>Really</em>?  Don&#8217;t you have a day job?  Aren&#8217;t you any good at it?  (Practice
takes time, and you&#8217;re obviously not practicing.)  Do you love to do anything
<em>else</em> in your life <em>besides</em> narcissistically plaster your verbal diarrhea
bullshit all over the Web?  (You should probably go do that instead.)  Did you
somehow miss the time-honored wisdom of <em>not</em> making a total ass of yourself in
public, especially when the Internet will <em>never</em> forget it?  Don&#8217;t you have
<em>anything</em> to lose?  I mean, seriously!</p>

<p>Sure, LinkedIn is great - it&#8217;s about jobs, careers, <em>credibility</em>.  Facebook -
ok fine, it&#8217;s an interesting concept to have 10 times more relationships each a
1/100th the value of a normal friendship.  But garbage like Twitter?  They&#8217;re
<em>ruining</em> the Internet with noise - 140 chars isn&#8217;t enough space to express
anything truly meaningful.  In the CS domain, statistically, 140 chars looks
almost like the <em>definition</em> of uselessness.  Yeah sure people use it usefully,
but the signal to noise ratio is intergalactically, unforgiveably huge.</p>

<p>But, that doesn&#8217;t mean I shouldn&#8217;t keep trying.  So, down the rabbit hole we go.
Again.</p>
<p><a rel="bookmark" href="http://www.darkridge.com/~jpr5/2011/11/04/something-new/">&#9875; Permalink</a></p>]]></content>
    </entry>
  
</feed>
