<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Talk Like A Duck: Category rails</title>
    <link>http://talklikeaduck.denhaven2.com/articles/category/rails</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>In Ruby, it's not the dog, it's the tricks!</description>
    <item>
      <title>Rails 2.1RC1 and the Enhanced Migrations Plugin</title>
      <description>At work, we use the Revolution on Rails &lt;a href="http://revolutiononrails.blogspot.com/2007/02/plugin-release-enhanced-rails.html"&gt;enhanced_migrations plugin&lt;/a&gt;.
&lt;p&gt;Yesterday I started the work of moving the app to Rails 2.1RC1.&lt;/p&gt;
&lt;p&gt;With version 2.1, Rails is moving to timestamp based migration names, instead of the traditional sequence numbering.  This effectively does the same thing as the enhanced_migrations plugin, but the implementation is slightly different, more on this in a bit.&lt;/p&gt;
&lt;p&gt;After installing or &lt;a href="http://railscasts.com/episodes/105"&gt;&lt;strong&gt;git&lt;/strong&gt;ting&lt;/a&gt; Rails 2.1 into my vendor/rails directory, I ran the rake task to run all of our tests and specs.&lt;/p&gt;
&lt;p&gt;Early on this task does a rake db:migrate, which attempted to run &lt;span class="caps"&gt;ALL&lt;/span&gt; of our migrations since Rails 2.1 looks in a different place to determine if a migration has been already run.&lt;/p&gt;
&lt;h2&gt;Implementation Differences&lt;/h2&gt;
&lt;p&gt;Until now Rails has tracked migrations using a single row, single column table in each database called schema_version. This table holds the number of the latest migration which has been run.&lt;/p&gt;
&lt;p&gt;The enhanced_migrations plugin uses a w table, named migrations_info, with one row for each migration which has been applied to the database.  The key used for this table is the migration number which the migration generator sets to Time.now.to_i. The only column besides the id is created_at. So the enhanced_migration plugin captures the time at which the migration was run against the database, which is different than the time it was generated.&lt;/p&gt;
&lt;p&gt;Rails 2.1 uses a table called schema_migrations, which also has a row per applied migration, but this table has a string key whose value is the migration number, in Rails 2.1, the migration number is also a utc timestamp but is a string in the the form &amp;#8220;yyyymmddhhmmss&amp;#8221;&lt;/p&gt;
&lt;p&gt;Blake Watters and I noticed that the timestamp forms can&amp;#8217;t overlap since enhanced migrations uses a 10-digit timestamp and Rails 2.1 uses a 14-digit one.  So we wrote a new migration 1_convert_migration_schema_to_rails21.rb&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;ConvertMigrationSchemaToRails21&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ActiveRecord&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Migration&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.up&lt;/span&gt;
    &lt;span class="ident"&gt;values&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;select_values&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;select id from migrations_info&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
    &lt;span class="ident"&gt;values&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;value&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;execute&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;replace into schema_migrations VALUES('&lt;span class="expr"&gt;#{id}&lt;/span&gt;')&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)}&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.down&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We then ran rake db:migrate:up &lt;span class="caps"&gt;VERSION&lt;/span&gt;=1&lt;/p&gt;
&lt;p&gt;This populated schema_migrations so that it now &amp;#8220;knew&amp;#8221; that all of our current migrations had already been run.&lt;/p&gt;
&lt;h2&gt;Not quite there&lt;/h2&gt;
&lt;p&gt;For many current users of enhanced_migrations, this might be enough. In our case it wasn&amp;#8217;t.  When I tried to run rake test again, it blew up in the prerequisite task db:test:clone_structure, complaining about bad sql syntax on an insert statement.  The insert statement which was logged looked perfectly fine. It was the second of a series of statements inserting rows into our new friend, the schema_migrations table.
The &lt;span class="caps"&gt;SQL&lt;/span&gt; in question looked like this:&lt;/p&gt; 
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;INSERT INTO schema_migrations (version) VALUES ('0');
INSERT INTO schema_migrations (version) VALUES ('1');&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Followed by a similar line for each of our 500 or so migrations.&lt;/p&gt;
&lt;p&gt;The rake task for db:test:clone structure, basically breaks the file db/development_structure.sql into chunks delimited by empty lines, and &amp;#8216;plays&amp;#8217; them against the test database using ActiveRecord::Base.connection.execute.  After some head scratching over why this seemingly legal &lt;span class="caps"&gt;SQL&lt;/span&gt; was being rejected, it occurred to us that it was trying to execute all of these lines as one sql statement.&lt;/p&gt;
&lt;p&gt;So the next step was to figure out how to get db/development_structure.sql into a form which would cause the task to execute each sql statement individually.  This was a simple patch to rails, which once made, allowed rake db:test:prepare to run successfully, which in turn allowed me to actually move on to running the test suite and working out the problems caused by the changes to rails.&lt;/p&gt;
&lt;p&gt;I opened up &lt;a href="http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/201-process-schema_migrations-inserts-individually-during-rake-db-test-clone_structure#ticket-201-2"&gt;ticket #201 on the Rails lighthouse&lt;/a&gt; which contains the Rails patch.&lt;/p&gt;</description>
      <pubDate>Thu, 15 May 2008 15:24:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:1c1affbf-7dca-4705-9248-099bdee52f3e</guid>
      <author>Rick DeNatale</author>
      <link>http://talklikeaduck.denhaven2.com/articles/2008/05/15/rails-2-1rc1-and-the-enhanced-migrations-plugin</link>
      <category>rails</category>
      <category>migrations</category>
      <category>rails2.1</category>
      <trackback:ping>http://talklikeaduck.denhaven2.com/articles/trackback/498</trackback:ping>
    </item>
    <item>
      <title>It's About Time!</title>
      <description>&lt;p&gt;The third edition of &lt;a href="http://www.pragprog.com/titles/rails3/agile-web-development-with-rails-third-edition"&gt;Agile Web Development With Rails&lt;/a&gt; is now in Beta.&lt;/p&gt;


	&lt;p&gt;Sam Ruby has become the third author, along with Dave Thomas and &lt;span class="caps"&gt;DHH&lt;/span&gt;.  According to PragDave, Sam has converted the Depot App tutorial to be compatible with Rails 2, and the rest of the book is also being revised.&lt;/p&gt;</description>
      <pubDate>Wed, 23 Apr 2008 16:17:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:a6e88ea3-1314-4488-b440-615d088b330d</guid>
      <author>Rick DeNatale</author>
      <link>http://talklikeaduck.denhaven2.com/articles/2008/04/23/its-about-time</link>
      <category>rails</category>
      <trackback:ping>http://talklikeaduck.denhaven2.com/articles/trackback/494</trackback:ping>
    </item>
    <item>
      <title>Rails Integration Test File Upload Plugin</title>
      <description>&lt;p&gt;Some time ago, I wrote a rails patch which allows http file uploading in integration tests.&lt;/p&gt;


