<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Thinking Digitally &#187; Programming</title>
	<atom:link href="http://thinkingdigitally.com/category/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://thinkingdigitally.com</link>
	<description>programming for the fun of it</description>
	<lastBuildDate>Mon, 15 Aug 2011 02:01:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.5</generator>
		<item>
		<title>Book Review: The Book of Ruby</title>
		<link>http://thinkingdigitally.com/archive/book-review-the-book-of-ruby/</link>
		<comments>http://thinkingdigitally.com/archive/book-review-the-book-of-ruby/#comments</comments>
		<pubDate>Mon, 15 Aug 2011 02:01:37 +0000</pubDate>
		<dc:creator>Rob Olson</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[book review]]></category>

		<guid isPermaLink="false">http://thinkingdigitally.com/?p=223</guid>
		<description><![CDATA[Last month No Starch Press released their second Ruby book ever, The Book of Ruby by Huw Collingbourne. Their first was Ruby by Example, released four years ago in 2007! The Book of Ruby is an introductory book to the Ruby programming language. The book covers all of the standard programming language basics: strings, classes, [...]]]></description>
			<content:encoded><![CDATA[<p>Last month No Starch Press released their second Ruby book ever, <a href="http://nostarch.com/boruby.htm">The Book of Ruby</a> by Huw Collingbourne. Their first was Ruby by Example, released four years ago in 2007! The Book of Ruby is an introductory book to the Ruby programming language.</p>

<p>The book covers all of the standard programming language basics: strings, classes, arrays, loops, etc. Additionally there are three chapters on more advanced subjects in Ruby: Marshal, Threads, and Dynamic Programming. Ruby on Rails is also quickly introduced in a chapter at the end of the book.</p>

<p>Each chapter includes a Digging Deeper section at the end that goes into more detail, warns about corner cases, or introduces an advanced usage. As someone who already knows Ruby these were the most interesting to read. They are placed inside of their own section to let someone who is just trying to learn Ruby know that they can safely be skipped.</p>

<p>No Starch Press is the publisher behind several fun programming books like <a href="http://nostarch.com/lisp.htm">Land of Lisp</a>, <a href="http://nostarch.com/lyah.htm">Learn You a Haskell for Great Good</a>, and the iconic <a href="http://nostarch.com/catalog/manga">Manga guides</a>. When I picked up The Book of Ruby I wasn&#8217;t expecting to encounter the second coming of <a href="http://mislav.uniqpath.com/poignant-guide/">Why&#8217;s (Poignant) Guide to Ruby</a>, but that&#8217;s what I was hoping for. Unfortunately, The Book of Ruby does not share any characteristics with that fun intro to programming Ruby and instead reads like an average technical book&#8230; dryly. On the positive side, I did find the author&#8217;s writing to be clear and easy to follow.</p>

<p>The book contains many examples but they are as contrived as possible. I understand that examples should be as simple as possible so that the reader can easily follow along but there is also a need to make the examples do interesting things to make the book more engaging.</p>

<p>Further, Collingbourne does not make an attempt to explain how Ruby is actually used &#8220;in the wild&#8221;. This is something that another Ruby author, Russ Olsen, does really well. Ruby has a lot of features so it is important to understand how Ruby programmers actually use Ruby. For instance, even though class variables are available, Ruby programmers try to never use them. This is something I would have liked to know when learning Ruby. However, instead of sharing these tidbits of information from his many years of Ruby experience, Collingbourne stays neutral and presents all of the information without including his opinions.</p>

<p>The one opinion that Collingbourne did share, is that he does not believe code style conventions are very important. This is something I can respect, and actually envy. In my own programming, I consider the time I spend to reformat my code to make it &#8220;look pretty&#8221; to be a waste. However, I still do it because it drives me crazy not to. If I could flip a switch inside my brain that would cause me to not care about code style anymore I absolutely would.</p>

<p>Overall, I feel like if this had been the first Ruby book I had picked up I would not have fallen in love with Ruby like I did. I am disappointed with No Starch Press for not upholding their unique style. The Book of Ruby does not differentiate itself enough to recommend over the other Ruby titles that are out there.</p>
]]></content:encoded>
			<wfw:commentRss>http://thinkingdigitally.com/archive/book-review-the-book-of-ruby/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Capturing Output from PUTS in Ruby</title>
		<link>http://thinkingdigitally.com/archive/capturing-output-from-puts-in-ruby/</link>
		<comments>http://thinkingdigitally.com/archive/capturing-output-from-puts-in-ruby/#comments</comments>
		<pubDate>Tue, 10 Mar 2009 08:36:13 +0000</pubDate>
		<dc:creator>Rob Olson</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[mocha]]></category>
		<category><![CDATA[puts]]></category>
		<category><![CDATA[redirect output]]></category>
		<category><![CDATA[simplesem]]></category>
		<category><![CDATA[zentest]]></category>

		<guid isPermaLink="false">http://thinkingdigitally.com/archive/capturing-output-from-puts-in-ruby/</guid>
		<description><![CDATA[When writing unit tests for my simplesem interpreter, one test in particular was problematic. In simplesem, the set write instruction prints output to the screen. // place Hello World! on the 'write' buffer set write, &#34;Hello World!&#34; Internally, the interpreter is just passing the second parameter, &#8220;Hello World!&#8221;, to the puts method in Ruby. This [...]]]></description>
			<content:encoded><![CDATA[<p>When writing unit tests for my <a href="http://thinkingdigitally.com/archive/a-simplesem-interpreter/">simplesem interpreter</a>, one test in particular was problematic. In simplesem, the <code>set write</code> instruction prints output to the screen.</p>


<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">// place Hello World! on the 'write' buffer
set write, &quot;Hello World!&quot;</pre></div></div>


<p>Internally, the interpreter is just passing the second parameter, &#8220;Hello World!&#8221;, to the <code>puts</code> method in Ruby. This makes it difficult to use traditional test/unit assertions to check that the simplesem instruction is working.</p>

<p>I eventually found two solutions for this. The first, suggested by <a href="http://flouri.sh/">David Stevenson</a> at Pivotal Labs, is to use <a href="http://github.com/floehopper/mocha/">mocha</a> to check that <code>puts</code> was called on the object.</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'test/unit'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'mocha'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> SimpleSemParserTest <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">Test::Unit::TestCase</span></span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> test_set_stmt_write
    parser = SimpleSemParser.<span style="color:#9900CC;">new</span>
    parser.<span style="color:#9900CC;">expects</span><span style="color:#006600; font-weight:bold;">&#40;</span>:<span style="color:#CC0066; font-weight:bold;">puts</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">with</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;Hello World!&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    parser.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'set write, &quot;Hello World!&quot;'</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">execute</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>


<p>This solution is fine for most situations; Mocha will throw an exception if <code>puts</code> is not called. However in my case, it was unsuitable because <code>puts</code> was not being called on the SimpleSemParser object but instead on a <a href="http://treetop.rubyforge.org/">Treetop</a> syntax node that I did not easily have access to within the unit test.</p>

<p>I knew that if I could capture the output from the <code>puts</code> method into a variable I would be able write the test using a standard <code>assert_equal</code>. After some googling I discovered that this functionality is built into the <a href="http://www.zenspider.com/ZSS/Products/ZenTest/index.html">ZenTest</a> gem. After rewriting the test looked like this.</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'test/zentest_assertions'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> SimpleSemParserTest <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">Test::Unit::TestCase</span></span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> test_set_stmt_write
    out, err = util_capture <span style="color:#9966CC; font-weight:bold;">do</span> 
      parser = SimpleSemParser.<span style="color:#9900CC;">new</span>
      parser.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'set write, &quot;Hello World!&quot;'</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">execute</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    assert_equal <span style="color:#996600;">&quot;Hello World!<span style="color:#000099;">\n</span>&quot;</span>, out.<span style="color:#CC0066; font-weight:bold;">string</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>


<p>This works great. However, should we decided that we do not want to use an external gem, with a little effort we can bypass ZenTest and implement <code>util_capture</code> ourselves.</p>

<p><span id="more-165"></span></p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'stringio'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">module</span> <span style="color:#CC00FF; font-weight:bold;">Kernel</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> capture_stdout
    out = <span style="color:#CC00FF; font-weight:bold;">StringIO</span>.<span style="color:#9900CC;">new</span>
    <span style="color:#ff6633; font-weight:bold;">$stdout</span> = out
    <span style="color:#9966CC; font-weight:bold;">yield</span>
    <span style="color:#0000FF; font-weight:bold;">return</span> out
  <span style="color:#9966CC; font-weight:bold;">ensure</span>
    <span style="color:#ff6633; font-weight:bold;">$stdout</span> = STDOUT
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>


<p>Done! We extended the Kernel module with a method called <code>capture_stdout</code><sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>. <code>capture_stdout</code> works by redirecting <code>$stdout</code> to an instance of <a href="http://www.ruby-doc.org/core/classes/StringIO.html">StringIO</a>. StringIO has all of the <a href="http://www.ruby-doc.org/core/classes/IO.html">IO</a> methods, but acts on a string instead of a file. After changing <code>$stdout</code> we yield to let the caller generate output. Once the yield is finished, we return the StringIO instance and add an ensure to guarantee that <code>$stdout</code> is reset to its default value. Adding <code>capture_stdout</code> to the Kernel module has the effect of giving <code>capture_stdout</code> a global scope so that it can be used anywhere.</p>

<p>With the exception that we that we renamed the method to <code>capture_stdout</code>, and are not returning <code>$stderr</code>, the unit test has not changed from the ZenTest version.</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> SimpleSemParserTest <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">Test::Unit::TestCase</span></span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> test_set_stmt_write
    out = capture_stdout <span style="color:#9966CC; font-weight:bold;">do</span> 
      parser = SimpleSemParser.<span style="color:#9900CC;">new</span>
      parser.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'set write, &quot;Hello World!&quot;'</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">execute</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    assert_equal <span style="color:#996600;">&quot;Hello World!<span style="color:#000099;">\n</span>&quot;</span>, out.<span style="color:#CC0066; font-weight:bold;">string</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>


<p>We end with a clean, very readable way to test Ruby methods that generate output without using any libraries.</p>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>I prefer this name over &#8220;util_capture&#8221;.&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://thinkingdigitally.com/archive/capturing-output-from-puts-in-ruby/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>A SIMPLESEM Interpreter</title>
		<link>http://thinkingdigitally.com/archive/a-simplesem-interpreter/</link>
		<comments>http://thinkingdigitally.com/archive/a-simplesem-interpreter/#comments</comments>
		<pubDate>Thu, 26 Feb 2009 09:35:24 +0000</pubDate>
		<dc:creator>Rob Olson</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[cs141]]></category>
		<category><![CDATA[simplesem]]></category>
		<category><![CDATA[treetop]]></category>

		<guid isPermaLink="false">http://thinkingdigitally.com/archive/a-simplesem-interpreter/</guid>
		<description><![CDATA[In my Programming Languages course, taught by Shannon Tauro we have been using a fake assembly language of sorts called SIMPLESEM to gain experience translating the semantics of a high level programming language, to a simple processor. Since SIMPLESEM is a made up language that was created just for our textbook, there was no way [...]]]></description>
			<content:encoded><![CDATA[<p>In my <a href="https://eee.uci.edu/09w/16250/">Programming Languages course</a>, taught by <a href="http://www.ics.uci.edu/~stauro/">Shannon Tauro</a> we have been using a fake assembly language of sorts called SIMPLESEM to gain experience translating the semantics of a high level programming language, to a simple processor.</p>

<p>Since SIMPLESEM is a made up language that was created just for our textbook, there was no way for me to execute the SIMPLESEM programs that I was writing for the homework assignments. This was annoying because SIMPLESEM is a low level language which makes it hard to notice mistakes. Of course, it is very easy to make a mistake any time you are programming but it is even harder to catch those mistakes if you are working at close to assembly level.</p>

<p>As a fun exercise I implemented an <a href="http://github.com/robolson/simplesem">interpreter for SIMPLESEM</a> using Ruby and published it as a RubyGem. Fortunately, I choose to use Nathan Sobo&#8217;s <a href="http://treetop.rubyforge.org/">Treetop</a> gem to aide in the development. Using Treetop, I wrote a parsing expression grammar to parse SIMPLESEM commands. This resulted in my SIMPLESEM interpreter being a lot more flexible than I had originally anticipated. After I familiarized myself with the basics of writing Treetop grammars I found it very easy to make changes to my grammar definitions to add language features one by one.</p>

<p><span id="more-158"></span>
Installing the SIMPLESEM interpreter should be easy if you are on Linux or OS X, and possible if you are on Windows. The program is packaged as a rubygem. *nix folks should have rubygems packaged with their system. Windows users should visit the  <a href="http://www.rubygems.org/read/chapter/3">RubyGems</a> page to get running. Once you are setup with RubyGems, install the simplesem gem from Gemcutter:</p>


<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">$ sudo gem install simplesem --source http://gemcutter.org</pre></div></div>


<p>The gem installs a command called <code>simplesem</code>. To test it out download this <a href="http://github.com/robolson/simplesem/blob?path[]=sample_programs&amp;path[]=hello-world.txt&amp;raw=true">sample SIMPLESEM program</a> that prints &#8220;hello world!&#8221; five times. Run it by passing the name of the file as an argument to the command.</p>


<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">$ simplesem hello-world.txt
hello world!
hello world!
hello world!
hello world!
hello world!</pre></div></div>


<p>You can view other sample SIMPLESEM programs <a href="http://github.com/robolson/simplesem/tree/master/sample_programs">here</a>. To learn more about SIMPLESEM or the interpreter check out the <a href="http://github.com/robolson/simplesem/blob/master/README.textile">README</a>.</p>

<div class="resource-list"><dl>

<dt><a href="http://github.com/robolson/simplesem">
<img src="/images/icons/application_x-ruby.png" alt="SIMPLESEM Interpreter on GitHub" />
SIMPLESEM Interpreter</a></dt>
<dd>Source code available on GitHub.</dd>

</dl></div>
]]></content:encoded>
			<wfw:commentRss>http://thinkingdigitally.com/archive/a-simplesem-interpreter/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The Case For Replacing Java With Python In Education</title>
		<link>http://thinkingdigitally.com/archive/the-case-for-replacing-java-with-python-in-education/</link>
		<comments>http://thinkingdigitally.com/archive/the-case-for-replacing-java-with-python-in-education/#comments</comments>
		<pubDate>Tue, 27 Jan 2009 21:56:26 +0000</pubDate>
		<dc:creator>Rob Olson</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[School]]></category>
		<category><![CDATA[computer science]]></category>
		<category><![CDATA[CS Education]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://thinkingdigitally.com/archive/the-case-for-replacing-java-with-python-in-education/</guid>
		<description><![CDATA[Around 2003 all of the colleges and high schools in the United States switched from teaching Computer Science courses in C++ to teaching them in Java. The intention was to make it easier for students to pick up programming. Schools were finding that many students were struggling to cope with low level tasks in C++ [...]]]></description>
			<content:encoded><![CDATA[<p>Around 2003 all of the colleges and high schools in the United States switched from teaching Computer Science courses in C++ to teaching them in Java. The intention was to make it easier for students to pick up programming. Schools were finding that many students were struggling to cope with low level tasks in C++ like manual memory management and pointer references. Instead of learning algorithms, data structures and object oriented programming, students were stuck for hours trying to track down incorrect pointer references.</p>

<p>About four years after the education system made the switch to Java from C++, the whole software industry started complaining about the degrading quality of the Computer Science graduates in the US; which is a <a href="http://thinkingdigitally.com/archive/what-if-i-went-to-a-java-school-joel/">topic I explored recently</a>. Ultimately, schools have made the switch away from C++, and they are unlikely to go back, nor do I think they should. Instead, what I want to discuss is why did we have to replace C++ with <em>Java</em>? I can see that at the time, it may have seemed the obvious choice, but looking around the language landscape now there are several choices that I think are better suited for the task. Namely, Python.</p>

<h3>Java > Python How???</h3>

<p>First, I want to really think about what advantage does learning programming with Java have over using a modern scripting language like Python? Python equally hides the things that make programming in C++ laborious and has many of the nice features that the JVM provides like garbage collection, unicode strings, and threads. The difference is Java is miserable for web programming (Java EE) and equally overly complex for building GUIs (Swing). As a scripting language, Python is far easier to pick and learn.</p>

<h3>What CS students would lose from switching from Java to Python</h3>

<ul>
<li><strong>Static Typing</strong> &#8211; The difference between an Integer and a Float is harder to understand when you do not have to declare variable types.</li>
<li><strong>Compilation</strong> &#8211; In my opinion this is not a big deal. They are still going to learn how to debug runtime errors which is where the substance is. Advanced IDEs like Eclipse are making dealing with compiler errors almost a thing of the past in Java. Additionally, the upper division compilers class will still be there to teach them the ins and outs of compilers.</li>
<li><strong>Performance</strong> &#8211; This is a moot point. I only put it down because it is what most people think of first but very rarely do the projects assigned in a classroom require serious computation. I would also wager that even the ones that do can be solved in a satisfactory manor with Python. If anything it will force students to be more creative about their solutions instead of just relying on brute force.</li>
</ul>

<h3>What CS students will gain from switching from Java to Python</h3>

<ul>
<li><strong>Dynamic Typing</strong> &#8211; There are tradeoffs to both approaches but as nearly everyone who programs dynamically typed language for a while finds out that the type safety provided by static typing is unnecessary and more often gets in your way than it helps you (ex. Casting).</li>
<li><strong>Interpretation</strong> &#8211; Becoming familiar with interpretation is just as important as compilation. Interpretation opens several doors for you when programming and is becoming more common. In addition it gives you helpful tools like an interactive console.</li>
</ul>

<p>Overall, there is no big loss in Computer Science concepts when moving from Java to Python like there was when we moved away from C++.  You trade static typing for dynamic typing and compilation for interpretation but everything else is just about the same and you gain Python&#8217;s simplicity.</p>

<p>One of the real problems with Java is that many students do not like to use it when programming for fun. Since the majority of students only become competent in Java, they only code they write is for their homework assignments. These are type A CS students. There is a second, type B, group of CS students. Type B students pick up another language like PHP, Python, Ruby, Clojure, etc. and are ones who spend time coding and creating cool things outside of their schoolwork. These students find programming on the side to be the most enriching and also the most educational. Employers often cite type B students, the self starters, as the ones they are most interested in hiring. If the only programming a student does while attending school is for their class projects, it is more than likely that they will continue this practice once leaving school, only writing code for their job. By making the switch away from Java in education, more type B CS students would emerge from American universities; enormously benefiting the software industry.</p>
]]></content:encoded>
			<wfw:commentRss>http://thinkingdigitally.com/archive/the-case-for-replacing-java-with-python-in-education/feed/</wfw:commentRss>
		<slash:comments>34</slash:comments>
		</item>
		<item>
		<title>What if I went to a Java school Joel?</title>
		<link>http://thinkingdigitally.com/archive/what-if-i-went-to-a-java-school-joel/</link>
		<comments>http://thinkingdigitally.com/archive/what-if-i-went-to-a-java-school-joel/#comments</comments>
		<pubDate>Wed, 30 Jul 2008 17:17:40 +0000</pubDate>
		<dc:creator>Rob Olson</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[computer science]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[Joel Spolsky]]></category>

		<guid isPermaLink="false">http://thinkingdigitally.com/?p=56</guid>
		<description><![CDATA[Way back in 2005, I read an essay by Joel Spolsky titled The Perils of JavaSchools. When I read the essay the first time, I suspected Joel was right about Java trivializing several aspects of the traditional Computer Science education, but I didn&#8217;t really care. At the time I was just starting my second quarter [...]]]></description>
			<content:encoded><![CDATA[<p>Way back in 2005, I read an essay by Joel Spolsky titled <a href="http://www.joelonsoftware.com/articles/ThePerilsofJavaSchools.html">The Perils of JavaSchools</a>. When I read the essay the first time, I suspected Joel was right about Java trivializing several aspects of the traditional Computer Science education, but I didn&#8217;t really care. At the time I was just starting my second quarter of college in the CS program at the University of California at Irvine which definitely falls under the &#8220;Java school&#8221; classification. At that point I had only ever really programmed in Java and I liked it a lot. Joel was right, but I was happy with my relative Java proficiency at a Java School so I largely indifferent.</p>

<p>Fast forward to the present. Last week, I borrowed Joel&#8217;s new book &#8220;More Joel on Software&#8221; from <a href="http://www.techcrunch.com/">Michael Arrington</a> which contains the &#8220;Perils of JavaSchools&#8221; essay. Reading the essay again I was blown away. What a difference a few years of CS education makes! This time instead of just <em>feeling</em> that Joel is right, I <em>know</em> he is right. Learning Computer Science completely in Java instead of C with a healthy dose of functional languages like Scheme is two different worlds.<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup></p>

<h3>All CS degrees are not created equal</h3>

<p>Is the value of my CS education less than that of the traditional CS education Joel reminisced about? All other things being equal, I would say absolutely say &#8220;Yes&#8221;. I can not help but agree with Joel when he says that an all Java education can never be of the same caliber as the CS programs that preceded the Java &#8220;revolution&#8221;. People like Guido van Rossum, Paul Graham, Steve Yegge, Linus Torvalds and many other great hackers all received their degrees before the notion of a Java school existed. And as Joel puts it, they all went &#8220;stark, raving mad trying to pack things into bits&#8221;. The bit level is considered foreign territory for students at Java schools; a place we dare to venture only once or twice and will quickly return to the safety of the Java virtual machine.</p>

<p>Joel&#8217;s essay is best summarized by this paragraph:</p>

<blockquote>
  <p>You used to start out in college with a course in data structures, with linked lists and hash tables and whatnot, with extensive use of pointers. These courses were often used as weedout courses: they were so hard that anyone that couldn&#8217;t handle the mental challenge of a CS degree would give up, which was a good thing, because if you thought pointers are hard, wait until you try and prove things about fixed point theory.</p>
</blockquote>

<h3>I have never even heard of fixed point theory!</h3>

<p>Finally we come to my dilemma. I have one year left at my Java school and I desperately want to avoid mediocrity. Since adopting Ruby as my primary programming language last summer, I have experienced several small victories. Ruby is a very powerful language which is gradually breaking me away from the ridged programming practices I picked up from programming in Java for 3 years. Ruby has introduced me to things like metaprogramming, reflection, DSL&#8217;s, anonymous methods, and several aspects of functional programming. All are things that I never would have been able to fathom had I stayed inside my Java bubble. I will say that CS students at Irvine take a Programming Languages class which introduces unfamiliar languages like Haskell. Unfortunately, the class doesn&#8217;t make up much ground. Like all classes it is only 10 weeks long and students only get a brief look at the various languages they are introduced to. To top it off most of the projects are <em>still</em> done with Java.</p>

<h3>Ruby is not the Answer to Life, the Universe, and Everything</h3>

<p>Ruby is great but its not going to teach me any of the low level knowledge I am lacking. I can program in Ruby for another decade and still not achieve a full understanding pointers. The only thing I can do to understand why <strong>while (&#42;s++ = &#42;t++);</strong> copies a string, is to actually program in C.</p>

<h3>Why I am not learning C now</h3>

<p>Learning C is something that you generally need to be forced into. In today&#8217;s world you are not going to able to write very much software if you are coding the entire thing in C from top to bottom. It is a very anti &#8220;Get Things Done&#8221; programming language. In addition, there are very few things that actually need to be written in C. Operating systems and compilers are the two big areas where use of C is nearly always required. Both are territory that I am not interested in venturing into at this point. The most common use for C among software developers is to optimize slow chunks of code by rewriting them in C. However, everything I write does not need to &#8220;scale&#8221; so while I always do my best to not write inefficient code, I can not be bothered to rewrite any of it in C when it is &#8220;fast enough&#8221; already.</p>

<h3>What I am going to do about it</h3>

<p>This is a problem that I have not thought of a solution for. I can not bring myself to sacrifice productivity in order to use C. At first I thought I would learn Objective-C which is based on C in order to create Cocoa applications for Mac OS X. That solution is flawed however. Just like Joel says <a href="http://www.joelonsoftware.com/articles/CollegeAdvice.html">learning C++ is not a substitute for learning C</a>, the same is true for Objective-C. My best chance is if something in my school work for next year comes up that requires the use of C. If it does happen it will be an elective; the chance of a required course using C at Irvine is very slim. I am just one person, what I am experiencing is true for Computer Science students across the county at Java schools. We are collectively being handed a disadvantageous education and in the long run it will have a direct impact on the level of software engineering that is being done in the United States. For instance, I would guess that a graduate from a Java school is far less likely to ever contribute to the Linux kernel, GCC, or a similar project. This is of great consequence because we need innovation at the lowest level of software in order to continue innovating at the top.</p>

<p>Obviously, if American Universities are going to keep up, they need to switch back to the &#8220;middle ages&#8221; of Computer Science and resume using C in the classroom. For those of us that are already in the system, or recently graduated, individual crusades are required to attain the level of understanding that is obligatory for Computer Science graduates. For myself, this will likely include working through the exercises in <a href="http://mitpress.mit.edu/sicp/">Structure and Interpretation of Computer Programs</a> and the <a href="http://webcast.berkeley.edu/course_details.php?seriesid=1906978454">accompanying lectures</a>. I am still looking for a good, practical way to learn C. Just reading <a href="http://cm.bell-labs.com/cm/cs/cbook/">Kernighan and Ritchie</a> is not going to be sufficient. There is a big distinction between learning to program and learning a language. I need to learn to program&mdash;for real this time.</p>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>Read &#8220;The Perils of JavaSchools&#8221; for an explanation of why they are different.&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://thinkingdigitally.com/archive/what-if-i-went-to-a-java-school-joel/feed/</wfw:commentRss>
		<slash:comments>63</slash:comments>
		</item>
		<item>
		<title>Rails-doc.org is my new Rails Reference</title>
		<link>http://thinkingdigitally.com/archive/rails-docorg-is-my-new-rails-reference/</link>
		<comments>http://thinkingdigitally.com/archive/rails-docorg-is-my-new-rails-reference/#comments</comments>
		<pubDate>Fri, 04 Jul 2008 18:32:27 +0000</pubDate>
		<dc:creator>Rob Olson</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[rails-doc]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://thinkingdigitally.com/archive/rails-docorg-is-my-new-rails-reference/</guid>
		<description><![CDATA[When working with a framework as large as Ruby on Rails its necessary to have a reference close by for&#8230; well just about everything. Until recently I was a big fan of gotAPI.com because I really appreciated the Ruby and Rails reference tied together. However, the Javascript autocomplete on their search box is broken in [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://thinkingdigitally.com/wp-content/uploads/2008/07/rails-doc-logo.png" class="display-inline-right" alt="Rails-doc.org" />
When working with a framework <a href="http://api.rubyonrails.org/">as large as Ruby on Rails</a> its necessary to have a reference close by for&#8230; well just about everything. Until recently I was a big fan of <a href="http://www.gotapi.com/rubyrails">gotAPI.com</a> because I really appreciated the Ruby and Rails reference tied together. However, the Javascript autocomplete on their search box is broken in <a href="http://www.spreadfirefox.com/en-US/worldrecord/firefox3">Firefox 3</a> so I decided to try the new Rails reference site, <a href="http://rails-doc.org">Rails-doc.org</a>.</p>

<p>Rails-doc.org is an fairly ambitious project to create a community driven Rails documentation site. Basically they let users sign up and contribute notes to the existing Rails documentation. This certainly has the potential to be very useful, especially for new Rails hackers because sometimes the people who have been around the framework for a while just take things for granted.</p>

<p>Take the documentation for <a href="http://www.ruby-doc.org/core-1.8.6/classes/Date.html#M000620">strftime in the Date class</a> for example. There is no documentation listed for that method. Despite the fact that you clearly need documentation of the strftime options in order to use that method. Instead you have to know to look under <a href="http://www.ruby-doc.org/core-1.8.6/classes/Time.html#M000297">strftime in the Time class</a> for the documentation. While this is an example specific to Ruby documentation, these are the kinds of obvious problems that a community documentation website can help solve.</p>

<p>Right now Rails-doc.org has only been live for a month the so amount of community documentation feels very low. In the mean time I&#8217;ll be using the site for the official documentation that is already in place. Plus its the best looking rendering of the Rails documentation site out there. The Nodeta guys did a good job with the design. They also have a nice looking <a href="http://blog.nodeta.fi/">blog</a>.</p>

<p>It will be interested to see how many of the notes contributed to Rails-doc get ported to the official Rails documentation. This certainly feels like the easiest and most straightforward way to contribute to Rails documentation and I can see it becoming a testing ground for future contributions to the official docs.</p>
]]></content:encoded>
			<wfw:commentRss>http://thinkingdigitally.com/archive/rails-docorg-is-my-new-rails-reference/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Ruby-Poker 0.3.0</title>
		<link>http://thinkingdigitally.com/archive/ruby-poker-030/</link>
		<comments>http://thinkingdigitally.com/archive/ruby-poker-030/#comments</comments>
		<pubDate>Wed, 28 May 2008 08:04:33 +0000</pubDate>
		<dc:creator>Rob Olson</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[poker]]></category>
		<category><![CDATA[ruby-poker]]></category>

		<guid isPermaLink="false">http://thinkingdigitally.com/archive/ruby-poker-030/</guid>
		<description><![CDATA[Ruby Poker has been updated! This release is largely a result of bug reports filed by Jim W. He took ruby poker to areas I had not previously thought to explore and he ran into a couple nasty bugs. They have all been fixed in Ruby-Poker 0.3.0. In addition the following changes were made that [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://rubyforge.org/projects/rubypoker/">Ruby Poker</a> has been updated! This release is largely a result of bug reports filed by <a href="http://rubyforge.org/users/asucis2001">Jim W</a>. He took ruby poker to areas I had not previously thought to explore and he ran into a couple nasty bugs. They have all been fixed in Ruby-Poker 0.3.0. In addition the following changes were made that users should be aware of.</p>

<p><span id="more-50"></span></p>

<h3>Comparing cards has changed</h3>

<p>Before 0.3.0 two cards objects were regarded as equal if they had the same face value. Resulting in a 6 of Spades being equal to a 6 of Clubs. After some thinking I decided that I did not like that and changed it so cards must have the same face value and same suit to be considered equal. This should not affect anyone unless they are creating and comparing Card objects directly.</p>

<h3>PokerHand#arranged&#95;hand has been replaced by PokerHand#sort&#95;using&#95;rank</h3>

<p>To sort a PokerHand there are a couple options. <a href="http://rubypoker.rubyforge.org/classes/PokerHand.html#M000016">PokerHand#by&#95;face</a> will sort a PokerHand in order from least to highest. But what if you have a pair and want to sort the cards based on the hand&#8217;s poker rank. For that there is <a href="http://rubypoker.rubyforge.org/classes/PokerHand.html#M000034">PokerHand#sort&#95;using&#95;rank</a> which was previously available as PokerHand#arranged&#95;hand but it wasn&#8217;t documented.</p>

<h3>Handling of duplicate cards</h3>

<p>Before 0.3.0 Ruby-Poker would not complain if you added four 8&#8242;s of Clubs to a PokerHand. I&#8217;ve added a configuration option so that you can tell Ruby-Poker to throw a tantrum if you try and add the same card to a PokerHand twice.</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'ruby-poker'</span>  
PokerHand.<span style="color:#9900CC;">allow_duplicates</span> = <span style="color:#0000FF; font-weight:bold;">false</span>  
PokerHand.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;8c&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#996600;">&quot;8c&quot;</span>   <span style="color:#008000; font-style:italic;"># this throws a RuntimeError</span></pre></div></div>


<p>allow_duplicates is set to true by default so you will not notice anything different unless you choose to opt-in to the exceptions.</p>

<p><strong>That&#8217;s everything</strong></p>

<p>As always you can install ruby-poker with the gem command.</p>


<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">gem install ruby-poker</pre></div></div>


<p>Or <code>gem update ruby-poker</code> if you already have it installed to upgrade from an old version.</p>
]]></content:encoded>
			<wfw:commentRss>http://thinkingdigitally.com/archive/ruby-poker-030/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Book Review: The Ruby Programming Language</title>
		<link>http://thinkingdigitally.com/archive/book-review-the-ruby-programming-language/</link>
		<comments>http://thinkingdigitally.com/archive/book-review-the-ruby-programming-language/#comments</comments>
		<pubDate>Tue, 27 May 2008 01:14:51 +0000</pubDate>
		<dc:creator>Rob Olson</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[book review]]></category>

		<guid isPermaLink="false">http://thinkingdigitally.com/archive/book-review-the-ruby-programming-language/</guid>
		<description><![CDATA[For a long time now Dave Thomas Programming Ruby (aka. The Pickaxe) has been the standard in the Ruby community as the book to learn Ruby from. Unfortunately the Pickaxe is not the best programming book ever written. In fact, its bulk and slowness almost killed my inspiration to learn Ruby. I respect Dave Thomas [...]]]></description>
			<content:encoded><![CDATA[<iframe src="http://rcm.amazon.com/e/cm?t=zotrails-20&#038;o=1&#038;p=8&#038;l=as1&#038;asins=0596516177&#038;fc1=000000&#038;IS2=1&#038;lt1=_top&#038;lc1=0000FF&#038;bc1=000000&#038;bg1=FFFFFF&#038;f=ifr" style="width:120px;height:240px;float:left;margin:0 10px 3px 0" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>

<p>For a long time now Dave Thomas <a href="http://www.pragprog.com/titles/ruby/programming-ruby"><em>Programming Ruby</em> (aka. The Pickaxe)</a> has been the standard in the Ruby community as the book to learn Ruby from. Unfortunately the Pickaxe is not the best programming book ever written. In fact, its bulk and slowness almost killed my inspiration to learn Ruby. I respect Dave Thomas a lot for what he does for the Ruby community but the Pickaxe and I just did not click.</p>

<p>Since I didn&#8217;t find the Pickaxe to be excellent reading material, I had been eagerly anticipating <a href="http://www.davidflanagan.com/">David Flanagan&#8217;s</a> <a href="http://www.oreilly.com/catalog/9780596516178/"><em>The Ruby Programming Language</em></a> to come out and unseat The Pickaxe as the de facto book to recommend to newcomers to Ruby.</p>

<p>I am happy to say that <em>The Ruby Programming Language</em> did not disappoint. I picked up this book solely expecting to just review it since I already comfortable programming in Ruby. However, once I started reading the book I found myself frequently learning things about Ruby that I didn&#8217;t know before. Not like little things either like, &#8220;oh that&#8217;s interesting&#8221;. I&#8217;m talking significant things like &#8220;holy crap that&#8217;s sweet&#8221;.</p>

<p>This book covers both Ruby 1.8 and Ruby 1.9. Initially this concerned me because as impressive as it is, it must have been quite a headache for the authors and was not sure how they were going to pull it off. It turns out to be pretty much a non-issue. The authors make a note of what is 1.8 or 1.9 only and it does not disturb the flow of the book since it doesnâ€™t come up too frequently. I do hope though that after Ruby 1.9 stable is released they upgrade the book and tear out all the 1.8 specific material. Since I currently use 1.8 on a daily basis I don&#8217;t mind having 1.8 material in there but after everything has shifted to 1.9 it would be rather irksome.</p>

<p>The style of the book is fairly straightforward. It starts with an introduction to how Ruby programs work and then goes into an explanation of Ruby datatypes and objects. The later chapters cover advanced topics like reflection and metaprogramming. The authors opted not to go the tutorial route, which I think, was a good approach since the book is not designed to be an &#8220;intro to programming&#8221; text.</p>

<p>In the preface of the book, the authors state:</p>

<blockquote>
  <p>[The Ruby Programming Language] is loosely modeled after the classic <em>The C Programming Language</em> by Kernighan and Ritchie and aims to document the Ruby language comprehensively but without the formality of a language specification. It is written for experienced programmers who are new to Ruby, and for current Ruby programmers who want to take their understanding and mastery of the language to the next level.</p>
</blockquote>

<p>O&#8217;Reilly is hoping that <em>The Ruby Programming Language</em> becomes the equivalent of K&amp;R&#8217;s <em>The C Programming Language</em> for Ruby and I hope it succeeds. I think that every language needs their own K&amp;R book for people to turn to as the definitive authority. That&#8217;s something that I feel like the Java programming language never had and it creates something of a hurdle when browsing for a Java book.</p>

<p>The third edition of the Pickaxe is in beta and will be coming out soon. I really hope it makes a strong showing when it hits the press because after the bang-up job Flanagan and Matz did with <em>The Ruby Programming Language</em>, there is no reason to look at the Pickaxe till then.</p>
]]></content:encoded>
			<wfw:commentRss>http://thinkingdigitally.com/archive/book-review-the-ruby-programming-language/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Ruby-Poker 0.2.4</title>
		<link>http://thinkingdigitally.com/archive/ruby-poker-024/</link>
		<comments>http://thinkingdigitally.com/archive/ruby-poker-024/#comments</comments>
		<pubDate>Mon, 21 Apr 2008 04:42:46 +0000</pubDate>
		<dc:creator>Rob Olson</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[poker]]></category>
		<category><![CDATA[ruby-poker]]></category>

		<guid isPermaLink="false">http://thinkingdigitally.com/archive/ruby-poker-024/</guid>
		<description><![CDATA[I just pushed out another release of the ruby-poker gem. The only change in this release is some code changes to achieve compatibility with Ruby 1.9. Initially I had thought that I would not need to change anything for 1.9 because ruby-poker-0.2.2 installed and ran through some quick examples without any trouble. However, I was [...]]]></description>
			<content:encoded><![CDATA[<p>I just pushed out another release of the <a href="http://rubyforge.org/projects/rubypoker/">ruby-poker</a> gem. The only change in this release is some code changes to achieve compatibility with Ruby 1.9.</p>

<p>Initially I had thought that I would not need to change anything for 1.9 because ruby-poker-0.2.2 installed and ran through some quick examples without any trouble. However, I was saved by my test suite when it quickly exposed a problem where I was calling <code>each</code> on a <code>String</code> object. The <code>each</code> method was removed from String in 1.9 so I made a quick change to work around it and once again I&#8217;m seeing nothing but dots.</p>

<p><img src="http://thinkingdigitally.com/wp-content/uploads/2008/04/rp-unit-tests-pass.png" alt="Rp Unit Tests Pass" /></p>
]]></content:encoded>
			<wfw:commentRss>http://thinkingdigitally.com/archive/ruby-poker-024/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Eager Loading with Ultrasphinx</title>
		<link>http://thinkingdigitally.com/archive/eager-loading-with-ultrasphinx/</link>
		<comments>http://thinkingdigitally.com/archive/eager-loading-with-ultrasphinx/#comments</comments>
		<pubDate>Fri, 11 Apr 2008 08:44:17 +0000</pubDate>
		<dc:creator>Rob Olson</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[ultrasphinx]]></category>

		<guid isPermaLink="false">http://thinkingdigitally.com/archive/eager-loading-with-ultrasphinx/</guid>
		<description><![CDATA[Ultrasphinx is a great Rails plugin that wraps around the Sphinx full-text search engine. I am using Ultrasphinx to handle search queries on a personal project I&#8217;m working on and I ran into a situation where I wanted to eager load associated models for my search results. The method for doing this is not well [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.evanweaver.com/files/doc/fauna/ultrasphinx/files/README.html">Ultrasphinx</a> is a great Rails plugin that wraps around the <a href="http://www.sphinxsearch.com/">Sphinx full-text search engine</a>. I am using Ultrasphinx to handle search queries on a personal project I&#8217;m working on and I ran into a situation where I wanted to eager load associated models for my search results. The method for doing this is not well documented so I&#8217;m going to step through how to add eager loading to your Ultrasphinx searches.</p>

<p>I am actually going to show two ways to do this. The first is the way that <a href="http://blog.evanweaver.com/">Evan Weaver</a>, the creator of Ultrasphinx, recommends and the second way is the create a simple plugin that extends the Ultrasphinx plugin. The second way is my favorite because it provides the cleanest integration in my opinion but I&#8217;m going to demonstrate both methods so you can choose for yourself.</p>

<p><span id="more-36"></span></p>

<h2>Method 1</h2>

<p>To begin we need to make a class method that performs the eager loading in the model. Something like this:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;">## app/models/course.rb</span>
<span style="color:#9966CC; font-weight:bold;">class</span> Course
  ...
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">find_with_includes</span><span style="color:#006600; font-weight:bold;">&#40;</span>id<span style="color:#006600; font-weight:bold;">&#41;</span>
    find<span style="color:#006600; font-weight:bold;">&#40;</span>id, :<span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:professors</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>


<p>Notice how I&#8217;m using the familiar ActiveRecord include option to perform the eager loading like we would normally. The next and last step is to add the method to <code>client_options[:finder_methods]</code> in your <code>environment.rb</code>.</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;">## config/environment.rb  </span>
<span style="color:#6666ff; font-weight:bold;">Ultrasphinx::Search</span>.<span style="color:#9900CC;">client_options</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:finder_methods</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">unshift</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:find_with_includes</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>


<p>That&#8217;s it. Now to the second method.</p>

<h2>Method 2</h2>

<p>As I mentioned before, in this method we are going to create a simple plugin that will add functionality to Ultrasphinx. The code for this plugin was written by <a href="http://rubyforge.org/users/malesca/">Henrik N</a>.</p>

<p>Create a new folder in <code>vendor/plugins/</code> called <code>ultrasphinx_customizations</code>. The name can be anything you like as long as it starts with &#8220;ultrasphinx&#8221;. This is so our customizations are loaded after the actual Ultrasphinx plugin. Inside the folder create <code>init.rb</code> and place this line in it.</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;">## vendor/plugins/ultrasphinx_customizations/init.rb</span>
<span style="color:#CC00FF; font-weight:bold;">Dir</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">dirname</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">__FILE__</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#996600;">'/lib/*.rb'</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">each</span> <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>file<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#CC0066; font-weight:bold;">require</span> file <span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>


<p>Now for the part of the plugin that actually does the work. Create a <code>lib</code> folder in <code>ultrasphinx_customizations</code> and create a new file in it called <code>eager_loading.rb</code> with the following contents.</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;">## vendor/plugins/ultrasphinx_customizations/lib/eager_loading.rb</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Allows specifying eager loading options as e.g.</span>
<span style="color:#008000; font-style:italic;"># Ultrasphinx::Search.client_options[:include]['MyKlass'] =&gt; [:user]</span>
<span style="color:#008000; font-style:italic;"># or directly in is_indexed like</span>
<span style="color:#008000; font-style:italic;"># is_indexed ..., :eagerly_load =&gt; [:user]</span>
&nbsp;
<span style="color:#6666ff; font-weight:bold;">Ultrasphinx::Search</span>.<span style="color:#9900CC;">client_options</span>.<span style="color:#9900CC;">merge</span>!<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">HashWithIndifferentAccess</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#123;</span>
  <span style="color:#ff3333; font-weight:bold;">:finder_methods</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'find_all_by_id_with_eager_loading'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
  :<span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">find_all_by_id_with_eager_loading</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">*</span>ids<span style="color:#006600; font-weight:bold;">&#41;</span>
    includes = <span style="color:#6666ff; font-weight:bold;">Ultrasphinx::Search</span>.<span style="color:#9900CC;">client_options</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'include'</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">name</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    args = ids <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#006600; font-weight:bold;">&#91;</span>:<span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> includes<span style="color:#006600; font-weight:bold;">&#93;</span>
    find_all_by_id<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">is_indexed_with_include_option</span><span style="color:#006600; font-weight:bold;">&#40;</span>options<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#6666ff; font-weight:bold;">Ultrasphinx::Search</span>.<span style="color:#9900CC;">client_options</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'include'</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">name</span><span style="color:#006600; font-weight:bold;">&#93;</span> = options.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:eagerly_load</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    is_indexed_without_include_option<span style="color:#006600; font-weight:bold;">&#40;</span>options<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#0000FF; font-weight:bold;">self</span>; alias_method_chain <span style="color:#ff3333; font-weight:bold;">:is_indexed</span>, <span style="color:#ff3333; font-weight:bold;">:include_option</span>; <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>


<p>Sweet we&#8217;re done with the plugin. Now for the fun part. Remember in the model where we have our Ultrasphinx <code>is_indexed :fields =&gt; [...]</code> declaration? Thanks to our new customization we can add an <code>:eagerly_loaded</code> key and it will behave like an ActiveRecord find(:include => &#8230;). Here is what mine looks like.</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;">## app/models/course.rb</span>
&nbsp;
is_indexed  <span style="color:#ff3333; font-weight:bold;">:fields</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'course_number'</span>, <span style="color:#996600;">'title'</span>, <span style="color:#996600;">'term'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
            <span style="color:#ff3333; font-weight:bold;">:eagerly_load</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:professors</span><span style="color:#006600; font-weight:bold;">&#93;</span></pre></div></div>


<p>That&#8217;s all you have to do! I really enjoy the second method because it provides a seamless integration with the <code>is_indexed</code> call which seems to help me sleep at night.</p>

<p>Huge thanks to Henrik N for writing the ultrasphinx_customization code and Evan Weaver for writing Ultrasphinx.</p>

<p><strong>Updated 04/17/2008</strong>: Fixed incorrect statement about plugin names.</p>
]]></content:encoded>
			<wfw:commentRss>http://thinkingdigitally.com/archive/eager-loading-with-ultrasphinx/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>

