<?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>Pervasive Code &#187; Uncategorized</title>
	<atom:link href="http://www.pervasivecode.com/blog/category/uncategorized/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.pervasivecode.com/blog</link>
	<description>Jamie Flournoy's Software Development Blog</description>
	<lastBuildDate>Wed, 01 Feb 2012 06:11:00 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Patch to make Ubuntu&#8217;s GNU Screen bash completion work better</title>
		<link>http://www.pervasivecode.com/blog/2012/02/01/patch-to-make-ubuntus-gnu-screen-bash-completion-work-better/</link>
		<comments>http://www.pervasivecode.com/blog/2012/02/01/patch-to-make-ubuntus-gnu-screen-bash-completion-work-better/#comments</comments>
		<pubDate>Wed, 01 Feb 2012 06:11:00 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/?p=258</guid>
		<description><![CDATA[If you make a screen with a name using screen -S foo and then try and reattach later using screen -R f&#60;tab&#62; it doesn&#8217;t work. It only completes the full name as seen in screen -ls which starts with the PID of the detached screen, like 9972.foo. Not very convenient. Why can&#8217;t it just complete [...]]]></description>
			<content:encoded><![CDATA[<p>If you make a screen with a name using <code>screen -S foo</code> and then try and reattach later using <code>screen -R f&lt;tab&gt;</code> it doesn&#8217;t work. It only completes the full name as seen in <code>screen -ls</code> which starts with the PID of the detached screen, like <code>9972.foo</code>. Not very convenient. Why can&#8217;t it just complete using the name you gave it?</p>
<p><a href="http://alioth.debian.org/tracker/?func=detail&#038;atid=413095&#038;aid=311540&#038;group_id=100114">Someone else solved this problem three years ago</a> but nobody accepted their patch, and now /etc/bash_completion.d/screen has been overhauled and the patch no longer applies.</p>
<p>I updated the patch so it works and <a href="https://bugs.launchpad.net/ubuntu/+source/bash-completion/+bug/924676">resubmitted it to Ubuntu</a>.</p>
<p>If you don&#8217;t wanna wait, grab the code from <a href="https://gist.github.com/1715383">this gist</a> and do this:</p>
<pre>sudo patch /etc/bash_completion.d/screen screen.patch</pre>
<p>This will probably work on Debian too since that&#8217;s where the completion script came from.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2012/02/01/patch-to-make-ubuntus-gnu-screen-bash-completion-work-better/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>On Ruby&#8217;s Expressiveness- The Littlest Microframework Explained</title>
		<link>http://www.pervasivecode.com/blog/2011/03/27/on-rubys-expressiveness-the-littlest-microframework-explained/</link>
		<comments>http://www.pervasivecode.com/blog/2011/03/27/on-rubys-expressiveness-the-littlest-microframework-explained/#comments</comments>
		<pubDate>Sun, 27 Mar 2011 20:14:26 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/?p=250</guid>
		<description><![CDATA[In the past few weeks, I&#8217;ve had a few conversations with web developers and back-end engineers who are unfamiliar with Ruby, in which I&#8217;ve tried to explain how Ruby can be nearly as expressive as Perl (tiny amounts of code can accomplish a lot) while being as readable as Python or Java. In fact, I [...]]]></description>
			<content:encoded><![CDATA[<p>In the past few weeks, I&#8217;ve had a few conversations with web developers and back-end engineers who are unfamiliar with Ruby, in which I&#8217;ve tried to explain how Ruby can be nearly as expressive as Perl (tiny amounts of code can accomplish a lot) while being as readable as Python or Java. In fact, I think that Ruby&#8217;s expressiveness can remove distracting boilerplate code, allowing compact expressions to be far more readable than a more verbosely written version of the same algorithm.<br />
<span id="more-250"></span><br />
Sadly, if you are not a Ruby developer, this may sound rather suspicious &mdash; what is this, cult gibberish? &#8220;As expressive as Perl without being hard to read? Nonsense! The only way to make readable code is to use Java, and to write 5x as many lines as is absolutely necessary, embedding a comment before every line and a Javadoc with as many lines of explanation as the code in the method.&#8221; I disagree; I think code should be self-documenting, and that it should be clear <i>to a programmer familiar with that language</i> what the code is doing, without the need for inline comments except in rare cases.</p>
<p>Well, a few months ago <a href="http://www.igvita.com/">Ilya Grigorik</a> posted <a href="https://gist.github.com/675667">a Gist containing a really amusing microframework</a> that is one of the most brilliantly expressive bits of code I&#8217;ve ever seen, without being particularly hard to read. 13 lines of Ruby code provides a web application that will allow any Ruby object you choose to have its entire public API exposed via URLs of the form /method/arg1/arg2, where the method return value becomes the response body.</p>
<p>For the benefit of non-Ruby developers, I&#8217;m going to walk through all 13 lines of code plus the 1-line example application to explain how it works. I really hope that by reading through this explanation you will come to appreciate the expressiveness of Ruby, and maybe what a clever bit of dynamic language programming this is.</p>
<p>Here is the code: <a href="https://gist.github.com/675667">Inspired by @JEG2&#8217;s talk at Rubyconf&#8230; Any ruby object, as a webapp! &#8216;Cause we can. :-)</a><br />
In particular, note the 7th comment, with the embedded animated GIF. This should put you into the right frame of mind for understanding this code.</p>
<p>Line 1: Load <a href="http://rubygems.org/">RubyGems</a>, which is a library that helps you manage other Ruby libraries that your code depends on.</p>
<p>Line 2: Load <a href="http://rack.rubyforge.org/">Rack</a>, which is a standard API for connecting web servers to web application frameworks.</p>
<p>Line 4: We are modifying the Object class itself, so our changes will affect every object in the application.</p>
<p>Line 5: We are adding an instance method called &#8220;webapp&#8221; to every object.</p>
<p>Line 6: We are going to modify the class of just the instance whose &#8220;webapp&#8221; method was invoked. This may seem paradoxical: how can you modify its class without affecting all other instances of that class? The answer is that we are actually creating a unique, anonymous subclass, and the object whose &#8220;webapp&#8221; method was invoked now  becomes an instance of it. So when a caller invokes &#8220;webapp&#8221; on an object, we will modify just that instance.</p>
<p>Line 7: We are defining a method in our anonymous subclass named &#8220;call&#8221;, which takes a single argument, &#8220;env&#8221;. This is what the Rack API will invoke to ask our web application to handle each web server request.</p>
<p>Line 8: We are splitting the URL path on occurrences of &#8220;/&#8221; and storing the result into an array, and then filtering out all elements of that array that return true when the &#8220;empty?&#8221; method is called on them. Then, using multiple assignment, we take the first element of the array and assign it to the local variable &#8220;func&#8221;, and a new array containing the remaining elements to the local variable &#8220;attrs&#8221;.</p>
<p>Line 9: The Rack API expects a return value of an array containing 3 elements: an HTTP status code, a hash of HTTP response header names and values, and the response body. So here we respond with that array. &#8220;send(func, *attrs)&#8221; is an expression that calls &#8220;send&#8221; on self, which lets you invoke a method without specifying the name of the method nor the arguments to be passed to it until runtime. The method invoked is the one named in func, and the argument list passed to that method are taken from the attrs array. This is how the URL of the web request is mapped onto the API of the object that you made into a webapp.</p>
<p>Line 12: The return value from invoking the &#8220;webapp&#8221; method will be the same object that &#8220;webapp&#8221; was invoked on, which now has our special &#8220;call&#8221; method added.</p>
<p>Okay, so that&#8217;s it: a tiny Ruby web app microframework. Now we&#8217;re going to use it to expose an object!</p>
<p>Line 16: Start up the Mongrel web server listening on port 9292, and load up an empty array as a Rack webapp.</p>
<p>Lines 17-19 are a joke: because our webapp is an array, we have just implemented a horizontally scalable in-memory sharded NoSQL database, which is really the only suitable option for our expected ROFLScale needs.</p>
<p>Line 23: [].push(1) returns [1]; rack calls .to_s (convert to string) which returns &#8220;1&#8243; as the response body.<br />
Lines 24 and 25: Since the array is the webapp, the changes are persistent.<br />
Line 27: [1,2,3].to_a returns [1,2,3], and [1,2,3].to_s returns &#8220;123&#8243;.<br />
Line 29: Remove the last value, returning 3 and leaving [1,2] in the array.<br />
Line 30: Remove the first value, returning 1 and leaving [2] in the array.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2011/03/27/on-rubys-expressiveness-the-littlest-microframework-explained/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Princess and the Pea, as a Cucumber Feature</title>
		<link>http://www.pervasivecode.com/blog/2010/06/01/the-princess-and-the-pea-as-a-cucumber-feature/</link>
		<comments>http://www.pervasivecode.com/blog/2010/06/01/the-princess-and-the-pea-as-a-cucumber-feature/#comments</comments>
		<pubDate>Tue, 01 Jun 2010 20:00:41 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/?p=197</guid>
		<description><![CDATA[Kent Beck tweeted:

User story: &#8220;As a princess I want to confirm my royalty so I get bruised after sleeping on 40 mattresses over a pea&#8221;. Just tell real stories&#8221;

That sounded so much like a Cucumber feature that I decided to write it as one:

Feature: Physical Sensitivity
  In order to confirm my royalty
  As [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://twitter.com/kentbeck/">Kent Beck</a> tweeted:</p>
<blockquote><p>
User story: &#8220;As a princess I want to confirm my royalty so I get bruised after sleeping on 40 mattresses over a pea&#8221;. Just tell real stories&#8221;
</p></blockquote>
<p>That sounded so much like a <a href="http://cukes.info/">Cucumber</a> feature that I decided to write it as one:</p>
<pre>
Feature: Physical Sensitivity
  In order to confirm my royalty
  As a princess
  I want to be very delicate

  Scenario: 40 mattresses on a pea
  Given there is a pea on the bed
  And there is a stack of 20 mattresses on the pea
  And there is a stack of 20 featherbeds on the mattresses
  When I try to sleep on top of the stack of featherbeds
  Then I should not be able to sleep
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2010/06/01/the-princess-and-the-pea-as-a-cucumber-feature/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unix tip: kill -STOP and kill -CONT</title>
		<link>http://www.pervasivecode.com/blog/2010/04/03/unix-tip-kill-stop-and-kill-cont/</link>
		<comments>http://www.pervasivecode.com/blog/2010/04/03/unix-tip-kill-stop-and-kill-cont/#comments</comments>
		<pubDate>Sun, 04 Apr 2010 01:31:44 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/?p=194</guid>
		<description><![CDATA[Pretty much every Unix user knows about the kill command, and most know about &#8216;kill -KILL&#8217; aka &#8216;kill -9&#8242;.
But do you know about kill -STOP and kill -CONT?

I&#8217;m not sure of the exact mechanism (kernel vs. user process) but everything I&#8217;ve used it on on a Mac OS X machine has responded to it in [...]]]></description>
			<content:encoded><![CDATA[<p>Pretty much every Unix user knows about the kill command, and most know about &#8216;kill -KILL&#8217; aka &#8216;kill -9&#8242;.</p>
<p>But do you know about kill -STOP and kill -CONT?<br />
<span id="more-194"></span><br />
I&#8217;m not sure of the exact mechanism (kernel vs. user process) but everything I&#8217;ve used it on on a Mac OS X machine has responded to it in the same way. So you may find a process that doesn&#8217;t do this, but I haven&#8217;t found one.</p>
<p>Basically <code>kill -STOP 1234</code> will pause the process with pid 1234, and <code>kill -CONT 1234</code> will resume it. It&#8217;s as if you can sleep individual applications instead of your entire computer.</p>
<p>It&#8217;s simple, but you can probably imagine why this would be useful. Want to keep Firefox with 45 tabs open, but you&#8217;re not using it for a while and you want to save battery life? Pause it. Pretty much anything like &#8220;I don&#8217;t want to quit and then re-launch this but I wish it wasn&#8217;t using a bunch of CPU time while it idles&#8221; is a good candidate.</p>
<p>Remember that this means your app my time out when it is resumed, as if you had slept your laptop. So network connections it had open when you paused it may be broken when you resume it. So pausing Terminal.app with a bunch of open ssh connections to remote servers isn&#8217;t going to work too well.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2010/04/03/unix-tip-kill-stop-and-kill-cont/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Rails Migration Antipatterns and How To Fix Them</title>
		<link>http://www.pervasivecode.com/blog/2010/03/18/rails-migration-antipatterns-and-how-to-fix-them/</link>
		<comments>http://www.pervasivecode.com/blog/2010/03/18/rails-migration-antipatterns-and-how-to-fix-them/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 11:29:40 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[databases]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/?p=171</guid>
		<description><![CDATA[Migrations are one of the best features of Rails. Although some folks prefer pure SQL rather than Rails migration DSL, I don&#8217;t know of anyone who dislikes the idea of a versioned schema that can evolve in a controlled and repeatable fashion.
But because the concept of database migrations is such a powerful one, it&#8217;s tempting [...]]]></description>
			<content:encoded><![CDATA[<p>Migrations are one of the best features of Rails. Although some folks prefer pure SQL rather than Rails migration DSL, I don&#8217;t know of anyone who dislikes the idea of a versioned schema that can evolve in a controlled and repeatable fashion.</p>
<p>But because the concept of database migrations is such a powerful one, it&#8217;s tempting to jam any old change that affects the database into a new migration and run <code>rake db:migrate</code> to make it happen. I&#8217;ve been guilty of a bit of this in the past, and I&#8217;ve joined some projects that did other ugly things in migrations. In the process I&#8217;ve learned the hard way that there are some things you <b>must never do</b> in a migration or they will come back to haunt you later. Here they are.<br />
<span id="more-171"></span></p>
<h3>Antipattern: Require the Database to Exist Already</h3>
<p>In other words, the antipattern is for the first migration to depend on some tables and maybe even some data already being in the database.</p>
<p>I know that the original Rails blog video shows DHH using a MySQL admin tool to create the blog database interactively, but really you should be using migrations to create the schema programmatically from scratch.</p>
<p>If you&#8217;re already working on a project that didn&#8217;t do that, you can run <code>rake db:schema:dump</code> and look at db/schema.rb; it contains code that you can insert into a new migration to create the same schema in your development environment. If you&#8217;re using DB features that the design philosophy of ActiveRecord doesn&#8217;t agree with, such as triggers, and the schema.rb dump doesn&#8217;t include them (or if you just think the migration DSL is ugly and you like SQL DDL better), you can do a mysqldump / pg_dump / whateverdump and wrap a migration around the loading of that SQL file.</p>
<p>If you have a hybrid (you have to start with an old db dump and then migrate it so it becomes current), that&#8217;s gross, and you have a couple of options which are both pretty ugly. But they will work, and when you&#8217;re done the ugliness will be gone.</p>
<p>You could fight your way back to the oldest schema version by debugging the <code>self.down</code> methods and running <code>rake db:rollback</code> repeatedly until you can create a <code>00001_starting_db_schema.rb</code> migration, or you could just blow away all the migrations and use the highest schema version for a new migration that contains the output of a current <code>rake db:schema:dump</code>. It depends on how many copies of the database are out there with old schemas that would need to be brought up to date. Clearing out db/migrate and replacing it all with a single migration is cleaner, but if your production database is 5 migrations out of date you obviously can&#8217;t do that. But you could collapse it down to the one big-bang migration (as the oldest), plus the 5 pending schema changes. If you do it right, you can just deploy the new code and run <code>rake db:migrate</code> and everything will be fine. If not, well, you were testing it on a backup of the production database, right? :)</p>
<h3>Antipattern: Only Work Correctly With the Production Data</h3>
<p>What&#8217;s wrong with developers just making dumps of the production database and loading them locally?</p>
<p>First of all, it means that all schema changes have to start at the production database and work backwards to developers&#8217; sandboxed development environments. Hopefully this strikes you as a very stupid workflow.</p>
<p>Secondly, maybe your users don&#8217;t all want to get a message that says &#8220;test message foo bar sdfasdfasd bloopity bloop&#8221; when you&#8217;re testing your new alert system. Should you really be putting their data (passwords, contact info, etc.) at the mercy of your crummy new code?</p>
<p>You should be able to immediately generate an empty, clean database for development. <code>rake db:drop; rake db:create; rake db:migrate</code> should do this; <code>rake db:reset</code> should have the same result but should be faster since it doesn&#8217;t bother with each migration in sequence.</p>
<p>You should also be able to immediately generate any essential base data such as the initial admin user. The <a href="http://github.com/mbleigh/seed-fu">SeedFu</a> plugin does a good job here.</p>
<p>If you need some additional fake data to fiddle around with in your development environment, the <a href="http://github.com/ryanb/populator">Populator</a> gem is handy for mass-inserting a bunch of faux data, especially in conjunction with <a href="http://faker.rubyforge.org/">Faker</a>.</p>
<p>Note that the migrations should neither depend on nor contain actual data. They should just change the data model.</p>
<h3>Antipattern: Clean Up That Only Works on Production Data</h3>
<p>This is really a subset of the previous item but it&#8217;s worth considering as a special case.</p>
<p>If you want to fix some data that got slightly corrupted by some bad code that has been replaced, migrations aren&#8217;t a terrible way to accomplish that.</p>
<p>It&#8217;s not really what migrations are for, and a one-off rake task can do it just as well, but if you really want to, you can get away with it under one condition: you have to make your cleanup migration code succeed even if the database is empty (such as when a developer has just run <code>rake db:reset; rake db:migrate</code>).</p>
<h3>Antipattern: Load Data</h3>
<p>The <a href="http://github.com/ryanb/populator">populator</a> gem is good for initial, mandatory data. The <a href="http://github.com/notahat/machinist">machinist</a> gem is good for synthetic test data. Delete db/fixtures and everything in it. Fixtures are evil.</p>
<p>Wrap a rake task around the &#8220;get my development database ready&#8221; concept. This task should start with the &#8220;get my empty production database ready&#8221; task (or some subset of that which is appropriate for developer use).</p>
<p>If you need to load arbitrary data now and then, write an importer. Do this as a rake task, or a web UI to a bulk data importer feature. Better yet, make a web UI in your admin area which is just a wrapper around the rake task that bulk imports data. Then delegate the bulk importing to your customers so your admins can do real admin work. But don&#8217;t load data in a migration.</p>
<h3>Antipattern: Use Rails Models in the Migration</h3>
<p>Models evolve, but old migrations don&#8217;t change (nor should they). So when you wrote a migration that used a model, it used the old version of the model code. Then a year later the model has evolved, and the new validations on first_name and last_name fail because it used to be full_name, and that old migration that hasn&#8217;t changed has stopped working. It depended on something that did change, incompatibly.</p>
<p>For rockstar points, in your continuous integration environment you should run <code>rake db:drop; rake db:create; rake db:migrate</code> to make sure that this can never happen.</p>
<p>But if it has already happened, rip out the model code and replace it with Rails DSL code, with execute statements containing raw SQL code, or (if you feel like a Ruby rockstar) declare new, stripped down model classes inside your migration class that will act as stand-ins for the limited needs of the migration. See <a href="http://toolmantim.com/thoughts/migrating_with_models">Migrating with Models</a> for more on how to do this last trick.</p>
<h3>Conclusion</h3>
<p>You should always be able to do this in every Rails environment that your application has: <code>rake db:drop; rake db:create; rake db:migrate; rake db:reset</code></p>
<p>At this point you should then be able to run <code>rake db:test:prepare</code> and then <code>rake spec</code> or <code>rake test</code> or whatever and have it work.</p>
<p>If any part of that process fails, you are missing out on the benefits of using Rails migrations.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2010/03/18/rails-migration-antipatterns-and-how-to-fix-them/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Making Bundler 0.8.5 install Nokogiri on Leopard with a newish libxml</title>
		<link>http://www.pervasivecode.com/blog/2010/03/17/making-bundler-0-8-5-install-nokogiri-on-leopard-with-a-newish-libxml/</link>
		<comments>http://www.pervasivecode.com/blog/2010/03/17/making-bundler-0-8-5-install-nokogiri-on-leopard-with-a-newish-libxml/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 01:03:34 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[Mac]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/?p=166</guid>
		<description><![CDATA[Nokogiri on a standard installation of Leopard is complain-y about a couple of old libraries:
&#8220;HI.  You&#8217;re using libxml2 version 2.6.16 which is over 4 years old and has plenty of bugs.  We suggest that for maximum HTML/XML parsing pleasure, you upgrade your version of libxml2 and re-install nokogiri.  If you like using [...]]]></description>
			<content:encoded><![CDATA[<p>Nokogiri on a standard installation of Leopard is complain-y about a couple of old libraries:</p>
<p>&#8220;HI.  You&#8217;re using libxml2 version 2.6.16 which is over 4 years old and has plenty of bugs.  We suggest that for maximum HTML/XML parsing pleasure, you upgrade your version of libxml2 and re-install nokogiri.  If you like using libxml2 version 2.6.16, but don&#8217;t like this warning, please define the constant I_KNOW_I_AM_USING_AN_OLD_AND_BUGGY_VERSION_OF_LIBXML2 before requring nokogiri.&#8221;</p>
<p>Aaron Kalin <a href="http://martinisoftware.com/2009/07/31/nokogiri-on-leopard.html">figured out how to fix this if you&#8217;re installing nokogiri as a system gem</a>, but I want to use Bundler and keep my system gems down to the bare minimum. I figured out how to do this under Bundler 0.8.5.<br />
<span id="more-166"></span></p>
<p>The gems I have installed via plain old &#8220;gem install xxx&#8221; are bundler08 -v0.8.5, rake -v0.8.7, and ZenTest -v4.2.1. That&#8217;s it. Everything else is under vendor/bundler. I&#8217;m using <a href="http://rvm.beginrescueend.com/">RVM</a> and REE 1.8.7 2009.10 as described in <a href="http://www.pervasivecode.com/blog/2010/03/16/using-rvm-to-install-ree-1-8-7-2009-10/">my previous post</a>.</p>
<p>Here is a quick summary of Aaron&#8217;s blog post; this will update your libxml and libxslt libraries to reasonably recent versions. (Be my guest if you want to use libxml 2.7.7 and libxslt 1.1.26, which are current as of today, but I didn&#8217;t test those myself.)</p>
<pre>
mkdir -p ~/Downloads/XML
cd ~/Downloads/XML
curl -O ftp://xmlsoft.org/libxml2/libxml2-2.7.3.tar.gz
curl -O ftp://xmlsoft.org/libxml2/libxslt-1.1.24.tar.gz
tar xzf libxml2-2.7.3.tar.gz
tar xzf libxslt-1.1.24.tar.gz
cd ~/Downloads/XML/libxml2-2.7.3
./configure
nice make
sudo make install
cd ~/Downloads/XML/libxslt-1.1.24
./configure --with-libxml-prefix=/usr/local --with-libxml-include-prefix=/usr/local/include --with-libxml-libs-prefix=/usr/local/lib
nice make
sudo make install
</pre>
<p>Now make this YAML file and call it bundler_build_options_macosx_leopard.yml and put it in your RAILS_ROOT:</p>
<pre>
nokogiri:
  xml2-include: /usr/local/include/libxml2
  xml2-lib: /usr/local/lib
</pre>
<p>Then, to build nokogiri so that it uses the new libs you just installed:</p>
<pre>
gem bundle --build-options bundler_build_options_macosx_leopard.yml
</pre>
<p>You should now have nokogiri installed under vendor/bundler/ruby/1.8/gems, and when you run your app it should not complain about the version of libxml2 anymore.</p>
<p><b>Update:</b> Bundler 1.0.0.beta.10 allows this too. See my <a href="http://www.pervasivecode.com/blog/2010/07/25/making-bundler-1-0-0-beta-10-install-nokogiri-on-leopard-with-a-newish-libxml/">other post</a> that shows how to do it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2010/03/17/making-bundler-0-8-5-install-nokogiri-on-leopard-with-a-newish-libxml/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>First public release of my AvantiConveniences gem</title>
		<link>http://www.pervasivecode.com/blog/2009/03/21/first-public-release-of-my-avanticonveniences-gem/</link>
		<comments>http://www.pervasivecode.com/blog/2009/03/21/first-public-release-of-my-avanticonveniences-gem/#comments</comments>
		<pubDate>Sun, 22 Mar 2009 02:12:50 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/?p=87</guid>
		<description><![CDATA[From the README:
AvantiConveniences is a set of convenience code for Ruby on Rails applications.

ArgChecks helps you implement simple sanity-checking of arguments, like
permanent assertions or a poor man&#8217;s Design by Contract facility, so you can
write code that will Fail Fast (see http://c2.com/cgi/wiki?FailFast).
HashExtensions currently just adds the Hash#rekey method.
StringExtensions provides String quoting (not escaping) with single quotes,
double [...]]]></description>
			<content:encoded><![CDATA[<p>From the README:</p>
<p>AvantiConveniences is a set of convenience code for Ruby on Rails applications.</p>
<p><span id="more-87"></span></p>
<p>ArgChecks helps you implement simple sanity-checking of arguments, like<br />
permanent assertions or a poor man&#8217;s Design by Contract facility, so you can<br />
write code that will Fail Fast (see <a href="http://c2.com/cgi/wiki?FailFast">http://c2.com/cgi/wiki?FailFast</a>).</p>
<p>HashExtensions currently just adds the Hash#rekey method.</p>
<p>StringExtensions provides String quoting (not escaping) with single quotes,<br />
double quotes, or a caller-specified quoting character, and a String#dehumanize<br />
method to do the reverse of the String#humanize method provided by ActiveSupport.</p>
<p>TextFormatter provides methods for hyphenating words for word-wrapping.</p>
<p>URIExtensions provides URI::Generic#query_from_hash, which will create a URI<br />
query string from a Hash.</p>
<p>INSTALL:<br />
If you haven&#8217;t done this before:<br />
<code>gem sources -a http://gems.github.com</code></p>
<p>Then:<br />
<code>sudo gem install JamieFlournoy-AvantiConveniences</code></p>
<p>See also: the <a href="http://github.com/JamieFlournoy/avanticonveniences/tree/master">AvantiConveniences GitHub project page</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2009/03/21/first-public-release-of-my-avanticonveniences-gem/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Things I had to fix for Rails 2.2.2</title>
		<link>http://www.pervasivecode.com/blog/2008/11/29/things-i-had-to-fix-for-rails-222/</link>
		<comments>http://www.pervasivecode.com/blog/2008/11/29/things-i-had-to-fix-for-rails-222/#comments</comments>
		<pubDate>Sun, 30 Nov 2008 01:57:06 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/?p=85</guid>
		<description><![CDATA[The new features in Ruby on Rails 2.2.2 have been well documented, and I&#8217;m looking forward to using several of them on WhatYouAte.com. If you&#8217;re reading this you probably are too.
However, if you&#8217;re upgrading an existing project and you&#8217;re sticking with official releases (as opposed to edge Rails) like I am, your code probably needs [...]]]></description>
			<content:encoded><![CDATA[<p>The new features in Ruby on Rails 2.2.2 have been <a href="http://www.rubyinside.com/rails-22-released-27-links-and-resources-to-get-you-going-1354.html">well documented</a>, and I&#8217;m looking forward to using several of them on <a href="http://www.whatyouate.com/">WhatYouAte.com</a>. If you&#8217;re reading this you probably are too.</p>
<p>However, if you&#8217;re upgrading an existing project and you&#8217;re sticking with official releases (as opposed to edge Rails) like I am, your code probably needs some tweaking to work with Rails 2.2.2. Mine certainly did. Although there were a lot of failed tests with ugly stacktraces, there were only a few API changes in Rails that needed to be accomodated to fix them all. Here&#8217;s a list of the changes that broke my app, and what I had to do to get it working again.<br />
<span id="more-85"></span></p>
<p><code>TextHelper.truncate</code> no longer allows you to supply the length parameter as a second argument. You have to use <code>truncate(somestring, :length => 20)</code> instead of <code>truncate(somestring, 20)</code>.</p>
<p>I was getting an error that looked like this:</p>
<pre>ActionView::TemplateError: wrong number of arguments (3 for 1)</pre>
<p>The line in question is:</p>
<pre>
&lt;%= render(:partial => 'layouts/header') %&gt;
</pre>
<p>The problem is that the simply_helpful plugin&#8217;s behavior is now built-in; just delete the whole vendor/plugins/simply_helpful directory if you were using it, and any existing code that depends on simply_helpful&#8217;s API should work again.</p>
<p>I was using the <a href="http://weblog.jamisbuck.org/2007/2/2/introducing-tztime">tztime</a> and <a href="http://agilewebdevelopment.com/plugins/tzinfo_timezone">tzinfo_timezone</a> plugins, which are no longer needed now that time zone support is available via Time.zone in Rails 2.2. Delete the plugins, upgrade the tzinfo gem to 0.3.12 or uninstall any older version of it, and search for TzTime instances in your code and replace any of the occurences of Time.at(some_tztime_variable) that you had been using. TzInfo is still useful in cases such as this:</p>
<pre>TZInfo::Timezone.get('UTC')</pre>
<p>But since you can now embed the time zone information in a Time instance, you don&#8217;t need TzTime objects anymore.</p>
<p>I was using a nice hack from Technoweenie, to allow me to validate forms using the familiar ActiveRecord model validations API even if those forms were not backed by a database table (sometimes the UI just doesn&#8217;t look anything like the data model, y&#8217;know?). It broke, and I was unable to find any solutions from anyone else, so I wrote my own: <a href="http://www.pervasivecode.com/blog/2008/11/29/ephemeralmodel-for-rails-222-form-validation-without-a-db-table/">EphemeralModel, for Rails 2.2.2 form validation without a DB table</a>.</p>
<p>I was using <code>ActiveRecord::Errors.default_error_messages[:invalid]</code> in a few model validators, which is now deprecated because it&#8217;s not internationalized. The new way to ask for the same string in the currently configured language is: <code>I18n.t(:invalid, :scope => 'activerecord.errors.messages')</code></p>
<p>Finally, the app wouldn&#8217;t start because it wants a <code>:secret</code> option to <code>config.action_controller.session</code> in <code>config/environment.rb</code>. I came up with something sufficiently random and now it&#8217;s fine.</p>
<p>I&#8217;d just like to make one last comment about this: having thorough automated tests is a huge time and sanity saver during this process. If you&#8217;re not close to 100% test coverage on your current Rails project, then your house is on fire and you need to address that immediately. Even as I write this in late 2008, I&#8217;m talking to prospective clients about contracting work, and some of them don&#8217;t do automated testing at all(!). Unless you&#8217;re in a mad dash for a demo that will save the company from financial collapse, having automated tests that verify that your code works should be priority #1. Upgrades can wait.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2008/11/29/things-i-had-to-fix-for-rails-222/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>EphemeralModel, for Rails 2.2.2 form validation without a DB table</title>
		<link>http://www.pervasivecode.com/blog/2008/11/29/ephemeralmodel-for-rails-222-form-validation-without-a-db-table/</link>
		<comments>http://www.pervasivecode.com/blog/2008/11/29/ephemeralmodel-for-rails-222-form-validation-without-a-db-table/#comments</comments>
		<pubDate>Sat, 29 Nov 2008 23:13:05 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/?p=84</guid>
		<description><![CDATA[I recently upgraded WhatYouAte.com to Rails 2.2.2. I had been using advice from the Rails Wiki&#8217;s HowToUseValidationsWithoutExtendingActiveRecord page. I was using a class based on the RailsWeenie code (that site is down now) and it stopped working. Here&#8217;s a new replacement hack that works almost identically.


# Usage: in the faux-model class, include EphemeralModel and ActiveRecord::Validations
# [...]]]></description>
			<content:encoded><![CDATA[<p>I recently upgraded <a href="http://www.whatyouate.com/">WhatYouAte.com</a> to Rails 2.2.2. I had been using advice from the Rails Wiki&#8217;s <a href="http://wiki.rubyonrails.com/rails/pages/HowToUseValidationsWithoutExtendingActiveRecord">HowToUseValidationsWithoutExtendingActiveRecord</a> page. I was using a class based on the RailsWeenie code (that site is down now) and it stopped working. Here&#8217;s a new replacement hack that works almost identically.<br />
<span id="more-84"></span></p>
<pre>
# Usage: in the faux-model class, include EphemeralModel and ActiveRecord::Validations
# Then just say "column :foo" to set up a property called 'foo' for validation
module EphemeralModel
    # Stubbing methods from ActiveRecord::Base that ActiveRecord::Validations may call
    def EphemeralModel.included(mod)
        def mod.self_and_descendents_from_active_record; [self]; end
        def mod.human_attribute_name(arg); arg.to_s; end
        def mod.human_name; self.name; end
        def mod.column(attr_name)
            attr_name = attr_name.to_s
            column_names.push(attr_name) unless column_names.include?(attr_name)
            attr_accessor attr_name
        end
        mod.module_eval do
            def self.column_names
                cn = self.instance_variable_get(:@column_names)
                if cn.nil?
                    cn = self.instance_variable_set(:@column_names, [])
                end
                cn
            end
        end
    end
    def save; end
    def save!; end
    def update_attribute; end
    def new_record?; end

    def initialize(initial_attributes = nil)
        initial_attributes.each{|k,v| instance_variable_set("@#{k}".to_sym, v)} if initial_attributes
    end

    def attributes
        @attributes = {}
        self.class.column_names.each do |colname|
            @attributes[colname]= instance_variable_get("@#{colname}".to_sym)
        end
        @attributes
    end

    def attribute_names
        self.class.column_names
    end

    def [](name); attributes[name.to_s]; end

    def []=(name, value)
        instance_variable_set("@#{name}".to_sym, value)
        # print "set #{name} to " + instance_variable_get("@#{name}".to_sym) + ".\n" # DEBUG
    end
end
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2008/11/29/ephemeralmodel-for-rails-222-form-validation-without-a-db-table/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