You just use the same TestUploadedFile class used in functional tests or controller specs if you&amp;#8217;re an RSpec&amp;#8217;er.  So you can do something like.
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;    post '/upload' :file =&amp;gt; TestUploadedFile(&amp;quot;/path/to/blah.txt&amp;quot;)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;The patch detects a TestUploaded file amongst the parameters, and converts the request into a proper multi-part request.&lt;/p&gt;


	&lt;p&gt;It will work for both posts and updates.&lt;/p&gt;


	&lt;p&gt;If you&amp;#8217;re running edge rails you&amp;#8217;ve already got this. But many have asked for a version for earlier rails versions.  At work, I&amp;#8217;ve been working on an RSpec story which requires file uploading, and we&amp;#8217;re using the 2.0.2 gem version of Rails for deployment purposes, so I whipped up a little plugin which patches 2.0.2 Rails with the changes from &lt;a href="http://dev.rubyonrails.org/changeset/8978"&gt;Rails changeset 8978&lt;/a&gt;.  The plugin checks the rails version and throws an exception if it&amp;#8217;s anything other than &amp;#8220;2.0.2&amp;#8221; since I haven&amp;#8217;t tried this with anything earlier, and it&amp;#8217;s not necessary for anything newer.&lt;/p&gt;


	&lt;p&gt;You can get it from git hub at &lt;a href="git://github.com/rubyredrick/integration_upload_plugin.git"&gt;git://github.com/rubyredrick/integration_upload_plugin.git&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;This also marks the first time I&amp;#8217;ve used git for anything but gitting Rubinius.&lt;/p&gt;</description>
      <pubDate>Fri, 18 Apr 2008 18:07:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:7bc970c8-4f95-4be1-aa4a-14e69a6015a4</guid>
      <author>Rick DeNatale</author>
      <link>http://talklikeaduck.denhaven2.com/articles/2008/04/18/rails-integration-test-file-upload-plugin</link>
      <category>rails</category>
      <category>integration_upload_plugin</category>
      <category>open_source_contributions</category>
      <trackback:ping>http://talklikeaduck.denhaven2.com/articles/trackback/493</trackback:ping>
    </item>
    <item>
      <title>RSpec Anti-Pattern - Don't Set @controller yourself</title>
      <description>&lt;p&gt;I was adding to an existing controller today at work and I was stumped because one of the examples in its controller spec was failing due to an exception thrown while rendering a view.&lt;/p&gt;
&lt;p&gt;Normally RSpec controller tests, which are usually used to specify controller logic, bypass view rendering unless you specifically use the integrate_views method in the example group. The idea is that you should use view specs to specify the logic and output of views.&lt;/p&gt;
&lt;p&gt;Since I was working in existing code, which pre-existed my being here, I&amp;#8217;d followed some of the existing example groups in the file.  These would typically look something like this:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;describe&lt;/span&gt; &lt;span class="constant"&gt;HobbitController&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;doing something&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;

    &lt;span class="ident"&gt;before&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:each&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
      &lt;span class="attribute"&gt;@controller&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;HobbitController&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;
      &lt;span class="comment"&gt;#.. more setup stubbing etc.&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

   &lt;span class="comment"&gt;#examples&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I finally realized that that first line in the before block was clobbering RSpecs ability to control whether or not views should be rendered.  RSpec actually creates the controller instance variable for you, and extends it with a module which overrides the render method to allow integrate_views to control the rendering while allowing the expect_render expectation to work whether or not rendering actually happens.&lt;/p&gt;
&lt;p&gt;So I&amp;#8217;ve got a new task to clean up all the other controller specs.&lt;/p&gt;</description>
      <pubDate>Wed, 26 Mar 2008 17:30:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:8ed18916-a083-41a8-9d17-75820dc1c273</guid>
      <author>Rick DeNatale</author>
      <link>http://talklikeaduck.denhaven2.com/articles/2008/03/26/rspec-anti-pattern-dont-set-controller-yourself</link>
      <category>rails</category>
      <category>Rspec</category>
      <trackback:ping>http://talklikeaduck.denhaven2.com/articles/trackback/492</trackback:ping>
    </item>
    <item>
      <title>Validating RSS Feeds with RSpec</title>
      <description>&lt;p&gt;One of my current Rails projects involves generating an RSS feed.  While I was working on this the other night, it seemed to be working, so I deployed it to the staging server. Everything looked fine. If I fetched it with Firefox, the browser offered to let me subscribe to the feed with Google Reader, and if I used Safari I'd see a nice view of the feed just like I expected.&lt;/p&gt;
&lt;p&gt;So I sent a note via our campfire to check it out, and a colleague replied that &lt;strong&gt;his&lt;/strong&gt; Safari was saying that it was in an invalid format.&lt;/p&gt;
&lt;p&gt;So I went to the &lt;a href="http://validator.w3.org/feed/"&gt;W3 RSS Feed Validation Service&lt;/a&gt; and worked through the validation issues, after which his browser was as happy as mine.&lt;/p&gt;
&lt;p&gt;Of course, having been through that, I wanted to make sure that RSS validation was covered in the specs for the project.&lt;/p&gt;
&lt;p&gt;I went looking for an existing RSpec matcher, and found &lt;a href="http://www.anodyne.ca/2007/09/28/rspec-custom-matchers-and-be_valid_xhtml/"&gt;a matcher to validate XHTML&lt;/a&gt; but nothing for RSS.&lt;/p&gt;
&lt;p&gt;I then found the &lt;a href="http://feedvalidator.rubyforge.org/"&gt;feedvalidator gem&lt;/a&gt; which provides a Ruby interface to the SOAP interface to the W3 feed validator.  You would think that W3 would be providing a REST interface!  The gem already provides assertions for use with Test::Unit, so I just built an RSpec matcher.&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;BeValidFeed&lt;/span&gt;
  &lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;feed_validator&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
  &lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;tmpdir&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
  &lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;md5&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;matches?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;response&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="constant"&gt;true&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;validity_checks_disabled?&lt;/span&gt;
    &lt;span class="ident"&gt;v&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;W3C&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;FeedValidator&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
    &lt;span class="ident"&gt;fragment&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;response&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;body&lt;/span&gt;
    &lt;span class="ident"&gt;filename&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt; &lt;span class="constant"&gt;Dir&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="ident"&gt;tmpdir&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;feed.&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="constant"&gt;MD5&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;md5&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;fragment&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt;
    &lt;span class="keyword"&gt;begin&lt;/span&gt;
      &lt;span class="ident"&gt;response&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;open&lt;/span&gt; &lt;span class="ident"&gt;filename&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;f&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="constant"&gt;Marshal&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;load&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;f&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="ident"&gt;v&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;parse&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;response&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  	&lt;span class="keyword"&gt;rescue&lt;/span&gt;   
      &lt;span class="keyword"&gt;unless&lt;/span&gt; &lt;span class="ident"&gt;v&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;validate_data&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;fragment&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
        &lt;span class="attribute"&gt;@failure&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; could not access w3 validator to validate the feed.&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
        &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="constant"&gt;false&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;open&lt;/span&gt; &lt;span class="ident"&gt;filename&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;w+&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;f&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="constant"&gt;Marshal&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;dump&lt;/span&gt; &lt;span class="ident"&gt;v&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;response&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;f&lt;/span&gt; &lt;span class="keyword"&gt;end&lt;/span&gt;
  	&lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="ident"&gt;v&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;valid?&lt;/span&gt;   
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;description&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;be valid xhtml&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;failure_message&lt;/span&gt;
   &lt;span class="attribute"&gt;@failure&lt;/span&gt; &lt;span class="punct"&gt;||&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; expected xhtml to be valid, but validation produced these errors:&lt;span class="escape"&gt;\n&lt;/span&gt; &lt;span class="expr"&gt;#{@message}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;negative_failure_message&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; expected to not be valid, but was (missing validation?)&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="ident"&gt;private&lt;/span&gt;
    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;validity_checks_disabled?&lt;/span&gt;
      &lt;span class="constant"&gt;ENV&lt;/span&gt;&lt;span class="punct"&gt;[&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;NONET&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;]&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;true&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;be_valid_feed&lt;/span&gt;
  &lt;span class="constant"&gt;BeValidFeed&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I saved this as spec/be_valid_feed.rb&lt;/p&gt;

&lt;p&gt;And in a view or controller spec, I can include this file, and test a response with:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&lt;notextile&gt;response.should be_valid_feed&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you use this in a controller spec, you will need to tell RSpec to integrate_views, or you won't have much of a feed to check.  If you use nested example groups, integrate_views needs to be inside the inner group.&lt;/p&gt;

</description>
      <pubDate>Fri, 08 Feb 2008 10:38:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:0b27f7ba-403b-48c5-9833-2fd2b5d73fa8</guid>
      <author>Rick DeNatale</author>
      <link>http://talklikeaduck.denhaven2.com/articles/2008/02/08/validating-rss-feeds-with-rspec</link>
      <category>ruby</category>
      <category>best_practices</category>
      <category>rails</category>
      <category>Rspec</category>
      <category>rss</category>
      <category>validation</category>
      <trackback:ping>http://talklikeaduck.denhaven2.com/articles/trackback/486</trackback:ping>
    </item>
    <item>
      <title>Why I Don't Mind Using RSpec - In Fact I've Come to Love It.</title>
      <description>&lt;p&gt;About a year ago when I first encountered RSpec, I thought that the idea sounded good, but I was concerned about how much the implementation at that time pushed new methods into Object and Kernel. It felt to me as though it could interfere with the code being specified/tested. Indeed back then there were some problems when RSpec and Rails bumped heads over the use of certain Ruby metaprogramming techniques.  I&amp;#8217;d been a &lt;span class="caps"&gt;TDD&lt;/span&gt; user advocate for many years, heck I was there right after Kent Beck, &amp;#8220;test-infected&amp;#8221; Erich Gamma and sat in on some of their early pairing sessions during an annual &lt;span class="caps"&gt;OTI&lt;/span&gt; company technical conference at Montebello in Quebec, when JUnit was in it&amp;#8217;s infancy.  The cleaner language of RSpec did have it&amp;#8217;s attractions, particularly in trying to get across the idea to newcomers that &lt;span class="caps"&gt;TDD&lt;/span&gt; was really writing mini-specifications rather than tests, which helps put them in the right mindset, but for those of us who had already crossed that paradigm shift, or been born on the right side of it, it didn&amp;#8217;t seem so important.&lt;/p&gt;


	&lt;p&gt;Since then the RSpec implementation has matured, and after talking to David Chelimsky and Dave Astels at RubyConf, I decided to give it another look, and, armed with a new perspective on the use of mocks and stubs to isolate specifications and tests in &lt;span class="caps"&gt;BDD&lt;/span&gt;/TDD, I quickly became a convert.  I still use other frameworks as external requirements dictate, but RSpec has become my first choice.&lt;/p&gt;


	&lt;p&gt;These days, though the choice of testing/specification framework seems to have become one of those religious issues which divide the community, almost as much as emacs vs. vim vs. textmate.  I run into people all the time who reject RSpec because it&amp;#8217;s &amp;#8220;too magical!&amp;#8221;  Although I&amp;#8217;ve never been able to get them to expand on that thought. Perhaps it&amp;#8217;s based on the kind of concerns I had about it at first, maybe it&amp;#8217;s something else.  I&amp;#8217;d love to have it explained.&lt;/p&gt;


	&lt;p&gt;And like advocates do, other arguments get expressed, some of which don&amp;#8217;t get the scrutiny they deserve.&lt;/p&gt;


	&lt;p&gt;For example, a few days ago Rob Sanheim, someone I know and respect, wrote about why &lt;a href="http://robsanheim.com/2008/01/25/why-i-use-testspec-over-rspec/"&gt;he eschews RSpec for Test::Spec&lt;/a&gt;. His basic, quite brief argument is that because RSpec is 10 times bigger in terms of lines of code than Test::Spec it must be worse.&lt;/p&gt;


&lt;h2&gt;How to Lie with Statistics&lt;/h2&gt;
Nice statistics, but back when I was in college, one of the must-read books was &amp;#8220;How to Lie with Statistics&amp;#8221;.  Given the right pick of statistics you can prove anything.

	&lt;p&gt;First off I think that Rob was unfair to lump the lib and spec or test directories together.  Even if you might believe that code bulk is bad, I think that it&amp;#8217;s reasonable to think of the code bulk in the implementation to be like &amp;#8216;bad cholesterol&amp;#8217;, and test-code which verifies that implementation as &amp;#8216;good cholesterol.&amp;#8217;  Most of you are probably too young to be concerned about it yet, but my doctors tell me that a high &lt;span class="caps"&gt;HDL&lt;/span&gt;/LDL ratio is more important than an absolute &lt;span class="caps"&gt;HDL&lt;/span&gt;+LDL.  The theory at least is that the &lt;span class="caps"&gt;HDL&lt;/span&gt; helps sweep the &lt;span class="caps"&gt;LDL&lt;/span&gt; out of the vessels, kind of like a good test suite keeps code under control.&lt;/p&gt;


	&lt;p&gt;Here are the numbers I get running sloccount on the latest RSpec and test/unit gems:&lt;/p&gt;


	&lt;table style="border:1px solid black; align:right;"&gt;
		&lt;tr&gt;
			&lt;th&gt;Framework &lt;/th&gt;
			&lt;th&gt;lib &lt;/th&gt;
			&lt;th&gt;spec/test&lt;/th&gt;
			&lt;th&gt;test/code ratio &lt;/th&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; Rspec &lt;/td&gt;
			&lt;td&gt; 5473 &lt;/td&gt;
			&lt;td&gt;10108  &lt;/td&gt;
			&lt;td&gt; 1.8 &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; Test::Spec &lt;/td&gt;
			&lt;td&gt; 275 &lt;/td&gt;
			&lt;td&gt; 879 &lt;/td&gt;
			&lt;td&gt; 3.2 &lt;/td&gt;
		&lt;/tr&gt;
	&lt;/table&gt;




	&lt;p&gt;So at first blush it looks bad for RSpec, Test::Spec even tests itself more thoroughly!&lt;/p&gt;


	&lt;p&gt;The real problem with Rob&amp;#8217;s post is that he&amp;#8217;s comparing Apple seeds with Apples.  Of course Test::Spec is considerably smaller than RSpec, it&amp;#8217;s a bump on Test::Unit to add the new assertion style.  So we need to at least add Test::Unit&amp;#8217;s numbers&lt;/p&gt;


	&lt;table style="border:1px solid black; align:right;"&gt;
		&lt;tr&gt;
			&lt;th&gt;Framework &lt;/th&gt;
			&lt;th&gt;lib &lt;/th&gt;
			&lt;th&gt;spec/test&lt;/th&gt;
			&lt;th&gt;test/code ratio &lt;/th&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; Test:Unit &lt;/td&gt;
			&lt;td&gt; 2741 &lt;/td&gt;
			&lt;td&gt; 0 &lt;/td&gt;
			&lt;td&gt; 0 &lt;/td&gt;
		&lt;/tr&gt;
	&lt;/table&gt;




	&lt;p&gt;Now I&amp;#8217;m sure that Nathaniel &amp;#8220;ate his own dog food&amp;#8221; when he developed Test::Unit, and Ryan is continuing to dine on it, now that he&amp;#8217;s taken over its maintenance, but that dog food apparently doesn&amp;#8217;t leave home.  Now if we look at the combination of Test::Unit and Test::Spec the comparison looks like this:&lt;/p&gt;


	&lt;table style="border:1px solid black; align:right;"&gt;
		&lt;tr&gt;
			&lt;th&gt;Framework &lt;/th&gt;
			&lt;th&gt;lib &lt;/th&gt;
			&lt;th&gt;spec/test&lt;/th&gt;
			&lt;th&gt;test/code ratio &lt;/th&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; Rspec &lt;/td&gt;
			&lt;td&gt; 5473 &lt;/td&gt;
			&lt;td&gt;10108  &lt;/td&gt;
			&lt;td&gt; 1.8 &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; TU+TS &lt;/td&gt;
			&lt;td&gt; 2713 &lt;/td&gt;
			&lt;td&gt; 879 &lt;/td&gt;
			&lt;td&gt; 0.3 &lt;/td&gt;
		&lt;/tr&gt;
	&lt;/table&gt;




	&lt;p&gt;So RSpec looks a little better, particularly when it comes to eating it&amp;#8217;s own dog food.&lt;/p&gt;


	&lt;p&gt;But, as that Billy Mays guy on the Infomercials is wont to say, &amp;#8220;Wait! There&amp;#8217;s more!&amp;#8221;.&lt;/p&gt;


	&lt;p&gt;RSpec also includes a built-in mocking framework, now with the &amp;#8216;traditional&amp;#8217; choice you need to throw in your choice of mock framework, here&amp;#8217;s are the stats for Flexmock and Mocha&lt;/p&gt;


	&lt;table style="border:1px solid black; align:right;"&gt;
		&lt;tr&gt;
			&lt;th&gt;Framework &lt;/th&gt;
			&lt;th&gt;lib &lt;/th&gt;
			&lt;th&gt;spec/test&lt;/th&gt;
			&lt;th&gt;test/code ratio &lt;/th&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; Flexmock &lt;/td&gt;
			&lt;td&gt; 1034  &lt;/td&gt;
			&lt;td&gt; 2743 &lt;/td&gt;
			&lt;td&gt; 2.6 &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; Mocha    &lt;/td&gt;
			&lt;td&gt; 1218  &lt;/td&gt;
			&lt;td&gt; 3622 &lt;/td&gt;
			&lt;td&gt; 2.8 &lt;/td&gt;
		&lt;/tr&gt;
	&lt;/table&gt;




	&lt;p&gt;So now we&amp;#8217;ve got two sub-variants to look at:&lt;/p&gt;


	&lt;table style="border:1px solid black; align:right;"&gt;
		&lt;tr&gt;
			&lt;th&gt;Framework &lt;/th&gt;
			&lt;th&gt;lib &lt;/th&gt;
			&lt;th&gt;spec/test&lt;/th&gt;
			&lt;th&gt;test/code ratio &lt;/th&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; Rspec &lt;/td&gt;
			&lt;td&gt; 5473 &lt;/td&gt;
			&lt;td&gt;10108  &lt;/td&gt;
			&lt;td&gt; 1.8 &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; TU+TS+FM &lt;/td&gt;
			&lt;td&gt; 3747 &lt;/td&gt;
			&lt;td&gt; 3622 &lt;/td&gt;
			&lt;td&gt; 1.0 &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; TU+TS+Mocha &lt;/td&gt;
			&lt;td&gt; 3931 &lt;/td&gt;
			&lt;td&gt;  3931 &lt;/td&gt;
			&lt;td&gt; 1.1 &lt;/td&gt;
		&lt;/tr&gt;
	&lt;/table&gt;




	&lt;p&gt;Now you might say that RSpec still is 40% larger than even the larger of the two competing combinations, but this is also ignoring the fact that RSpec also includes RBehave which is another higher level integration/acceptance testing framework.&lt;/p&gt;


	&lt;p&gt;So in retrospect, I&amp;#8217;d humbly submit that code bulk isn&amp;#8217;t such a good comparison criteria in this case.&lt;/p&gt;


	&lt;p&gt;So whatever your test framework &amp;#8216;belief system&amp;#8217; do as you feel best, but do unto others!&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;d still like to hear more about why people think that RSpec is &amp;#8220;too magic&amp;#8221; though.&lt;/p&gt;


	&lt;p&gt;By the way on the subject of lying statistics.  I&amp;#8217;m sure that most of us have by now seen &lt;a href="http://www.indeed.com/jobtrends?q=ruby%2C+java&amp;#38;relative=1"&gt;this chart of Ruby job prospects.&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Which looks like, and is, &lt;span class="caps"&gt;GREAT&lt;/span&gt; news for Rubyists, but how many have seen &lt;a href="http://www.indeed.com/jobtrends?q=ruby%2C+java"&gt;this from the same source.&lt;/a&gt; It&amp;#8217;s the same data, just looked at through a different lens.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m still not looking for Java work though!&lt;/p&gt;</description>
      <pubDate>Tue, 29 Jan 2008 16:24:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:29b762a2-2d17-453e-9346-48acb81d03d2</guid>
      <author>Rick DeNatale</author>
      <link>http://talklikeaduck.denhaven2.com/articles/2008/01/29/why-i-dont-mind-using-rspec-in-fact-ive-come-to-love-it</link>
      <category>ruby</category>
      <category>rails</category>
      <category>tdd</category>
      <category>bdd</category>
      <category>Rspec</category>
      <category>TestUnit</category>
      <category>TestSpec</category>
      <trackback:ping>http://talklikeaduck.denhaven2.com/articles/trackback/485</trackback:ping>
    </item>
    <item>
      <title>Book Review: The Rails Way</title>
      <description>&lt;a href="http://www.amazon.com/gp/product/0321445619?ie=UTF8&amp;tag=denhaven2com-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0321445619"&gt;&lt;img border="0" src="http://talklikeaduck.denhaven2.com/files/2007-12-26_railswaycover.jpg"&gt;&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=denhaven2com-20&amp;l=as2&amp;o=1&amp;a=0321445619" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt;

Disclaimer: I received a free copy of this book because I contributed a one-page essay about "What Rails Means to Me" which appears starting on page 821.
&lt;p&gt;The Rails Way came out shortly before Rails 2.0 was released.  I must say that it serves as a very valuable reference for those with some Rails experience, and in particular for those who are coming up to speed on Rails 2.0.&lt;/p&gt;



&lt;p&gt;Comprising 850 pages, this tome covers a wide spectrum of Rails and Rails related topics.  Although it's been a while since I was a newcomer to Rails, I think it would be a rare newbie who could jump into Rails and learn it by reading this book. Although some sections are written in a tutorial style, it really serves best as a resource for those wanting to increase their mastery of Rails. I've found many thought provoking ideas as I read it.&lt;/p&gt;
&lt;p&gt;Obie's approach is to pick an aspect of Rails and talk about how it's put together as a way of providing a more intimate view of the framework.  I find this very comfortable, it's kind of a an advanced guided tour.&lt;/p&gt;
&lt;p&gt;The book starts out with a walk-through of how Rails starts up, giving the opportunity to explore how Rails configuration works, and how it relates to the various rails environments.&lt;/p&gt;
&lt;p&gt;The next four chapters, comprising 101 pages, talk about controllers and routing. There's a lot of valuable information here, particularly with regards to Rails 2.0, and how RESTful controllers, resources, and routing works.&lt;/p&gt;
&lt;p&gt;From there, the book moves on to ActiveRecord. Four chapters cover the basics, associations, validations, callbacks, observers, single-table inheritance, and more in 167 pages, a book-length treatment in itself.
This is more than the 131 pages on ActiveRecord in &lt;a href="http://www.amazon.com/gp/product/0977616630?ie=UTF8&amp;tag=denhaven2com-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0977616630"&gt;Agile Web Development with Rails&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=denhaven2com-20&amp;l=as2&amp;o=1&amp;a=0977616630" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt; 
snd only slightly less than &lt;a href="http://www.amazon.com/gp/product/1590598474?ie=UTF8&amp;tag=denhaven2com-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=1590598474"&gt;Pro Active Record: Databases with Ruby and Rails&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=denhaven2com-20&amp;l=as2&amp;o=1&amp;a=1590598474" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt; which is totally dedicated to ActiveRecord.
&lt;/p&gt;
&lt;p&gt;This is about as far as I've managed to get through to date, the remainder of this review is based on skimming.&lt;/p&gt;
&lt;p&gt;The coverage of ActionView starts with a chapter covering the basics of ERB, tne new naming conventions in Rails 2.0 (e.g. a view named index.rhtml would now be named index.html.erb); layouts, templates and partials; and various aspects of caching in Rails and how to tame it.&lt;/p&gt;
&lt;p&gt;Chapter 11 covers helpers. Among other things, Obie covers the popular topic of how to write form views which handle updating multiple objects simultaneously. He covers both built-in Rails helpers as well as those provided by popular plug-ins such as the various pagination plugins. Of course he also covers the niceties of writing your own helpers.&lt;/p&gt;
&lt;p&gt;Chapter 12 devotes 48 pages to Ajax on Rails, starting with the very valuable advice to install and use Firebug to debug the resultant Javascript, then covering Prototype and Scriptaculous and their associated helpers, RJS and JSON &lt;/p&gt;
&lt;p&gt;Chapter 13 gives us 15 pages on managing sessions, including the latest on Rails 2.0's new CookieStore default for "storing" session data.&lt;/p&gt;
&lt;p&gt;Chapter 14 is all about user login and authentication.  Seventeen pages are devoted to using Rick Olsen's &lt;a href="http://technoweenie.stikipad.com/plugins/show/Acts+as+Authenticated"&gt;acts_as_authenticated&lt;/a&gt; plugin.  This is one area of the book which is already slightly dated, particularly for Rails 2.0, since acts_as_authenticated has been supplanted by Rick's newer &lt;a href="http://weblog.techno-weenie.net/2006/8/1/restful-authentication-plugin"&gt;restful_authentication&lt;/a&gt; plugin, or so some commentary in the acts_as_authenticated plugin itself leads me to believe.&lt;/p&gt;
&lt;p&gt;Chapter 15 covers XML in 26 pages.  The ability to produce and consume XML is part and parcel of fully supporting REST in Rails and the use of ActiveResource. Obie also covers how to generate XML, and the use of the Builder framework; parsing XML using the XMLSimple library built in to Rails; leading up to an exposition of ActiveResource.&lt;/p&gt;
&lt;p&gt;ActionMailer gets it's due in Chapter 16.&lt;/p&gt;
&lt;p&gt;Testing, and test-driven development gets two chapters.  The 51 pages in Chapter 17 cover "classical" Rails testing using Test::Unit, while Chapter 18 adds another 30 pages on RSpec and the RSpec on Rails plugin.&lt;/p&gt;
&lt;p&gt;Chapter 19 covers plugins from multiple aspects: managing them with the script/plugin command, keeping them under version control with subversion and Piston; and a basic overview of how to write your own plugins.&lt;/p&gt;
&lt;p&gt;The last three chapters cover deployment. Chapter 20 discusses the Rails deployment landscape covering the requirements for a Rails "Stack"; the installation and configuration of various stack components (Ruby, RubyGems, Rails, Mongrel, MongrelCluster, Nginx, Subversion, MySQL, Monit, and Capistrano); writing init scripts for Mongrel, Monit, and Nginx; and a very brief overview of production stack considerations related to performance, reliability and security.&lt;/p&gt;
&lt;p&gt;Chapter 21 covers Capistrano 2.0 in 25 pages, while Chapter 22 wraps up with 16 pages on background processing.&lt;/p&gt;
&lt;p&gt;Finally, there are two appendices. Appendix A covers ActiveSupport, and Appendix B is a catchall for useful things Obie thinks every Rails developer should know, but didn't have another place in the book.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This book, as I said before, is a tome like Hal Fulton's &lt;a href="http://www.amazon.com/gp/product/0672328844?ie=UTF8&amp;tag=denhaven2com-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0672328844"&gt;The Ruby Way&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=denhaven2com-20&amp;l=as2&amp;o=1&amp;a=0672328844" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt;, also in the Addison-Wesley "Professional Ruby Series."  While both suffer from minor editing omissions and mishaps, "The Rails Way" seems to be a bit more polished, and Obie has set up a lighthouse site for &lt;a href="http://awprorubyseries.lighthouseapp.com/projects/6454-the-rails-way/overview"&gt;tracking errata.&lt;/a&gt;&lt;/p&gt; 
&lt;p&gt;All in all I heartily recommend &lt;a href="http://www.amazon.com/gp/product/0321445619?ie=UTF8&amp;tag=denhaven2com-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0321445619"&gt;The Rails Way&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=denhaven2com-20&amp;l=as2&amp;o=1&amp;a=0321445619" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt; as a resource for Rails developers wanting to move on from white or green, to black-belt status.&lt;/p&gt;</description>
      <pubDate>Thu, 27 Dec 2007 12:57:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:f2fe3229-39bb-40c3-9e61-a4dcc91d66e5</guid>
      <author>Rick DeNatale</author>
      <link>http://talklikeaduck.denhaven2.com/articles/2007/12/27/book-review-the-rails-way</link>
      <category>book_reviews</category>
      <category>rails</category>
      <trackback:ping>http://talklikeaduck.denhaven2.com/articles/trackback/483</trackback:ping>
    </item>
    <item>
      <title>Book Review: Pro Active Record</title>
      <description>&lt;a href="http://www.amazon.com/gp/product/1590598474?ie=UTF8&amp;tag=denhaven2com-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=1590598474"&gt;&lt;img border="0" src="http://talklikeaduck.denhaven2.com/files/2007-10-30_cover_of_pro_active_record.jpg" style='float:left;  margin-bottom:30px; margin-right:30px;'&gt;&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=denhaven2com-20&amp;l=as2&amp;o=1&amp;a=1590598474" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt; 
I've been meaning to write a review of the recently published Apress book &lt;a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2FPro-Active-Record-Databases-Rails%2Fdp%2F1590598474%3Fie%3DUTF8%26s%3Dbooks%26qid%3D1193756135%26sr%3D1-1&amp;tag=denhaven2com-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325"&gt;"Pro Active Record"&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=denhaven2com-20&amp;amp;l=ur2&amp;amp;o=1" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt; by Kevin Marshall, Chad Pytel, and Jon Yurek for a while now. I have to admit that I was prompted to sit down and actually do it after reading &lt;a href="http://blog.hasmanythrough.com/2007/10/29/book-review-pro-active-record"&gt;Josh Susser's recent review of the same book.&lt;/a&gt;
&lt;p&gt;While I generally agree with Josh's assessment, We do differ a bit on which audience the book best serves.&lt;/p&gt;
&lt;p&gt;The goal of the book is to cover Active Record in depth, outside of the context of Rails.  The result, as I see it, is a book which is useful to intermediate to advanced users of Active Record, those who want to dig in to understanding the implementation and perhaps extending it.&lt;/p&gt;
&lt;p&gt;My own reading of the book gave me the impetus to explore the code of Active Record to the extent where I felt comfortable submitting contributions to Rails.  Since reading the book, I've written and submitted two active record patches to the Rails Trac. The &lt;a href="http://dev.rubyonrails.org/ticket/9971"&gt;first&lt;/a&gt; fixed an oversight which made the schema.db file dumped for MySQL tables with non-standard primary keys to lack those primary key declarations, and the second is an enhancement which allows the :joins option of methods like find and count in ActiveRecord::Base to take&lt;a href="http://dev.rubyonrails.org/ticket/10012"&gt; values like the :include option&lt;/a&gt; as an alternative to a sql joins clause string.  Both have made it into rails edge!&lt;/p&gt;



&lt;h2&gt;Pro Active Record for Beginners?&lt;/h2&gt;
&lt;p&gt;While I suppose that you could learn Active Record just from this book, I personally think that &lt;a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2FAgile-Web-Development-Rails-2nd%2Fdp%2F0977616630%3Fie%3DUTF8%26s%3Dbooks%26qid%3D1193759512%26sr%3D1-1&amp;tag=denhaven2com-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325"&gt;Agile Web Development with Rails (2nd ed)&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=denhaven2com-20&amp;amp;l=ur2&amp;amp;o=1" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt; does a better job, and makes a better reference for everyday use of Active Record.  While not entirely devoted to Active Record, AWDWR devotes four chapters and 131 pages to it in the "Rails in Depth" section of the book, in addition to coverage of AR in the tutorial section.  In contrast, "Pro Active Record" comprises 8 chapters in 214 pages, plus a 52 page Appendix which is pretty much derived from the RDoc generated from the Active Record source code.&lt;/p&gt;
&lt;p&gt;Shortly after I bought the book, I was working on an issue with some active record validation callbacks on one of my projects. Since "Pro Active Record" was at hand I turned to it.  Although they have good coverage of the topic in Chapter 4, "Core Features of Active Record", the five pages of text description in PAR just doesn't make it as clear when particular callbacks will be called as the single chart on page 372 of the "Object Life Cycle" chapter in AWDWR.&lt;/p&gt;
&lt;p&gt;While some newcomers to active record who are using, say Camping, might welcome the "Rails-free" presentation of PAR, sometimes I get the impression that studiously eschewing Rails in this book hampers it just a bit. There sems to be a little too much repetition of things that Rails does for you, like ActiveRecord::Base.connect(...)&lt;/p&gt;
&lt;h2&gt;Digging In&lt;/h2&gt;
&lt;p&gt;That said, I do really like the book.  The chapter on dealing with legacy databases is quite useful, and I'd recommend it.&lt;/p&gt;
&lt;p&gt;The best part of the book was the section on extending AR. It gives a good introduction to the way AR works, it got me started actually reading the AR code in edge rails.  It also gives some good coverage of Ruby metaprogramming, particularly in the context of AR and Rails&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;So all in all, I recommend the book, although I would recommend newcomers to start with &lt;a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2FAgile-Web-Development-Rails-2nd%2Fdp%2F0977616630%3Fie%3DUTF8%26s%3Dbooks%26qid%3D1193759512%26sr%3D1-1&amp;tag=denhaven2com-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325"&gt;Agile Web Development with Rails (2nd ed)&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=denhaven2com-20&amp;amp;l=ur2&amp;amp;o=1" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt; even if they are using AR outside of rails.&lt;/p&gt;
&lt;p&gt;Those who are, or want to be, a little further along in their exploration, exploitation, and extension of Active Record will find it to be a valuable addition to their book shelf, just as I did.&lt;/p&gt;</description>
      <pubDate>Tue, 30 Oct 2007 12:31:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:bacdbcc3-19b3-4cd9-87fd-2ecae8c6c150</guid>
      <author>Rick DeNatale</author>
      <link>http://talklikeaduck.denhaven2.com/articles/2007/10/30/book-review-pro-active-record</link>
      <category>book_reviews</category>
      <category>rails</category>
      <category>activerecord</category>
      <trackback:ping>http://talklikeaduck.denhaven2.com/articles/trackback/476</trackback:ping>
    </item>
    <item>
      <title>My First Serious TextMate Automation</title>
      <description>&lt;div style='width:240; float:left; text-align:right; font-size:xx-small; border-width:1px; border-color:#444444; border-style:solid;margin-bottom:30px; margin-right:30px;' class='tease-image'&gt;
&lt;img width='240' height='144' alt='A permanent fixture.' src='http://farm1.static.flickr.com/21/34024841_8e548f4569_m.jpg'&gt;
&lt;br/&gt;
&lt;a href='http://flickr.com/photos/henryfaber/34024841/'&gt;A permanent fixture.&lt;/a&gt;
&lt;br/&gt;&amp;copy;
&lt;a href='http://flickr.com/people/henryfaber'&gt;Henry Faber&lt;/a&gt;
&lt;br/&gt;&lt;a href='http://creativecommons.org/licenses/by-nc/2.0/'&gt;&lt;img src='http://i.creativecommons.org/l/by-nc/2.0/80x15.png' title='used under a Creative Commons Attribution-NonCommercial License' width='80' height='15' border='0'/&gt;&lt;/a&gt;
&lt;/div&gt;

I recently got assimilated by the Mac/TextMate borg.  I'm slowly teaching my fingers to dance the TextMate tango and unlearning old vim habits.
&lt;p&gt;One resource has been James Edward Gray II's book on TextMate published by the Pragmatic Programmers. I finally sat down and got serious about writing some automations of my own.&lt;/p&gt;
&lt;p&gt;I've got to say that I'm pretty impressed by TextMate.  At the last Raleigh.rb hack night I was talking to another vim user.  I'd mentioned to him that you can extend TextMate easily in Ruby, without really having experienced it. Today, I wrote a neat little TextMate command to help in building Rails database test fixtures.&lt;/p&gt;
&lt;p&gt;It acts like a tab triggered snippet, but it's a smart little critter.  If I'm editing a fixture file, say 'test/fixtures/users.yml', I can type item then tab and it will produce the skeleton yaml for a new record, with:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;A dummy name selected for overtyping.&lt;/li&gt;
  &lt;li&gt;The id set to the next available primary key&lt;/li&gt;
  &lt;/li&gt;Each column name as a yaml key ...&lt;/li&gt;
  &lt;li&gt;... A tabstop on a value which shows the column type&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For example:&lt;/p&gt;



&lt;p&gt;Suppose I've got a fixture file for a model called Item:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&lt;notextile&gt;	# == Schema Information
	# Schema version: 14
	#
	# Table name: items
	#
	#  id          :integer(11)   not null, primary key
	#  description :string(255)   
	#  name        :string(255)   
	#  price       :integer(11)   
	#

	# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
	lotr1:
	  id: 1
	  name: LOTR1
	  description: The Road Goes Ever On
	lotr2:
	  id: 2
	  name: LOTR2
	  description: Introduction to Elvish&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If I type a new line at the end of this file with the snippet command item and hit tab I see this:&lt;/p&gt;                                                    
&lt;br/&gt;lotr2:
&lt;br/&gt;&amp;nbsp;&amp;nbsp;id: 2
&lt;br/&gt;&amp;nbsp;&amp;nbsp;name: LOTR2
&lt;br/&gt;&amp;nbsp;&amp;nbsp; description: Introduction to Elvish
&lt;br/&gt;
&lt;br/&gt;&amp;nbsp;&amp;nbsp;&lt;b&gt;NameMe&lt;/b&gt;:
&lt;br/&gt;&amp;nbsp;&amp;nbsp;  id: 3
&lt;br/&gt;&amp;nbsp;&amp;nbsp;  description: string
&lt;br/&gt;&amp;nbsp;&amp;nbsp;  name: string
&lt;br/&gt;&amp;nbsp;&amp;nbsp;  price: integer    
&lt;p&gt;With &lt;b&gt;NameMe&lt;/b&gt; selected so that I can easily replace it by typing. Note that the id was set to 3 since rows with ids 1 and 2 already exist.&lt;/p&gt;
&lt;p&gt;Hitting tab again selects the first instance of string, and subsequent tabs step through the columns&lt;/p&gt;
&lt;p&gt;Another feature which I won't show is that it looks at the table and if it doesn't have a primary key (e.g. for an association table in a has_and_belongs_to_many association), it won't generate the id: or a key.&lt;/p&gt;
&lt;p&gt;You might be impressed, but I'm pretty happy with the results of a couple of hours of playing with TextMata and Ruby.&lt;/p&gt;
&lt;h2&gt;How it works.&lt;/h2&gt;
&lt;p&gt;The whole thing is done with a TextMate command implemented in Ruby.  A few notes.  First, it's just a coincidence that the snippet trigger is item and my example table is called items.  Second, I'm not using the comments at the top of the fixture file which were generated when the model was created.  The command works off of db/schema.db.&lt;/p&gt;
&lt;p&gt;Here's the code:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&lt;notextile&gt;	#!/usr/bin/env ruby -w  
	#
	#  Created by Rick DeNatale on 2007-10-09.
	#  Copyright (c) 2007. You may use this under the ruby license.                    

	$LOAD_PATH &amp;lt;&amp;lt; &amp;quot;#{ENV['TM_SUPPORT_PATH']}/lib&amp;quot;
	require 'exit_codes.rb'


	class FixtureSnipGen
	  attr_reader :rails_root, :table_name
	  def initialize(fixture_file)
	    match  = %r{(.*)test/fixtures/(.*).yml}.match(ENV[&amp;quot;TM_FILEPATH&amp;quot;])
	    @rails_root = match[1]
	    @table_name = match[2]
	    @no_id = false  
	  end

	  def next_id
	    max_id = 0     
	    while line = gets
	      claimed = %r{\s+id:\s+(\d+)}.match(line) 
	      max_id = [max_id, claimed[1].to_i].max if claimed
	    end
	    max_id + 1
	  end

	  def gen_snippet
	    cols = gen_columns
	    if cols
	      puts &amp;quot;${1:NameMe}:&amp;quot;
	      puts &amp;quot;  id: #{next_id}&amp;quot; unless @no_id
	      puts cols.join(&amp;quot;\n&amp;quot;)
	    else 
	      puts &amp;quot;Couldn't find #{table_name} in schema.rb&amp;quot;
	      TextMate.exit_show_tool_tip
	    end
	    puts &amp;quot;$0&amp;quot;
	  end

	  def schema_file_name  
	    &amp;quot;#{rails_root}db/schema.rb&amp;quot;
	  end 

	  def value_tab(text)
	    @tab_stop += 1
	    (@tab_stop &amp;lt; 10) ? &amp;quot;${#{@tab_stop}:#{text}}&amp;quot; : &amp;quot; # #{text}&amp;quot;
	  end


	  def gen_columns
	    #    raise Exception.new(&amp;quot;No schema file&amp;quot;) unless File.exist?(schema_file_name)
	    started = false
	    @tab_stop = @no_id ? 0 : 1
	    result = []
	    File.new(schema_file_name).each do | line |
	      if started
	        break if %r{^(\s*)create_table\s+}.match(line)
	        col_match = %r{\.column\s+\&amp;quot;(.*)\&amp;quot;\s*,\s*:(\w+)}.match(line)
	        result &amp;lt;&amp;lt; &amp;quot;  #{col_match[1]}: #{value_tab(col_match[2])}&amp;quot; if col_match
	      else
	        started = %r{^(\s*)create_table\s+[&amp;quot;']#{table_name}['&amp;quot;]}.match(line)
	        @no_id = %r{:id\s+=&amp;gt;\s+false}.match(line) if started
	      end
	    end
	    return result.empty? ? nil : result    
	  end
	end

	begin
	  FixtureSnipGen.new(ENV[&amp;quot;TM_FILEPATH&amp;quot;]).gen_snippet
	rescue Exception =&amp;gt; ex
	  puts ex
	  TextMate.exit_show_tool_tip
	end&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the TextMate bundle editor, I just added a new command with this code, and set the following options:&lt;/p&gt;
&lt;dl&gt;
	&lt;dt&gt;Save:&lt;/dt&gt;&lt;dd&gt;Nothing&lt;/dd&gt;
	&lt;dt&gt;Input:&lt;/dt&gt;&lt;dd&gt;Entire Document - which pipes the entire textmate buffer for the file into stdin.&lt;/dd&gt;
	&lt;dt&gt;Output:&lt;/dt&gt;&lt;dd&gt;Insert as Snippet - which triggers TextMate to interpret the output as a snippet once the script has finished.&lt;/dd&gt;
	&lt;dt&gt;Activation:&lt;/dt&gt;&lt;dd&gt;Tab Trigger = item&lt;/dd&gt;
	&lt;dt&gt;Scope Selector&lt;/dt&gt;source.yaml - this only works within yml files.&lt;/&gt;
&lt;/dl&gt;         
&lt;p&gt;Finally note that although my example uses a table called items, it's just a coincidence that the tab trigger is item. It would be item in any fixture file.&lt;/p&gt;</description>
      <pubDate>Tue, 09 Oct 2007 08:15:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:ad8ffd07-f3e1-4083-abee-ec5301b9c1ba</guid>
      <author>Rick DeNatale</author>
      <link>http://talklikeaduck.denhaven2.com/articles/2007/10/09/my-first-serious-textmate-automation</link>
      <category>rails</category>
      <category>textmate</category>
      <category>automation</category>
      <category>testing</category>
      <category>fixtures</category>
      <trackback:ping>http://talklikeaduck.denhaven2.com/articles/trackback/469</trackback:ping>
    </item>
    <item>
      <title>Observing Fields With Rails in the Browser</title>
      <description>&lt;div style='width:160; float:left; text-align:right; font-size:xx-small; border-width:1px; border-color:#444444; border-style:solid;margin-bottom:30px; margin-right:30px;' class='tease-image'&gt;
&lt;img width='160' height='240' alt='observation car' src='http://farm1.static.flickr.com/205/443042586_8194430e7a_m.jpg'&gt;
&lt;br/&gt;
&lt;a href='http://flickr.com/photos/dustbowlballad/443042586/'&gt;observation car&lt;/a&gt;
&lt;br/&gt;&amp;copy;
&lt;a href='http://flickr.com/people/dustbowlballad'&gt;carolyn&lt;/a&gt;
&lt;br/&gt;&lt;a href='http://creativecommons.org/licenses/by-nc/2.0/'&gt;&lt;img src='http://i.creativecommons.org/l/by-nc/2.0/80x15.png' title='used under a Creative Commons Attribution-NonCommercial License' width='80' height='15' border='0'/&gt;&lt;/a&gt;
&lt;/div&gt;
The AJAX support in Rails is great, but sometimes you don't want to have to make an unnecessary trip to the server to make your UI dynamic. For example, let's say you want to do something like Basecamp does when you create a new message.  If you have a Basecamp setup to allow you to talk to both members of your team and also clients, it provides some nice checkboxes to let you control who will get notified of the new message.  Those checkboxes are grouped with a checkbox for each company, and then checkboxes for all of the people from that company below the company checkbox. If you check or uncheck a company checkbox all of the people listed under the company are checked or unchecked to match.
&lt;p&gt;This can all be done within the browser.  It just requires manipulation of existing elements within the domain object model, so there's no need to go back to the server.&lt;/p&gt;
&lt;p&gt;Rails provides the &lt;strong&gt;observe_field&lt;/strong&gt; helper method which is normally used to generate a remote request when a DOM element changes.  It can be used to do what we want, but how to do so isn't well documented, either in the Rails documentation, or via google.&lt;/p&gt;
&lt;p&gt;So here's how to do it.&lt;p&gt;



&lt;h2&gt;What the Rails Doc says&lt;/h2&gt;
&lt;p&gt;Here's how the official doc for observe_field starts...&lt;/p&gt; 
&lt;blockquote&gt;
&lt;b&gt;observe_field&lt;/b&gt;(field_id, options = {})
&lt;p&gt;
Observes the field with the DOM ID specified by &lt;tt&gt;field_id&lt;/tt&gt; and calls
a callback when its contents have changed. The default callback is an Ajax
call. By default the value of the observed field is sent as a parameter
with the Ajax call.
&lt;/p&gt;
&lt;p&gt;
Required &lt;tt&gt;options&lt;/tt&gt; are either of:
&lt;/p&gt;
&lt;table&gt;
&lt;tr&gt;&lt;td valign="top"&gt;&lt;tt&gt;:url&lt;/tt&gt;:&lt;/td&gt;&lt;td&gt;&lt;tt&gt;url_for&lt;/tt&gt;-style options for the action to call when the field has
changed.

&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign="top"&gt;&lt;tt&gt;:function&lt;/tt&gt;:&lt;/td&gt;&lt;td&gt;Instead of making a remote call to a URL, you can specify a function to be
called instead.

&lt;/td&gt;&lt;/tr&gt;

&lt;/table&gt;
&lt;/blockquote&gt;
&lt;p&gt;So the &lt;b&gt;function&lt;/b&gt; option seems to be what we need  When I read this I assumed that the value should be a string containing a javascript function definition. But it's not.&lt;/p&gt;
&lt;p&gt;What the value should be is javascript code for the &lt;b&gt;body&lt;/b&gt; of the function definition.  The prototype helper provides the surrounding definition.  So when you code:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&lt;notextile&gt;        
observe_element('company1', :function =&amp;gt; 'code')&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
The javascript code generated looks like:
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&lt;notextile&gt;Form.Observer.new('company1', function(element,value) {code})&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So just write Javascript code for the body.  You can use the element parameter to refer to the domain element being observed, in this case it would be the same as the prototype expression "$('company1')"  and the value parameter gives you the value attribute of the observed element.&lt;/p&gt;
So let's say our company has two guys whose checkboxes are 'bill_c' and 'sam_r' and our company checkbox is called 'our_corp'.  Then this helper call:
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&lt;notextile&gt;        
observe_element(
    'our_corp', 
    :function =&amp;gt; &amp;quot;$('bill_c') = value\n$('sam_r') = value&amp;quot;)&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Should do the trick of turning both the bill_c and sam_r checkboxes on or off when we toggle the our_corp checkbox.&lt;/p&gt;
&lt;p&gt;Of course you probably don't want to hand code the ids, and the actual ids will conform to those used by the form helpers, but I'll leave those details to you&lt;/p&gt;
&lt;h2&gt;Getting the Rails Docs Updated&lt;/h2&gt;
&lt;p&gt;I've submitted a &lt;a href="http://dev.rubyonrails.org/ticket/9808"&gt;ticket on rails trac&lt;/a&gt; with a patch to document this.  If you've got a rails trac account, please have a look and consider adding a +1 to get this into report #12 and into Rails.&lt;/p&gt;</description>
      <pubDate>Sun, 07 Oct 2007 12:34:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:f816b609-8767-4817-aa66-523db46cb82b</guid>
      <author>Rick DeNatale</author>
      <link>http://talklikeaduck.denhaven2.com/articles/2007/10/07/observing-fields-with-rails-in-the-browser</link>
      <category>rails</category>
      <category>ajax</category>
      <category>prototype</category>
      <trackback:ping>http://talklikeaduck.denhaven2.com/articles/trackback/468</trackback:ping>
    </item>
  </channel>
</rss>
