<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="http://feeds.feedburner.com/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US">
  <id>tag:errtheblog.com,2008:/posts</id>
  <link type="text/html" rel="alternate" href="http://errtheblog.com/" />
  
  <title>Err the Blog</title>
  <updated>2008-06-24T20:52:08+00:00</updated>
  <link rel="self" href="http://feeds.feedburner.com/errtheblog" type="application/atom+xml" /><entry>
    <id>tag:errtheblog.com,2008:Post/91</id>
    <published>2008-06-24T20:50:00+00:00</published>
    <updated>2008-06-24T20:52:08+00:00</updated>
    <link type="text/html" rel="alternate" href="http://errtheblog.com/posts/91-the-best-of-cheat" />
    <title>The Best of Cheat</title>
    <content type="html">&lt;p&gt;There&amp;#8217;s some real gold in &lt;a href="http://cheat.errtheblog.com"&gt;Cheat&lt;/a&gt;.  Like, nuggets.  Ever since we got tagged by &lt;a href="http://cheat.errtheblog.com/s/mustache/"&gt;mustache&lt;/a&gt; it&amp;#8217;s been just wild.&lt;/p&gt;


	&lt;p&gt;Ever wonder how to make hot chocolate?  We&amp;#8217;ve got a tasty &lt;a href="http://cheat.errtheblog.com/s/hot_chocolate/"&gt;recipe&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Need some night time reading to go along with your cocoa?  May I suggest &lt;a href="http://cheat.errtheblog.com/s/into_the_code/"&gt;Into the Code&lt;/a&gt;?&lt;/p&gt;


	&lt;p&gt;The &lt;a href="http://cheat.errtheblog.com/s/datamapper/"&gt;DataMapper sheet&lt;/a&gt; is superb in its brevity: &lt;span class="code"&gt;has_many :class =&amp;gt; &amp;#8220;ClassName&amp;#8221;&lt;/span&gt;&lt;/p&gt;


	&lt;p&gt;(By the way, this post has been highly optimized with the &lt;a href="http://cheat.errtheblog.com/s/seo/"&gt;&lt;span class="caps"&gt;SEO&lt;/span&gt; sheet&lt;/a&gt;.)&lt;/p&gt;


	&lt;p&gt;The &lt;a href="http://cheat.errtheblog.com/s/foo/"&gt;Foo sheet&lt;/a&gt; is the foo sheet is the foo sheet.&lt;/p&gt;


	&lt;p&gt;Hot chocolate not hitting the spot?  How about some &lt;a href="http://cheat.errtheblog.com/s/gazpacho/"&gt;Gazpacho soup&lt;/a&gt;?&lt;/p&gt;


	&lt;p&gt;If you&amp;#8217;re a designer, you&amp;#8217;ll love this: &lt;a href="http://cheat.errtheblog.com/s/lipsum/"&gt;lipsum&lt;/a&gt;.  All of it.&lt;/p&gt;


	&lt;p&gt;Ever wanted to talk like you&amp;#8217;re in the military, or own a walkie talkie?  Now you can with this handy &lt;a href="http://cheat.errtheblog.com/s/military_alphabet/"&gt;military alphabet&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Oh, an entire &lt;a href="http://cheat.errtheblog.com/s/pddd/"&gt;Cheat Emacs mode&lt;/a&gt;.  Remember: &lt;a href="http://cheat.errtheblog.com/s/emacs_tips/"&gt;Never quit Emacs&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m sure you&amp;#8217;ve been wondering, so here it is: &lt;a href="http://cheat.errtheblog.com/s/tld/"&gt;every &lt;span class="caps"&gt;TLD&lt;/span&gt; ever&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;In the spirit of three letter acronyms, there&amp;#8217;s also the &lt;a href="http://cheat.errtheblog.com/s/gtd/"&gt;&lt;span class="caps"&gt;GTD&lt;/span&gt; sheet&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;One of my favorites, the &lt;a href="http://cheat.errtheblog.com/s/runescape/"&gt;Runescape sheet&lt;/a&gt;:&lt;/p&gt;


&lt;pre&gt;
Hot keys

1 selling
2 buing
3 buy
4 noob
&lt;/pre&gt;

	&lt;p&gt;For the serious kids in the room, there&amp;#8217;s the &lt;a href="http://cheat.errtheblog.com/s/permissions/"&gt;Unix permissions&lt;/a&gt; and &lt;a href="http://cheat.errtheblog.com/s/redirect/"&gt;Unix redirection&lt;/a&gt; sheets.  Oh, and the &lt;a href="http://cheat.errtheblog.com/s/notify/"&gt;notify trick&lt;/a&gt; then the complete &lt;a href="http://cheat.errtheblog.com/s/firebug/"&gt;Firebug sheet&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Finally, the &lt;a href="http://cheat.errtheblog.com/s/nonsense/"&gt;nonsense sheet&lt;/a&gt; imparts on us some non-nonsense wisdom: &amp;#8220;and that&amp;#8217;s why cheat also is an anagram for teach!&amp;#8221;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/errtheblog?a=jB902I"&gt;&lt;img src="http://feeds.feedburner.com/~f/errtheblog?i=jB902I" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
    <author>
      <name>Chris</name>
    </author>
  </entry>
  <entry>
    <id>tag:errtheblog.com,2008:Post/90</id>
    <published>2008-05-14T23:57:00+00:00</published>
    <updated>2008-05-15T02:19:29+00:00</updated>
    <link type="text/html" rel="alternate" href="http://errtheblog.com/posts/90-who-needs-an-api" />
    <title>Who Needs an API?</title>
    <content type="html">&lt;p&gt;&lt;a href="http://github.com"&gt;GitHub&lt;/a&gt; is a pretty fun site to work on, I&amp;#8217;m not gonna lie. On more than one occasion, we thought it would be pretty cool to setup a service allowing public projects to receive donations.&lt;/p&gt;


	&lt;h3&gt;Sounds like an Itch&lt;/h3&gt;


	&lt;p&gt;&lt;a href="http://pledgie.org"&gt;Pledgie&lt;/a&gt; being the venerable service it is, I decided one night it couldn&amp;#8217;t possibly be that hard to integrate it with GitHub. It&amp;#8217;s a pretty standard Rails site with some simple forms to make the magic happen (eg. setup a donation page).&lt;/p&gt;


	&lt;p&gt;They don&amp;#8217;t have an &lt;span class="caps"&gt;API&lt;/span&gt; (yet), but in this day and age, you really don&amp;#8217;t need one if you procure the proper tools.&lt;/p&gt;


	&lt;p&gt;Enter &lt;a href="http://mechanize.rubyforge.org/mechanize/"&gt;Mechanize&lt;/a&gt;. You can do all I&amp;#8217;m about to describe with just &lt;span class="code"&gt;Net::HTTP&lt;/span&gt;, but seriously, who wants to do that?&lt;/p&gt;


	&lt;h3&gt;Start Scratching&lt;/h3&gt;


	&lt;p&gt;&lt;strong&gt;Step 0:&lt;/strong&gt; Drive girlfriend to airport, buy a case of Anchor Steam, and turn off  the Xbox.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Sign up for a Pledgie account, cause GitHub&amp;#8217;s a regular user after all.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Write the interface on GitHub to accept the user&amp;#8217;s Paypal address.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Figure out the form fields I should be filling out to login and create a new pledge on Pledgie.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Step 4:&lt;/strong&gt; Write the Mechanize code:&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;pledgify&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;email&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;agent&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;WWW&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Mechanize&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;
  &lt;span class="ident"&gt;page&lt;/span&gt;  &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;agent&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;get&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;http://pledgie.org/accounts/login&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
  &lt;span class="ident"&gt;form&lt;/span&gt;  &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;page&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;forms&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
  &lt;span class="ident"&gt;form&lt;/span&gt;&lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;account[login]&lt;/span&gt;&lt;span class="punct"&gt;']&lt;/span&gt;    &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;GitHub&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;PledgieUser&lt;/span&gt;
  &lt;span class="ident"&gt;form&lt;/span&gt;&lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;account[password]&lt;/span&gt;&lt;span class="punct"&gt;']&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;GitHub&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;PledgiePass&lt;/span&gt;
  &lt;span class="ident"&gt;page&lt;/span&gt;  &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;agent&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;submit&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;form&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

  &lt;span class="ident"&gt;link&lt;/span&gt;  &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;page&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;links&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;text&lt;/span&gt;&lt;span class="punct"&gt;(/&lt;/span&gt;&lt;span class="regex"&gt;Create A Campaign&lt;/span&gt;&lt;span class="punct"&gt;/)&lt;/span&gt;
  &lt;span class="ident"&gt;page&lt;/span&gt;  &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;agent&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;click&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;link&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;form&lt;/span&gt;  &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;page&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;forms&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
  &lt;span class="ident"&gt;form&lt;/span&gt;&lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;campaign[title]&lt;/span&gt;&lt;span class="punct"&gt;']&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;FooBarz&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; 
  &lt;span class="ident"&gt;form&lt;/span&gt;&lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;campaign[paypal]&lt;/span&gt;&lt;span class="punct"&gt;']&lt;/span&gt;       &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;email&lt;/span&gt;
  &lt;span class="ident"&gt;form&lt;/span&gt;&lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;campaign[description]&lt;/span&gt;&lt;span class="punct"&gt;']&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;The best project evar!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; 
  &lt;span class="ident"&gt;form&lt;/span&gt;&lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;campaign[end_date(1i)]&lt;/span&gt;&lt;span class="punct"&gt;']&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;10&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;years&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;from_now&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;year&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt;
  &lt;span class="ident"&gt;page&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;agent&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;submit&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;form&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;form&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;buttons&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;last&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;update_attribute&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:pledgie&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;page&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;uri&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt;&lt;span class="punct"&gt;[/&lt;/span&gt;&lt;span class="regex"&gt;&lt;span class="escape"&gt;\d&lt;/span&gt;+&lt;/span&gt;&lt;span class="punct"&gt;/])&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;&lt;strong&gt;Step 5:&lt;/strong&gt; Take the pledgie attribute we just grabbed and put a cool badge in their repository&amp;#8217;s detail box.&lt;/p&gt;


&lt;div style="text-align:center; padding-bottom:10px"&gt;&lt;img src="http://img.skitch.com/20080505-ny4cigb52pgf5rnad4xge325k2.jpg" alt="" /&gt;&lt;/div&gt;

	&lt;p&gt;&lt;strong&gt;Step 6:&lt;/strong&gt; &lt;a href="http://pledgie.org/accounts/github"&gt;Watch the millions pour in&lt;/a&gt; for GitHub&amp;#8217;s hard-working open source committers.&lt;/p&gt;


	&lt;p&gt;The obvious caveat here is that it relies on Pledgie not drastically changing the structure of its &lt;span class="caps"&gt;HTML&lt;/span&gt;, but it&amp;#8217;s incredibly satisfying to throw something together like this in such a short amount of time.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;PS.&lt;/strong&gt; If you&amp;#8217;re on GitHub and wondering how you missed the original announcement, the post is here: &lt;a href="http://github.com/blog/57-getting-paid-the-open-source-way"&gt;http://github.com/blog/57-getting-paid-the-open-source-way&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/errtheblog?a=SprL6H"&gt;&lt;img src="http://feeds.feedburner.com/~f/errtheblog?i=SprL6H" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
    <author>
      <name>PJ</name>
    </author>
  </entry>
  <entry>
    <id>tag:errtheblog.com,2008:Post/89</id>
    <published>2008-05-11T02:59:00+00:00</published>
    <updated>2008-05-11T05:14:32+00:00</updated>
    <link type="text/html" rel="alternate" href="http://errtheblog.com/posts/89-huba-huba" />
    <title>Huba Huba</title>
    <content type="html">&lt;p&gt;Surely, by now, you&amp;#8217;ve heard of &lt;a href="http://github.com/"&gt;GitHub&lt;/a&gt;.  (Don&amp;#8217;t call me surely.) It&amp;#8217;s totally the Indiana Jones of repository hosts. Feel free to stalk &lt;a href="http://github.com/pjhyett"&gt;Pj&lt;/a&gt; and &lt;a href="http://github.com/defunkt"&gt;I&lt;/a&gt; to see what we&amp;#8217;re up to.  Blogging be damned!&lt;/p&gt;


	&lt;p&gt;If you haven&amp;#8217;t heard of GitHub, there are &lt;a href="http://www.google.com/search?q=github"&gt;tons of posts&lt;/a&gt; explaining the hows and whys of its awesomeness.  This is not one of the posts.  Instead, I want to quickly share some oft overlooked but tasty GitHub tidbits.&lt;/p&gt;


	&lt;h3&gt;The GitHub Gem&lt;/h3&gt;


	&lt;p&gt;&lt;a href="http://gems.github.com/"&gt;GitHub supports gems&lt;/a&gt;, which is cool, and also means we can install the &lt;a href="http://github.com/defunkt/github-gem"&gt;official GitHub gem&lt;/a&gt; with ease:&lt;/p&gt;


&lt;pre&gt;
$ gem install defunkt-github --source=http://gems.github.com/
&lt;/pre&gt;  

	&lt;p&gt;Great.  At this point, possibilities become reality.  The gem has a few cool features, all of which are displayed via &lt;span class="code"&gt;$ github -h&lt;/span&gt;, but the best feature by far is &lt;span class="code"&gt;pull&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s how it works: I have my fork of &lt;a href="http://github.com/technoweenie"&gt;technoweenie&amp;#8217;s&lt;/a&gt; &lt;a href="http://github.com/defunkt/exception_logger/tree/master"&gt;exception_logger&lt;/a&gt;.  I&amp;#8217;ve cloned it and am sitting in the working directory.  Suddenly I discover &lt;a href="http://github.com/ryanb"&gt;ryanb&lt;/a&gt; (of &lt;a href="http://railscasts.com/"&gt;RailsCasts&lt;/a&gt; fame) has sent me a pull request.  Open source&amp;#8217;s finest moment.&lt;/p&gt;


	&lt;p&gt;So, I type &lt;span class="code"&gt;$ github pull ryanb&lt;/span&gt;.  A remote is added, a new branch is created, and Ryan&amp;#8217;s changes are pulled into that branch.  (It&amp;#8217;s probably named &lt;span class="code"&gt;ryanb/master&lt;/span&gt;.)  I then review the changes and, if they rock, either rebase or merge them back into master.  Like this:&lt;/p&gt;


&lt;pre&gt;
$ git checkout master
$ git merge ryanb/master
$ git push
&lt;/pre&gt;

	&lt;p&gt;Already reviewed the changes on the web and know they&amp;#8217;re legit?  Just &lt;span class="code"&gt;$ github pull --merge ryanb&lt;/span&gt;.  This&amp;#8217;ll grab the changes and merge them into master for you.  Oh, right, you can also specify a branch.  The assumption is master, but you know what they say about assumptions: you&amp;#8217;re a jerk.&lt;/p&gt;


	&lt;p&gt;Thus: &lt;span class="code"&gt;$ github pull&amp;#8212;merge ryanb weird_branch&lt;/span&gt;&lt;/p&gt;


	&lt;p&gt;And just like that, GitHub &lt;a href="http://github.com/guides/pull-requests"&gt;pull requests&lt;/a&gt; are no longer a pain in the ass.&lt;/p&gt;


	&lt;p&gt;But really, this is just start.  Please please please &lt;a href="http://github.com/defunkt/github-gem"&gt;fork the gem&lt;/a&gt; and add awesome features.  &lt;span class="code"&gt;github clone&lt;/span&gt;, anyone?&lt;/p&gt;


	&lt;h3&gt;Keyboard Shortcuts&lt;/h3&gt;


	&lt;p&gt;Let&amp;#8217;s say you want to peep some &lt;a href="http://github.com/rails/rails/commits"&gt;Rails changes&lt;/a&gt;.  In classic vi style, &lt;span class="code"&gt;j&lt;/span&gt; and &lt;span class="code"&gt;k&lt;/span&gt; navigate between changes.  &lt;span class="code"&gt;c&lt;/span&gt;, &lt;span class="code"&gt;t&lt;/span&gt;, and &lt;span class="code"&gt;p&lt;/span&gt; lead you to the selected change&amp;#8217;s commit, tree, or parent.  &lt;span class="code"&gt;h&lt;/span&gt; and &lt;span class="code"&gt;l&lt;/span&gt; navigate between pages.&lt;/p&gt;


&lt;div align="center" style="padding-bottom: 10px;"&gt;
  &lt;img src="http://img.skitch.com/20080511-wush93mper9pj6fj5knk2tuih.png" /&gt;
&lt;/div&gt;

	&lt;p&gt;In fact, &lt;span class="code"&gt;h&lt;/span&gt; and &lt;span class="code"&gt;l&lt;/span&gt; will always go back and forward on any paginated page.  We&amp;#8217;ve written an &lt;a href="http://errtheblog.com/posts/67-evil-twin-plugin"&gt;evil twin&lt;/a&gt; which adds those hotkeys to any &lt;span class="code"&gt;will_paginate&lt;/span&gt; call.&lt;/p&gt;


	&lt;p&gt;Also cool: &lt;span class="code"&gt;s&lt;/span&gt;.  If you&amp;#8217;re logged in, hitting &lt;span class="code"&gt;s&lt;/span&gt; will display and focus the search bar.  I use this one the most.&lt;/p&gt;


	&lt;h3&gt;Ranged Code Highlighting&lt;/h3&gt;


	&lt;p&gt;Clicking on any line number then shift clicking a higher value line number selects a range.  Super useful for code discussion.  Discussion such as, &amp;#8220;Dude, &lt;span class="code"&gt;nonzero?&lt;/span&gt; is so awesome.  &lt;a href="http://github.com/evanphx/rubinius/tree/master/kernel/core/numeric.rb#L121-123"&gt;Check it out&lt;/a&gt;!&amp;#8221;  (People definitely talk like that.)&lt;/p&gt;


&lt;div align="center" style="padding-bottom: 10px;"&gt;
  &lt;img src="http://img.skitch.com/20080511-d6pe85ru7nnaf8h9cn4ub8m6js.png" /&gt;
&lt;/div&gt;

	&lt;p&gt;Sweet.&lt;/p&gt;


	&lt;h3&gt;Keep Your Dotfiles in Git&lt;/h3&gt;


	&lt;p&gt;Okay, this isn&amp;#8217;t strictly related to GitHub, but it&amp;#8217;s good.  You should be keeping your dotfiles in Git.  Here are the steps to do so:&lt;/p&gt;


	&lt;p&gt;1. Create a &amp;#8216;dotfiles&amp;#8217; directory.&lt;/p&gt;


	&lt;p&gt;2. Move your dotfiles to this new directory, sans leading dot.  For example, to keep your &lt;span class="code"&gt;&amp;tilde;/.vimrc&lt;/span&gt; under version control, do this:&lt;/p&gt;


	&lt;p&gt;&lt;span class="code"&gt;$ mv &amp;tilde;/.vimrc &amp;tilde;/Projects/dotfiles/vimrc&lt;/span&gt;.  Rinse and repeat as necessary.&lt;/p&gt;


	&lt;p&gt;3. Add the following file to your &lt;span class="code"&gt;dotfiles&lt;/span&gt; project, then run it: &lt;a href="http://pastie.org/195036"&gt;http://pastie.org/195036&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;4. Finally: &lt;span class="code"&gt;$ git init &amp;#38;&amp;#38; git add .&lt;/span&gt;  Then: &lt;span class="code"&gt;$ git commit -m &amp;#8216;new dotfiles project&amp;#8217;&lt;/span&gt;&lt;/p&gt;


	&lt;p&gt;You&amp;#8217;re all set.  Now your dotfiles that live in &lt;span class="code"&gt;&amp;tilde;&lt;/span&gt; are symlinked to their counterparts in &lt;span class="code"&gt;&amp;tilde;/Projects/dotfiles&lt;/span&gt;.  As a bonus, any time you &lt;span class="code"&gt;git commit&lt;/span&gt; it will automatically &lt;span class="code"&gt;git push&lt;/span&gt;.  &lt;abbr title="ROFL!  Not English!"&gt;One of the entire points&lt;/abbr&gt; of keeping your files under version control is to back them up regularly.&lt;/p&gt;


	&lt;p&gt;I push to a private &amp;#8216;dotfiles&amp;#8217; repo on GitHub.  Others have created &lt;a href="http://github.com/search?q=dotfiles"&gt;public repos&lt;/a&gt;.  Your call.&lt;/p&gt;


	&lt;p&gt;For posterity&amp;#8217;s sake, here&amp;#8217;s my version controlled dotfiles:&lt;/p&gt;


&lt;pre&gt;
bashrc
gitconfig
irbrc
railsrc
sake
screenrc
ssh
vim
vimrc
&lt;/pre&gt;

	&lt;h3&gt;The best part?&lt;/h3&gt;


	&lt;p&gt;The best part about GitHub, f&amp;#8217;sure, is all the outrageously cool open source projects hosted on it.  &lt;a href="http://github.com/why"&gt;_why&amp;#8217;s stuff&lt;/a&gt;, the &lt;a href="http://github.com/search?q=jquery"&gt;jQuery plugins and mirrors&lt;/a&gt;, all the &lt;a href="http://github.com/search?q=lisp"&gt;&lt;span class="caps"&gt;LISP&lt;/span&gt; projects&lt;/a&gt;, newer languages like &lt;a href="http://github.com/stevedekorte/io"&gt;Io&lt;/a&gt;, and of course the assorted &lt;a href="http://github.com/search?q=github"&gt;GitHub-related projects&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Got something cool hosted there?  Let us know.&lt;/p&gt;


	&lt;p&gt;Til next time, keep on hubbin&amp;#8217;.&lt;/p&gt;


	&lt;h3&gt;Update: GitHub Open Sores&lt;/h3&gt;


	&lt;p&gt;I just created the &lt;a href="http://github.com/github"&gt;GitHub account&lt;/a&gt; and did two things: created and pushed up some extractions from GitHub itself (like the &lt;a href="http://github.com/github/jquery-hotkeys"&gt;jQuery hotkeys&lt;/a&gt; plugin) and also forked all the projects that are used on GitHub which we&amp;#8217;re using on GitHub.  Dude, meta.  Anyway, have fun with that.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/errtheblog?a=yhF4mH"&gt;&lt;img src="http://feeds.feedburner.com/~f/errtheblog?i=yhF4mH" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
    <author>
      <name>Chris</name>
    </author>
  </entry>
  <entry>
    <id>tag:errtheblog.com,2008:Post/86</id>
    <published>2008-02-16T21:19:00+00:00</published>
    <updated>2008-02-16T21:24:47+00:00</updated>
    <link type="text/html" rel="alternate" href="http://errtheblog.com/posts/86-sugary-adapters" />
    <title>Sugary Adapters</title>
    <content type="html">&lt;p&gt;Very recently, &lt;a href="http://www.redhillconsulting.com.au/blogs/simon/"&gt;Simon Harris&lt;/a&gt; had an idea: &lt;span class="code"&gt;nil?&lt;/span&gt; for Ambition.  Tasty sugar.&lt;/p&gt;


	&lt;p&gt;Let&amp;#8217;s figure out what it takes to make&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class="constant"&gt;User&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;select&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;x&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;x&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;nil?&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;behave just like&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class="constant"&gt;User&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;select&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;x&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;x&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="constant"&gt;nil&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;in Ambition.&lt;/p&gt;


	&lt;h3&gt;Short and Sweet&lt;/h3&gt;


	&lt;p&gt;Simon&amp;#8217;s approach was to modify Ambition directly to add support for &lt;span class="code"&gt;nil?&lt;/span&gt;.  While this is for sure ambitious, &lt;span class="code"&gt;nil?&lt;/span&gt; is just another method.  Not special.  The adapter should decide what to do with it.&lt;/p&gt;


	&lt;p&gt;Easy.  Here&amp;#8217;s what we added to the ActiveRecord adapter&amp;#8217;s Select translator:&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;nil?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;column&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;left&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;&lt;span class="expr"&gt;#{owner.table_name}&lt;/span&gt;.&lt;span class="expr"&gt;#{quote_column_name column}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; 
  &lt;span class="ident"&gt;negated?&lt;/span&gt; &lt;span class="punct"&gt;?&lt;/span&gt; &lt;span class="ident"&gt;not_equal&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;left&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;nil&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.==(&lt;/span&gt;&lt;span class="ident"&gt;left&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;nil&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;See it in action on &lt;a href="http://github.com/defunkt/ambition/tree/master/adapters/ambitious_activerecord/lib/ambition/adapters/active_record/select.rb#L84-87"&gt;lines 84 to 87&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;The tests, of course, can be found in &lt;a href="http://github.com/defunkt/ambition/tree/master/adapters/ambitious_activerecord/test/types_test.rb#L55-63"&gt;types_test&lt;/a&gt;.&lt;/p&gt;


	&lt;h3&gt;Chaining Stuffs&lt;/h3&gt;


	&lt;p&gt;So, how does this work?&lt;/p&gt;


	&lt;p&gt;Every adapter&amp;#8217;s Select translator has a special &lt;span class="code"&gt;chained_call&lt;/span&gt; method.  Ambition invokes &lt;span class="code"&gt;chained_call&lt;/span&gt; and passes it an array of symbols when a &lt;span class="code"&gt;chained.method.call&lt;/span&gt; is executed on itself.&lt;/p&gt;


	&lt;p&gt;In this case, the chain is &lt;span class="code"&gt;m.name.nil?&lt;/span&gt;.  Ambition knows that &lt;span class="code"&gt;m&lt;/span&gt; is itself and ignores it, passing &lt;span class="code"&gt;[ :name, :nil? ]&lt;/span&gt; to &lt;span class="code"&gt;chained_call&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;The ActiveRecord adapter&amp;#8217;s &lt;span class="code"&gt;chained_call&lt;/span&gt; method takes the passed array and, if it can find the second element, &lt;span class="code"&gt;sends&lt;/span&gt; it the first element.&lt;/p&gt;


	&lt;p&gt;Basically:&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class="comment"&gt;# methods = [ :name, :nil? ]&lt;/span&gt;
&lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;respond_to?&lt;/span&gt; &lt;span class="ident"&gt;methods&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
  &lt;span class="ident"&gt;send&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;methods&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;],&lt;/span&gt; &lt;span class="ident"&gt;methods&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;first&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;Which translates to:&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;nil?&lt;/span&gt; &lt;span class="symbol"&gt;:name&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;Cool.  Adapters don&amp;#8217;t need to set themselves up this way, but it works for ActiveRecord.&lt;/p&gt;


	&lt;p&gt;Notice: the ActiveRecord adapter doesn&amp;#8217;t support anything more than chains two methods deep.  It calls the second element and passes the first, ignoring the rest.  Almost discouraging, but chin up &amp;#8211; this is ActiveRecord specific.  Ambition itself supports chains of arbitrary length, and your adapter can, too.&lt;/p&gt;


	&lt;h3&gt;So array.include?, right?&lt;/h3&gt;


	&lt;p&gt;The thing is, &lt;span class="code"&gt;chained_call&lt;/span&gt; is only invoked when a chained method call is executed on an object Ambition owns.&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class="constant"&gt;User&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;select&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;x&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;x&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;nil?&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;In the above, Ambition owns the &lt;span class="code"&gt;x&lt;/span&gt;.  It&amp;#8217;s &lt;span class="code"&gt;self&lt;/span&gt; as far as the translator is concerned.&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class="constant"&gt;User&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;select&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;x&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="number"&gt;2&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="number"&gt;3&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt; &lt;span class="ident"&gt;x&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;id&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;Ambition does not own the array, only the &lt;span class="code"&gt;x.id&lt;/span&gt;.  So what happens?&lt;/p&gt;


	&lt;p&gt;Well, it&amp;#8217;s the same as &lt;span class="code"&gt;[1,2,3] == x.id&lt;/span&gt; to Ambition.  The dude really doesn&amp;#8217;t care.  Any time there is something like &lt;span class="code"&gt;left op right&lt;/span&gt;, Ambition calls &lt;span class="code"&gt;op(left, right)&lt;/span&gt; on your translator.&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s an idea of the call:&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;([&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="number"&gt;2&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="number"&gt;3&lt;/span&gt;&lt;span class="punct"&gt;],&lt;/span&gt; &lt;span class="ident"&gt;x&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;Luckily &lt;span class="code"&gt;x.id&lt;/span&gt; is translated for you prior to this.  The call really looks more like:&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;([&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="number"&gt;2&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="number"&gt;3&lt;/span&gt;&lt;span class="punct"&gt;],&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;users.id&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;The &lt;span class="code"&gt;include?&lt;/span&gt; definition, then, on ActiveRecord&amp;#8217;s translator is very straightforward:&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;left&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;right&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;left&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;left&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;map&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;element&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;sanitize&lt;/span&gt; &lt;span class="ident"&gt;element&lt;/span&gt; &lt;span class="punct"&gt;}.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;, &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;&lt;span class="expr"&gt;#{right}&lt;/span&gt; IN (&lt;span class="expr"&gt;#{left}&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;/pre&gt;

	&lt;p&gt;Beautiful.&lt;/p&gt;


	&lt;h3&gt;Join the Fun&lt;/h3&gt;


	&lt;p&gt;While the &lt;a href="http://twitter.com/err"&gt;Err twitter&lt;/a&gt; is great for general stuff, you should really hop on the &lt;a href="http://groups.google.com/group/ambition-rb"&gt;Ambition mailing list&lt;/a&gt; if you want in on this action.  Or just watch the project &lt;a href="http://github.com/defunkt/ambition"&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Til next time.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/errtheblog?a=7OBtWVE"&gt;&lt;img src="http://feeds.feedburner.com/~f/errtheblog?i=7OBtWVE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
    <author>
      <name>Chris</name>
    </author>
  </entry>
  <entry>
    <id>tag:errtheblog.com,2008:Post/82</id>
    <published>2008-01-29T22:46:00+00:00</published>
    <updated>2008-01-29T23:34:22+00:00</updated>
    <link type="text/html" rel="alternate" href="http://errtheblog.com/posts/82-adapting-ambitiously" />
    <title>Adapting Ambitiously</title>
    <content type="html">&lt;p&gt;It&amp;#8217;s funny, really. All these people walking around, talking about Ambition.  &amp;#8220;Oh, Ambition?  Yeah, pretty cool.&amp;#8221;  &amp;#8220;Ambition?  Impedance mismatch.&amp;#8221;  &amp;#8220;I&amp;#8217;m happy with &lt;span class="caps"&gt;SQL&lt;/span&gt;-92 the way it is, thank you very much.&amp;#8221;  Outrageous!&lt;/p&gt;


	&lt;p&gt;I know, I know.  We&amp;#8217;ve said some crazy things ourselves.  Like how we wanted Ambition to be a &lt;a href="http://errtheblog.com/posts/63-full-of-ambition"&gt;Rack for databases&lt;/a&gt;.  Or, far fetched as it sounds, how we hoped Ambition could &lt;a href="http://errtheblog.com/posts/64-even-more-ambitious"&gt;evolve into something akin to &lt;span class="caps"&gt;LINQ&lt;/span&gt;&lt;/a&gt;.  But we&amp;#8217;re done talking.&lt;/p&gt;


	&lt;p&gt;Today we want to show you some plain jane Ruby and how Ambition empowers it to leverage its inherent synergy.  Er, I mean, we want to show you something kickass.&lt;/p&gt;


	&lt;h3&gt;New School&lt;/h3&gt;


	&lt;p&gt;This is what we&amp;#8217;re used to:&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class="punct"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;SQL&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;User&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;select&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;m&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;m&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;jon&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="ident"&gt;m&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;age&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="number"&gt;21&lt;/span&gt; &lt;span class="punct"&gt;}.&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt;
&lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;SELECT * FROM users WHERE users.name = 'jon' AND users.age = 21&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; 
&lt;/pre&gt;

	&lt;p&gt;This is what&amp;#8217;s new:&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class="punct"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;LDAP&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;User&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;select&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;m&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;m&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;jon&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="ident"&gt;m&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;age&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="number"&gt;21&lt;/span&gt; &lt;span class="punct"&gt;}.&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt;
&lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;(&amp;amp;(name=jon)(age=21))&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; 
&lt;/pre&gt;

	&lt;h3&gt;Adapter School&lt;/h3&gt;


	&lt;p&gt;As of 0.5, Ambition is no longer a &lt;span class="caps"&gt;SQL&lt;/span&gt; wrapper.  Rather, it is an &lt;span class="caps"&gt;API&lt;/span&gt; for writing your own adapters.  If you&amp;#8217;d like to continue using the ActiveRecord version of Ambition, please install the &lt;span class="code"&gt;ambitious-activerecord&lt;/span&gt; gem:&lt;/p&gt;


	&lt;p&gt;&lt;span class="code"&gt;$ gem install ambitious-activerecord&lt;/span&gt;&lt;/p&gt;


	&lt;p&gt;Then, of course, use it:&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;rubygems&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;ambition/adapters/active_record&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;You can, too, install and use the older 0.3 series:&lt;/p&gt;


	&lt;p&gt;&lt;span class="code"&gt;$ gem install ambition -v 0.3.2&lt;/span&gt;&lt;/p&gt;


	&lt;p&gt;Anyway, you heard right: Ambition now supports arbitrary data stores.  Anything.  Ambition adapters are just gems which depend on &lt;span class="code"&gt;ambition&lt;/span&gt; and use its amazing &lt;span class="caps"&gt;API&lt;/span&gt; powers for the greater good.&lt;/p&gt;


	&lt;p&gt;What other adapters are underway?  Oh, I dunno.  How about ActiveLDAP, CouchDB, Facebook &lt;span class="caps"&gt;FQL&lt;/span&gt;, XPath, and DataMapper, to name a few.  Why, just the other night the &lt;a href="http://boston.rubygroup.org/"&gt;Boston.rb&lt;/a&gt; guys started working on a Sphinx adapter.  Check it out with git:&lt;/p&gt;


	&lt;p&gt;&lt;span class="code"&gt;$ git clone git://technicalpickles.com/ambitious_sphinx.git&lt;/span&gt;&lt;/p&gt;


	&lt;p&gt;We&amp;#8217;ve also got two example gems: &lt;a href="http://github.com/defunkt/ambition/tree/master/adapters/ambitious_activeldap"&gt;ambitious-activeldap&lt;/a&gt; and &lt;a href="http://github.com/defunkt/ambition/tree/master/adapters/ambitious_activerecord"&gt;ambitious-activerecord&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;There&amp;#8217;s basic documentation for Ambition&amp;#8217;s &lt;span class="caps"&gt;API&lt;/span&gt; over at &lt;a href="http://ambition.rubyforge.org"&gt;ambition.rubyforge.org&lt;/a&gt;, which you are free to peruse as well.&lt;/p&gt;


	&lt;p&gt;We&amp;#8217;re just starting out, but it&amp;#8217;s not a bad start.  Got an idea?  Something crazy?  We&amp;#8217;re all about it.  Jump on &lt;a href="http://groups.google.com/group/ambition-rb/"&gt;the mailing list&lt;/a&gt; or join &lt;span class="code"&gt;#ambition&lt;/span&gt; on irc.freenode.net then chime in.&lt;/p&gt;


	&lt;h3&gt;Dream School&lt;/h3&gt;


	&lt;p&gt;Let&amp;#8217;s take the &lt;span class="code"&gt;youtube-g&lt;/span&gt; gem, as an example.  There&amp;#8217;s no finished adapter for it yet so we&amp;#8217;re going to pretend.&lt;/p&gt;


	&lt;p&gt;Using the new Ambition, we could (behind the scenes) turn a query like this:&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class="constant"&gt;Videos&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;select&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;video&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;video&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;user&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;liz&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;Into this:&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class="constant"&gt;YouTubeG&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Client&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;videos_by&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:user&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;liz&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;We could turn a query like this:&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class="constant"&gt;Videos&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;select&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;video&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;video&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;tags&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;apple&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;Into this:&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class="constant"&gt;YouTubeG&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Client&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;videos_by&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:tags&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;apple&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;And we could even turn a query like this:&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class="constant"&gt;Videos&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;select&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;video&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; 
  &lt;span class="ident"&gt;video&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;tags&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;football&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="punct"&gt;!&lt;/span&gt;&lt;span class="ident"&gt;video&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;tags&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;soccer&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;Into this:&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class="constant"&gt;YouTubeG&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Client&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;videos_by&lt;/span&gt; &lt;span class="symbol"&gt;:tags&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; 
    &lt;span class="symbol"&gt;:include&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;football&lt;/span&gt;&lt;span class="punct"&gt;'],&lt;/span&gt; 
    &lt;span class="symbol"&gt;:exclude&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;soccer&lt;/span&gt;&lt;span class="punct"&gt;']&lt;/span&gt; 
  &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;Not bad.  It even comes with a generator, courtesy of &lt;a href="http://rubigen.rubyforge.org"&gt;Dr Nic&lt;/a&gt;, for spitting out an adapter scaffold:&lt;/p&gt;


	&lt;p&gt;&lt;span class="code"&gt;$ ambition_adapter ambitious_youtube&lt;/span&gt;&lt;/p&gt;


	&lt;h3&gt;Future School&lt;/h3&gt;


	&lt;p&gt;Got an idea for an adapter, or some code to show?  Throw it in the comments.  You better believe we&amp;#8217;ll keep the rest of you abreast of cool adapters, fancy tricks, and new features.&lt;/p&gt;


	&lt;p&gt;Want to get involved?  Like I said, there&amp;#8217;s always &lt;a href="http://groups.google.com/group/ambition-rb/"&gt;the list&lt;/a&gt; and the &lt;a href="http://github.com/defunkt/ambition/"&gt;GitHub repo&lt;/a&gt;.  Bugs can go to &lt;a href="http://err.lighthouseapp.com/projects/466-plugins/tickets"&gt;Lighthouse&lt;/a&gt; and you can clone my repo thisaways:&lt;/p&gt;


	&lt;p&gt;&lt;span class="code"&gt;$ git clone git://github.com/defunkt/ambition.git&lt;/span&gt;&lt;/p&gt;


	&lt;p&gt;Ah, how far we&amp;#8217;ve come.  And how far we&amp;#8217;ll go!  Here&amp;#8217;s to it.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/errtheblog?a=rZrh3mD"&gt;&lt;img src="http://feeds.feedburner.com/~f/errtheblog?i=rZrh3mD" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
    <author>
      <name>Chris</name>
    </author>
  </entry>
  <entry>
    <id>tag:errtheblog.com,2008:Post/78</id>
    <published>2008-01-23T07:45:00+00:00</published>
    <updated>2008-01-23T11:29:52+00:00</updated>
    <link type="text/html" rel="alternate" href="http://errtheblog.com/posts/78-feeds-for-free" />
    <title>Feeds for Free</title>
    <content type="html">&lt;p&gt;And money for nothing.  Or something like that?  Sorry, Mark Knopfler.  I&amp;#8217;ll pay more attention next time.&lt;/p&gt;


	&lt;p&gt;Anyways, let us be painfully aware that we can get Atom feeds for free.  Not as in beer or speech, but as in &amp;#8216;zero lines of code.&amp;#8217;  How?  Microformats.&lt;/p&gt;


	&lt;h3&gt;You and meFormats&lt;/h3&gt;


	&lt;p&gt;Almost a year has past since we last spoke of &lt;a href="http://errtheblog.com/posts/53-microformathingies"&gt;microformats&lt;/a&gt;, and way more than a year since our &lt;a href="http://errtheblog.com/posts/35-me-and-uformats"&gt;first encounter&lt;/a&gt;.  Seems like only yesterday.&lt;/p&gt;


	&lt;p&gt;Remember hAtom?  It&amp;#8217;s like Atom, only embedded into your existing content&amp;#8217;s &lt;span class="caps"&gt;HTML&lt;/span&gt; pages.  The &lt;a href="http://mofo.rubyforge.org/"&gt;mofo site&lt;/a&gt; references the following example:&lt;/p&gt;


	&lt;p&gt;A normal, typical blog post:&lt;/p&gt;


&lt;pre&gt;
&amp;lt;div class="post"&amp;gt;
  &amp;lt;h3&amp;gt;Megadeth Show Last Night&amp;lt;/h3&amp;gt;
  &amp;lt;span class="subtitle"&amp;gt;Posted by Chris on June 4th&amp;lt;/span&amp;gt;
  &amp;lt;div class="content"&amp;gt;
    Went to a show last night. Megadeth. 
    It was alright.
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;

	&lt;p&gt;The same post with hAtom superpowers:&lt;/p&gt;


&lt;pre&gt;
&amp;lt;div class="post hentry"&amp;gt;
  &amp;lt;h3 class="entry-title"&amp;gt;Megadeth Show Last Night&amp;lt;/h3&amp;gt;
  &amp;lt;span class="subtitle"&amp;gt;Posted by 
    &amp;lt;span class="author vcard fn"&amp;gt;Chris&amp;lt;/span&amp;gt; 
    on 
    &amp;lt;abbr class="updated" title="2006-06-04T10:32:10Z"&amp;gt;June 4th&amp;lt;/abbr&amp;gt;
  &amp;lt;/span&amp;gt;
  &amp;lt;div class="content entry-content"&amp;gt;
    Went to a show last night. Megadeth. It was alright.
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;

	&lt;p&gt;To you and I, eagerly searching for a review of last summer&amp;#8217;s Megadeth show, there is no difference between the two.  Our browsers render them the same.  To a machine, however, the second post is chock full of semantic goodness.&lt;/p&gt;


	&lt;p&gt;This semantic goodness represents, in our &lt;span class="caps"&gt;HTML&lt;/span&gt;, the same information an Atom feed would provide.  This leaves us with two paths of action for gettin&amp;#8217; our feed on: we can wait for &lt;a href="http://placenamehere.com/article/185/SubscribingTohAtomFeedsWithNetNewsWire"&gt;feed readers to start speaking hAtom fluently&lt;/a&gt;, or we can have someone &lt;a href="http://subtlety.errtheblog.com"&gt;translate hAtom to Atom&lt;/a&gt; for us.&lt;/p&gt;


	&lt;h3&gt;Subtlely Free Feeds&lt;/h3&gt;


	&lt;p&gt;One year ago today &lt;a href="http://subtlety.errtheblog.com"&gt;Subtlety&lt;/a&gt; was released.  Today it is re-released with a new feature: it can convert a page containing hAtom entries into an Atom feed.  This means your feeds are now officially free.&lt;/p&gt;


&lt;div align="center" style="padding-bottom:10px;"&gt;&lt;a href="http://subtlety.errtheblog.com"&gt;&lt;img src="/static/images/subtlety2.png" /&gt;&lt;/a&gt;&lt;/div&gt;

	&lt;p&gt;We&amp;#8217;ve actually been doing this for a while right here on Err.  Our &lt;a href="http://feeds.feedburner.com/errtheblog"&gt;Feedburner feed&lt;/a&gt; points to this url: &lt;a href="http://subtlety.errtheblog.com/O_o/29f.xml"&gt;http://subtlety.errtheblog.com/O_o/29f.xml&lt;/a&gt;.  It&amp;#8217;s an Atom feed generated by Subtlety after parsing the hAtom elements on this site.  On Err the Blog.&lt;/p&gt;


	&lt;p&gt;My &lt;a href="http://ozmm.org/"&gt;ozmm blog&lt;/a&gt; is a static blog with no special &lt;span class="caps"&gt;RSS&lt;/span&gt; code.  Instead, I point the Feedburner &lt;span class="caps"&gt;URL&lt;/span&gt; at a Subtlety Atom feed which is generated from the hAtom in the posts.  Our &lt;a href="http://dynamite.errfree.com/"&gt;Dynamite blog&lt;/a&gt; uses the same trick.  See the pattern?&lt;/p&gt;


	&lt;p&gt;There&amp;#8217;s no reason to ever write your own Atom feeds anymore.  Sorry.&lt;/p&gt;


	&lt;h3&gt;But what if I don&amp;#8217;t want you hosting my feeds?&lt;/h3&gt;


	&lt;p&gt;That&amp;#8217;s fine, and acceptable.  How about I just hand you the technology to do this on your own?&lt;/p&gt;


	&lt;p&gt;It goes like this:&lt;/p&gt;


&lt;pre&gt;
$ gem install mofo
$ cd rails_app/vendor/plugins
$ gem unpack mofo
&lt;/pre&gt;

	&lt;p&gt;Then, here&amp;#8217;s your controller:&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;PostsController&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;index&lt;/span&gt;
    &lt;span class="attribute"&gt;@posts&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;find&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:all&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;def &lt;/span&gt;&lt;span class="method"&gt;atom&lt;/span&gt;
    &lt;span class="ident"&gt;target&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;url_for&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:action&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="symbol"&gt;:index&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;render&lt;/span&gt; &lt;span class="symbol"&gt;:xml&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ident"&gt;hEntry&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;find&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;target&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;to_atom&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:title&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;whatever&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;/pre&gt;

	&lt;p&gt;You can use this trick for dynamically generated feeds (changelogs or activity feeds, perhaps) or whatever else.  Thanks, mofo.&lt;/p&gt;


	&lt;h3&gt;Last Step: Cut the Code&lt;/h3&gt;


	&lt;p&gt;Now go through your app and remove all the Atom code.  Drop those extra plugins, remove those xml templates, cut out all the special logic, and enjoy simple Subtlety or profound mofo.&lt;/p&gt;


	&lt;p&gt;Have fun.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/errtheblog?a=6syWWbD"&gt;&lt;img src="http://feeds.feedburner.com/~f/errtheblog?i=6syWWbD" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
    <author>
      <name>Chris</name>
    </author>
  </entry>
  <entry>
    <id>tag:errtheblog.com,2008:Post/73</id>
    <published>2008-01-07T13:32:00+00:00</published>
    <updated>2008-01-07T14:02:48+00:00</updated>
    <link type="text/html" rel="alternate" href="http://errtheblog.com/posts/73-the-jskinny-on-jquery" />
    <title>The jSkinny on jQuery</title>
    <content type="html">&lt;p&gt;j-j-j-jQuery.  It&amp;#8217;s on everyone&amp;#8217;s lips, right?  You love it or you hate it, or you&amp;#8217;ve never tried it but you love it, or you&amp;#8217;ve never tried it but you super-hate it.  Yeah, we know.&lt;/p&gt;


	&lt;p&gt;Well, PJ and I launched &lt;a href="http://famspam.com/"&gt;FamSpam&lt;/a&gt; a bit ago and made the bold move of powering all the jabbascript with &lt;a href="http://jquery.com"&gt;jQuery&lt;/a&gt;.  We even wrote our own Facbeook-style lightbox library in jQuery (&lt;a href="http://famspam.com/facebox/"&gt;Facebox&lt;/a&gt;).  So while this is a Ruby blog, indulge me for a moment as we dance with Ruby&amp;#8217;s ugly-cool half-sister: Javascript.&lt;/p&gt;


	&lt;h3&gt; whatQuery?&lt;/h3&gt;


	&lt;p&gt;There are a bajillion posts about jQuery, all of which introduce you gently, so I will be brief: jQuery is all about a single namespace and kickass querying.  (Get it?)&lt;/p&gt;


	&lt;p&gt;Our buddy Hpricot, you may remember, was heavily influenced by jQuery&amp;#8217;s selector syntax.  Which was, in turn, heavily influenced by &lt;span class="caps"&gt;CSS&lt;/span&gt; selectors.  As such, some of this may look familiar:&lt;/p&gt;


&lt;pre&gt;
$('#id').hide()
$('.class').css('height', 20)
$('#posts li &amp;gt; a').addClass('dark')
&lt;/pre&gt;

	&lt;p&gt;And so forth.  One of the fun things is that any of those &lt;span class="code"&gt;$()&lt;/span&gt; queries may return 0, 1, or more elements&amp;#8212;yet the code stays the same.  That&amp;#8217;s right: our &lt;span class="code"&gt;css()&lt;/span&gt; call would affect the height of all matched elements.  Same with the &lt;span class="code"&gt;addClass&lt;/span&gt;.  But, if nothing is found, it&amp;#8217;ll all silently fail.  jAwesome!&lt;/p&gt;


	&lt;h3&gt; niceQuery()&lt;/h3&gt;


	&lt;p&gt;While some of the recent &amp;#8220;jQuery vs &amp;lt;insert_framework_here&amp;gt;&amp;#8221; blog posts might not be so nice, jQuery itself certainly is: it (mostly) easily works alongside other libraries.  That means you can start dipping your toe into the jSauce while your Prototype or MooTools code doesn&amp;#8217;t suspect a thing.&lt;/p&gt;


	&lt;p&gt;It&amp;#8217;s easy:&lt;/p&gt;


&lt;pre&gt;
jQuery.noConflict()
&lt;/pre&gt;

My above examples would now be written like this:
&lt;pre&gt;
jQuery('#id').hide()
jQuery('.class').css('height', 20)
jQuery('#posts li &amp;gt; a').addClass('dark')
&lt;/pre&gt;

	&lt;p&gt;The &lt;span class="code"&gt;noConflict()&lt;/span&gt; call causes jQuery to defer ownership of &lt;span class="code"&gt;$()&lt;/span&gt; to Moo or Proto, leaving your current js intact.  How thoughtful.  Check more at the comprehensive &lt;a href="http://docs.jquery.com/Using_jQuery_with_Other_Libraries"&gt;doc site&lt;/a&gt;.&lt;/p&gt;


	&lt;h3&gt;chainQuery()&lt;/h3&gt;


	&lt;p&gt;jQuery is all about chaining, in a big way.  Here&amp;#8217;s an example from FamSpam:&lt;/p&gt;


&lt;pre&gt;
var person_email = $(this).parent().find('#person_email').val()
&lt;/pre&gt;

	&lt;p&gt;Pretty self explanatory.  The &lt;span class="code"&gt;find&lt;/span&gt; is scoped to the receiver, in this case the parent of the current element.&lt;/p&gt;


	&lt;p&gt;Another cool chain:&lt;/p&gt;


&lt;pre&gt;
$('#invite_error').show().text('Please enter an email and a name.')  
&lt;/pre&gt;

	&lt;p&gt;Hrm, we should probably put &lt;span class="code"&gt;text()&lt;/span&gt; before &lt;span class="code"&gt;show()&lt;/span&gt;, yeah?  I love these kind of questions!&lt;/p&gt;


	&lt;p&gt;Finally, a slightly more advanced chain:&lt;/p&gt;


&lt;pre&gt;
$('#facebox .body').children().hide().end().
append('&amp;lt;div class="loading"&amp;gt;&amp;lt;img src="'+$s.loading_image+'"/&amp;gt;&amp;lt;/div&amp;gt;')
&lt;/pre&gt;

	&lt;p&gt;Get it?  The &lt;span class="code"&gt;end()&lt;/span&gt; reverts the most recent &amp;#8216;destructive&amp;#8217; (read: find) operation.  So we start with the &lt;span class="code"&gt;.body&lt;/span&gt;, then find its children, then hide its children, then go back to &lt;span class="code"&gt;.body&lt;/span&gt; and append some html.  Slick, I think.  Real slick.&lt;/p&gt;


	&lt;p&gt;Like I said, the &lt;a href="http://docs.jquery.com/Traversing"&gt;doc site&lt;/a&gt; is super great.&lt;/p&gt;


	&lt;h3&gt;ujsQuery()&lt;/h3&gt;


	&lt;p&gt;Okay, here&amp;#8217;s the segue: jQuery has unobtrusiveness built in.  And it feels smooth.  Real smooth.&lt;/p&gt;


	&lt;p&gt;Here, a snippet straight from FamSpam&amp;#8217;s javascript:&lt;/p&gt;


&lt;pre&gt;
$('.reset_invite_form').click(function() {
  $('#new_person').resetForm()
  $('#invite_another').hide()
  $('#invite_another &amp;gt; span').remove()
  $('#new_person').show()
  return false
})
&lt;/pre&gt;

	&lt;p&gt;Pretty simple, right?  And clear, to boot.  What we do is slip this code inside of a function passed to &lt;span class="code"&gt;$(document).ready()&lt;/span&gt;, which will be run when the, erm, document is, uh, ready.&lt;/p&gt;


Like this:
&lt;pre&gt;
$(document).ready(function {
  $('.reset_invite_form').click(function() {
    ... stuff ...
  })
})
&lt;/pre&gt;

	&lt;p&gt;So on and so forth.  We attach Facebox to links the same way:&lt;/p&gt;


&lt;pre&gt;
if ($.facebox)
  $('a[rel*=facebox]').facebox()
&lt;/pre&gt;

	&lt;p&gt;If the Facebox plugin is loaded, we find any links with a &lt;span class="code"&gt;rel&lt;/span&gt; of &amp;#8220;facebox&amp;#8221; and convert them from normal links into jsery&amp;#8217;d Facebox links.  Easy as pie.&lt;/p&gt;


	&lt;p&gt;Which brings us, of course, to the segue.&lt;/p&gt;


	&lt;h3&gt;spamQuery()&lt;/h3&gt;


	&lt;p&gt;How are we using jQuery on FamSpam?  &lt;a href="http://ennerchi.com/projects/jrails"&gt;jRails&lt;/a&gt;?  Something custom?  By hand?!&lt;/p&gt;


	&lt;p&gt;Yeah, well, by hand.  We add all our behavior unobtrusively using the method detailed above.  As far as I know, there&amp;#8217;s no javascript in our html.  If there is it&amp;#8217;s on the run.  For its life.&lt;/p&gt;


	&lt;p&gt;If you want to peep around, the js is (predictably) right here: &lt;a href="http://pastie.caboo.se/136116"&gt;http://famspam.com/javascripts/application.js&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Something to note: as of writing (1.2.2), jQuery doesn&amp;#8217;t play nicely with Rails&amp;#8217; &lt;span class="code"&gt;respond_to&lt;/span&gt;.  But, hold the phone, it&amp;#8217;s okay: a simple fix.  &lt;a href="http://ozmm.org/posts/jquery_and_respond_to.html"&gt;Right here&lt;/a&gt;:&lt;/p&gt;


&lt;pre&gt;
jQuery.ajaxSetup({ 
  'beforeSend': function(xhr) {xhr.setRequestHeader("Accept",
    "text/javascript")} 
})  
&lt;/pre&gt;

	&lt;p&gt;You&amp;#8217;re now ready to rock.&lt;/p&gt;


	&lt;p&gt;Oh, one more thing before we move on: if you want some ajax-flavored will_paginate, check out &lt;a href="http://ozmm.org/posts/ajax_will_paginate_jq_style.html"&gt;this short guide&lt;/a&gt;.  It was mentioned in another post, and now it&amp;#8217;s mentioned here.&lt;/p&gt;


	&lt;h3&gt;plugQuery()&lt;/h3&gt;


	&lt;p&gt;jQuery, you see, has a wonderfully simple plugin system.  We take full advantage of it by using a few choice plugins.  Here&amp;#8217;s a taste to wet your pallet.&lt;/p&gt;


	&lt;p&gt;The most essential plugin is the &lt;a href="http://www.malsup.com/jquery/form/"&gt;jQuery Form Plugin&lt;/a&gt;.  With it, you can unobtrusively convert normal forms into ajax forms.  The (obvious) advantage of this is graceful degradation, which is very kind but also very courageous.&lt;/p&gt;


&lt;pre&gt;
$('#new_person').ajaxForm(function() { alert('Atta boy!') })
&lt;/pre&gt;

	&lt;p&gt;Seriously.  Simple.  And just so perfect for Rails&amp;#8212;all the form&amp;#8217;s attributes stay the same, including its &lt;span class="code"&gt;action&lt;/span&gt; and &lt;span class="code"&gt;method&lt;/span&gt;, just now it&amp;#8217;s submitted through ajax.  &lt;span class="code"&gt;respond_to&lt;/span&gt; and jQuery are so in love it&amp;#8217;s making me sick.&lt;/p&gt;


	&lt;p&gt;Another plugin we use is the &lt;a href="http://tablesorter.com/docs/"&gt;Tablesorter&lt;/a&gt;.  While we don&amp;#8217;t have much tabular data on the promo or family sides of FamSpam, our admin interface is full of it.  Want to sort your families by number of members?  Conversations?  Photos?  It&amp;#8217;s one line of code with this plugin.  Sure, we&amp;#8217;ll have to do some more complicated server-side sorting as our database grows, but this does the trick so quick right now.&lt;/p&gt;


&lt;pre&gt;
$('#sorted_table').tablesorter()
&lt;/pre&gt;

	&lt;p&gt;See?&lt;/p&gt;


	&lt;p&gt;Another plugin we really love is the &lt;a href="http://blue-anvil.com/archives/anti-aliased-rounded-corners-with-jquery"&gt;anti-aliased rounded corner plugin&lt;/a&gt;.  Unfortunately this is not the most popular rounded corner plugin for jQuery, and that&amp;#8217;s a shame.  A damn shame.  Because it&amp;#8217;s definitely the best.  We use it on the home page and other places we thought could use some class.&lt;/p&gt;


	&lt;p&gt;As usual, it&amp;#8217;s dead simple once installed:&lt;/p&gt;


&lt;pre&gt;
$('.corner').corner()  
&lt;/pre&gt;

	&lt;p&gt;You don&amp;#8217;t have to be so generic with it, but we like to be.&lt;/p&gt;


	&lt;p&gt;Finally, the brand new &lt;a href="http://plugins.jquery.com/project/jq-autocomplete"&gt;autocomplete plugin&lt;/a&gt; by &lt;a href="http://reinh.com/"&gt;ReinH&lt;/a&gt; and &lt;a href="http://yehudakatz.com/"&gt;wycats&lt;/a&gt; is simple, small, and slick.  See a pattern here?  We&amp;#8217;re using this on our admin site and couldn&amp;#8217;t be happier.  It speaks &lt;span class="caps"&gt;JSON&lt;/span&gt;, baby.  Sign me up.&lt;/p&gt;


	&lt;h3&gt;thatsitQuery()&lt;/h3&gt;


	&lt;p&gt;Thanks for letting us stray for a moment from our normally dreary discourse.  Got any other cool jQuery tips or treats?  Leave &amp;#8216;em in the comments.&lt;/p&gt;


	&lt;p&gt;Oh, a parting gift.  More code to chew on: &lt;a href="http://pastie.caboo.se/136115"&gt;our tour.js&lt;/a&gt;.  We use it to power the &lt;a href="http://famspam.com/tour"&gt;FamSpam tour&lt;/a&gt;.  Enjoy.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/errtheblog?a=uh8oeTD"&gt;&lt;img src="http://feeds.feedburner.com/~f/errtheblog?i=uh8oeTD" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
    <author>
      <name>Chris</name>
    </author>
  </entry>
  <entry>
    <id>tag:errtheblog.com,2008:Post/69</id>
    <published>2007-12-25T19:57:08+00:00</published>
    <updated>2007-12-25T20:19:50+00:00</updated>
    <link type="text/html" rel="alternate" href="http://errtheblog.com/posts/69-paginatin-christmas" />
    <title>Paginatin' Christmas</title>
    <content type="html">&lt;p&gt;In a timely holiday manner, we present to you a short list of &lt;span class="code"&gt;will_paginate&lt;/span&gt; resources.  Please enjoy responsibly.&lt;/p&gt;


&lt;div align="center"&gt;
&lt;img src="http://errtheblog.com/static/images/william_paginate.png" alt="will paginate" /&gt;
&lt;/div&gt;

	&lt;h3&gt;Sightings&lt;/h3&gt;


	&lt;p&gt;Since its inception, millions of people have paginated billions of records using &lt;span class="code"&gt;will_paginate&lt;/span&gt;.  A few notable examples:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Err Free&amp;#8217;s &lt;a href="http://famspam.com/"&gt;FamSpam&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://realworldcasting.mtv.com/browse/recent_voters"&gt;&lt;span class="caps"&gt;MTV&lt;/span&gt;&amp;#8217;s Real World Casting&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://beast.caboo.se/forums/1"&gt;Beast&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://warehouseapp.com/"&gt;Warehouse&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.demontrondrv.com/inventory/"&gt;DeMontrond RV&lt;/a&gt; (with ajax!)&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://grabb.it/grabs"&gt;Grabb.it&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Know a site that belongs on this list?  Let us know in the comments.&lt;/p&gt;


	&lt;h3&gt;New Features&lt;/h3&gt;


	&lt;p&gt;Just in time for the holidays, Mislav has gifted us all with a bucket o&amp;#8217; new features for &lt;span class="code"&gt;will_paginate&lt;/span&gt;, mostly dealing with customizing the output.  Take a look at his &lt;a href="http://groups.google.com/group/will_paginate/browse_frm/thread/d5c8a5bc356cd296"&gt;announcement&lt;/a&gt; and dive in.&lt;/p&gt;


	&lt;h3&gt;Testing Your Views&lt;/h3&gt;


	&lt;p&gt;For those of us constantly asking the &lt;a href="http://errtheblog.com/posts/66-view-testing-20"&gt;view testing question&lt;/a&gt;, stern but fair &lt;span class="code"&gt;will_paginate&lt;/span&gt; maintainer Mislav comes to the rescue with his aptly titled &lt;a href="http://mislav.caboo.se/rails/will_paginate-and-view-testing/"&gt;will_paginate and view testing&lt;/a&gt; article.  It&amp;#8217;s in-depth, so be sure to check it out.  Also: subscribe to his blog.  &lt;a href="http://mislav.caboo.se/feeds/dev"&gt;Immediately&lt;/a&gt;.&lt;/p&gt;


	&lt;h3&gt;Ajax Pagination&lt;/h3&gt;


	&lt;p&gt;This Ajax thing is going to be huge!  Get in on the action with Matt Aimonetti&amp;#8217;s &lt;a href="http://www.railsontherun.com/2007/9/27/ajax-pagination-in-less-than-5-minutes"&gt;Ajax Pagination in less than 5 minutes&lt;/a&gt; article.  He&amp;#8217;ll teach you how to unobtrusively add Ajax behavior to &lt;span class="code"&gt;will_paginate&lt;/span&gt; using Prototype, LowPro, and &lt;span class="caps"&gt;RJS&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;If you&amp;#8217;re more of the &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; type, check out the &lt;a href="http://ozmm.org/posts/ajax_will_paginate_jq_style.html"&gt;Ajax will_paginate, jq-style&lt;/a&gt; article over at ozmm.&lt;/p&gt;


	&lt;h3&gt;The RailsCast&lt;/h3&gt;


	&lt;p&gt;The prolific Ryan Bates has a screencast explaining the basics of WP.  As always, it&amp;#8217;s to the point and very well done.  And hey, you can even watch it on your iPod! &lt;a href="http://railscasts.com/episodes/51"&gt;Have a look&lt;/a&gt;.&lt;/p&gt;


	&lt;h3&gt;will_paginate without ActiveRecord&lt;/h3&gt;


	&lt;p&gt;There&amp;#8217;s only a few things I like more than websites with tildes in the &lt;span class="caps"&gt;URL&lt;/span&gt;.  Like, say, twisting Rails plugins into non-Rails uses.  Lucky for us, Erin Ptacek provides both in an entry titled &lt;a href="http://mingu.sping.us/~erin/blog/2007/11/erins-adventures-with-rails.html"&gt;Erin&amp;#8217;s Adventures with Rails: will_paginate without ActiveRecord&lt;/a&gt;.  In it, you&amp;#8217;ll learn how to paginate a collection of &lt;span class="code"&gt;OpenStruct&lt;/span&gt; objects.  No &lt;span class="code"&gt;ActiveRecord&lt;/span&gt; required.  What a rush.&lt;/p&gt;


	&lt;h3&gt;Ferret Integration&lt;/h3&gt;


	&lt;p&gt;Brandon Keepers, that handsome devil, wrote &lt;a href="http://opensoul.org/2007/8/17/acts_as_ferret-will_paginate"&gt;a popular article&lt;/a&gt; detailing the steps necessary to paginate your Ferret search results using good ol&amp;#8217; WP.  If you&amp;#8217;re using Ferret, this is definitely the way to go.&lt;/p&gt;


	&lt;h3&gt;Solr Integration&lt;/h3&gt;


	&lt;p&gt;While I don&amp;#8217;t know what &amp;#8216;The Pug Automatic&amp;#8217; means, and I certainly know nothing of the RoboPug in said blog&amp;#8217;s header, Henrik Nyh&amp;#8217;s article on &lt;a href="http://henrik.nyh.se/2007/06/using-will_paginate-with-acts_as_solr"&gt;paginating acts_as_solr with will_paginate&lt;/a&gt; is an undeniable must read for any Java lovin&amp;#8217;, Apache huggin&amp;#8217; Solr user wanting to add a bit of style and flair into his app.&lt;/p&gt;


	&lt;h3&gt;acts_as_taggable Integration&lt;/h3&gt;


	&lt;p&gt;Perhaps as contentious as the comments and &lt;a href="http://groups.google.com/group/will_paginate/browse_frm/thread/d4202c15a572b75b/f64a4f4388e99df8?lnk=gst&amp;#38;q=acts_as_taggable_on_steroids#f64a4f4388e99df8"&gt;this thread&lt;/a&gt; suggest, Jim Morris&amp;#8217; &lt;a href="http://blog.wolfman.com/articles/2007/07/30/paginating-acts_as_taggable-with-will_paginate"&gt;Paginating acts_as_taggable&lt;/a&gt; article offers a few ways to make both the &lt;span class="code"&gt;on_steroids&lt;/span&gt; variant of &lt;span class="code"&gt;acts_as_taggable&lt;/span&gt; plugin and &lt;span class="code"&gt;will_paginate&lt;/span&gt; play nicely together.&lt;/p&gt;


	&lt;h3&gt;Rails Plugins&lt;/h3&gt;


	&lt;p&gt;A number of Rails plugins have been released with support for &lt;span class="code"&gt;will_paginate&lt;/span&gt; lovingly baked in.  Like a Santa shaped sugar cookie.&lt;/p&gt;


	&lt;p&gt;SpinBits&amp;#8217; &lt;a href="http://code.spinbits.com/simply_searchable.html"&gt;SimplySearchable&lt;/a&gt; helps you search in style while providing options to paginate using our friend WP.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://blog.evanweaver.com/files/doc/fauna/ultrasphinx/files/README.html"&gt;UltraSphinx&lt;/a&gt;, Evan Weaver&amp;#8217;s preeminent &lt;a href="http://www.sphinxsearch.com/"&gt;Sphinx search engine&lt;/a&gt; plugin, longs to be installed alongside &lt;span class="code"&gt;will_paginate&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;While &lt;span class="code"&gt;will_paginate&lt;/span&gt;, due to popular demand, plays nicely with &lt;a href="http://code.google.com/p/scope-out-rails/"&gt;scope_out&lt;/a&gt;, Nick Kallen&amp;#8217;s similar &lt;a href="http://pivots.pivotallabs.com/users/nick/blog/articles/284-hasfinder-it-s-now-easier-than-ever-to-create-complex-re-usable-sql-queries"&gt;HasFinder&lt;/a&gt; works technically and conceptually well with everyone&amp;#8217;s favorite paginator.&lt;/p&gt;


	&lt;p&gt;And finally, how can we neglect to mention &lt;a href="http://douglasfshearer.com/blog/rails-plugin-will_paginate_search"&gt;Will_Paginate_Search&lt;/a&gt;, which hooks into both WP and acts_as_indexed to the benefit of all involved parties.&lt;/p&gt;


	&lt;h3&gt;The Bugtracker&lt;/h3&gt;


	&lt;p&gt;Found a bug?  Got an idea?  Of course we&amp;#8217;d love to hear it.  Our &lt;a href="http://err.lighthouseapp.com/projects/466-plugins/tickets"&gt;Lighthouse tracker&lt;/a&gt;, which we love is the place for all of it.&lt;/p&gt;


	&lt;h3&gt;The Google Group&lt;/h3&gt;


	&lt;p&gt;Did you catch it above?  Yep, you did.  So observant: there&amp;#8217;s now a &lt;a href="http://groups.google.com/group/will_paginate/"&gt;Google Group&lt;/a&gt; for &lt;span class="code"&gt;will_paginate&lt;/span&gt;.  Be sure to join up and chime in.&lt;/p&gt;


	&lt;h3&gt;Nightly RDoc&lt;/h3&gt;


	&lt;p&gt;Finally, RDoc is now generated nightly from the latest code in Subversion.  Check it out at &lt;a href="http://rock.errtheblog.com/will_paginate"&gt;the Rock&lt;/a&gt;.  It&amp;#8217;s like Christmas every day!&lt;/p&gt;


	&lt;h3&gt;That&amp;#8217;s a wrap&lt;/h3&gt;


	&lt;p&gt;Hey, where did 2007 go?  I&amp;#8217;m getting sucked into 2008 faster than Perl into obscurity.&lt;/p&gt;


	&lt;p&gt;Keep paginatin&amp;#8217;, Railers.  See you next year.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/errtheblog?a=8MaqW6C"&gt;&lt;img src="http://feeds.feedburner.com/~f/errtheblog?i=8MaqW6C" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
    <author>
      <name>Chris</name>
    </author>
  </entry>
  <entry>
    <id>tag:errtheblog.com,2008:Post/67</id>
    <published>2007-11-20T01:24:40+00:00</published>
    <updated>2007-12-07T00:20:28+00:00</updated>
    <link type="text/html" rel="alternate" href="http://errtheblog.com/posts/67-evil-twin-plugin" />
    <title>Evil Twin Plugin</title>
    <content type="html">&lt;p&gt;Seriously, I think I have something against Rails&amp;#8217; &lt;span class="code"&gt;lib&lt;/span&gt; directory.  We jumped from keeping gems in &lt;span class="code"&gt;lib&lt;/span&gt; to &lt;span class="code"&gt;vendor/gems&lt;/span&gt; &lt;a href="http://errtheblog.com/post/2120"&gt;back in March&lt;/a&gt;.  Then we jumped from keeping generic Rake tasks in &lt;span class="code"&gt;lib/tasks&lt;/span&gt; to &lt;a href="http://errtheblog.com/post/6069"&gt;Sake&lt;/a&gt;.  Now we&amp;#8217;re gonna jump again.&lt;/p&gt;


	&lt;h3&gt;Hacking Plugins&lt;/h3&gt;


	&lt;p&gt;It&amp;#8217;s really not that big of a deal, and pretty common&amp;#8212;you want to change the behavior of some existing plugin.  Maybe you &lt;a href="http://www.rubyinside.com/advent2006/12-piston.html"&gt;Piston&lt;/a&gt; it and commit your changes.  Sure.  But maybe you just want to leave the original code alone.&lt;/p&gt;


	&lt;p&gt;A classic approach has been to stick some kind of hack in the &lt;span class="code"&gt;lib&lt;/span&gt; directory.  Issues abound, for sure.  First: the load order.  Who gets loaded first?  Who reloads and who doesn&amp;#8217;t?  Second: location.  You&amp;#8217;ve got one bit of code messing with another bit of code in a totally separate location.  Third: testing.  Are you testing it?  Maybe.&lt;/p&gt;


	&lt;p&gt;None of these things are deal breakers, but we can certainly address them.  And we will.&lt;/p&gt;


	&lt;h3&gt;The Evil Twin Plugin&lt;/h3&gt;


&lt;div align="center" style="margin-bottom:10px;"&gt;
  &lt;img src="http://errtheblog.com/static/images/eviltwin.jpg" alt="Evil Twin" /&gt;
&lt;/div&gt;

	&lt;p&gt;Here&amp;#8217;s the simple solution: create a plugin called &lt;span class="code"&gt;whatever_hacks&lt;/span&gt;, where &lt;em&gt;whatever&lt;/em&gt; is the name of the plugin you&amp;#8217;re hacking.  That&amp;#8217;s it.  An evil twin, if you will.&lt;/p&gt;


	&lt;p&gt;Adding the &lt;em&gt;_hacks&lt;/em&gt; suffix ensures it will always be loaded after the target plugin (assuming you haven&amp;#8217;t messed with the default plugin load order&amp;#8212;alphabetical).  Keeping it right next to the target plugin also ensures anyone who peers into &lt;span class="code"&gt;vendor/plugins&lt;/span&gt; will instantly know tomfoolery is afoot.&lt;/p&gt;


	&lt;p&gt;You can now build out a tested, hack happy plugin.  Or, y&amp;#8217;know, just stick it all in &lt;span class="code"&gt;init.rb&lt;/span&gt;.  With caution.&lt;/p&gt;


	&lt;h3&gt;Caution: init.rb&lt;/h3&gt;


	&lt;p&gt;Caution: &lt;span class="code"&gt;init.rb&lt;/span&gt; does not always do what you expect it to do.  It&amp;#8217;s loaded in the context of &lt;span class="code"&gt;Rails::Plugin&lt;/span&gt; in 2.0 and &lt;span class="code"&gt;Rails::Initializer&lt;/span&gt; in 1.2.5, not &lt;span class="code"&gt;Object&lt;/span&gt;.  Come again?  Like this: re-opening existing classes isn&amp;#8217;t as straightforward as elsewhere.&lt;/p&gt;


=&amp;gt; &lt;strong&gt;init.rb&lt;/strong&gt;
&lt;pre class='ruby'&gt;
&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Hash&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="constant"&gt;Hash&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;inspect&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;Guess what that prints.  Ready?&lt;/p&gt;


&lt;pre&gt;
$ ./script/runner 
Rails::Plugin::Hash
&lt;/pre&gt;

	&lt;p&gt;That&amp;#8217;s right&amp;#8212;we didn&amp;#8217;t re-open &lt;span class="code"&gt;Hash&lt;/span&gt;, we created a new &lt;span class="code"&gt;Rails::Plugin::Hash&lt;/span&gt; class.  Any methods we add in there won&amp;#8217;t be added to &lt;span class="code"&gt;Hash&lt;/span&gt; proper.&lt;/p&gt;


	&lt;p&gt;If we want to grab a real class and stuff some methods in it, we need to use &lt;span class="code"&gt;class_eval&lt;/span&gt; or &lt;span class="code"&gt;module_eval&lt;/span&gt;:&lt;/p&gt;


=&amp;gt; &lt;strong&gt;init.rb&lt;/strong&gt;
&lt;pre class='ruby'&gt;
&lt;span class="constant"&gt;Hash&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;class_eval&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;duck_punched?&lt;/span&gt;
    &lt;span class="constant"&gt;true&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;puts&lt;/span&gt;&lt;span class="punct"&gt;({}.&lt;/span&gt;&lt;span class="ident"&gt;duck_punched?&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;As expected:&lt;/p&gt;


&lt;pre&gt;
$ ./script/runner 
true
&lt;/pre&gt;

	&lt;p&gt;Doing it this way (&lt;span class="code"&gt;class_eval&lt;/span&gt;) forces a constant lookup, making Ruby happily run up the chain and find the class or module in question.&lt;/p&gt;


	&lt;h3&gt;attachment_fu_cropper&lt;/h3&gt;


	&lt;p&gt;Okay, time for a real example.  I wanted to change attachment_fu&amp;#8217;s &lt;span class="code"&gt;ImageScienceProcessor&lt;/span&gt; to crop thumbnails before resizing them.  As this is a hack I use on all my apps, I also want to keep it out of my models.  Hence, &lt;span class="code"&gt;attachment_fu_hacks&lt;/span&gt;.&lt;/p&gt;


=&amp;gt; &lt;strong&gt;vendor/plugins/attachment_fu_hacks/init.rb&lt;/strong&gt;
&lt;pre class='ruby'&gt;
&lt;span class="ident"&gt;klass&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Technoweenie&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;AttachmentFu&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Processors&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;ImageScienceProcessor&lt;/span&gt;
&lt;span class="ident"&gt;klass&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;module_eval&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
  &lt;span class="comment"&gt;##&lt;/span&gt;
  &lt;span class="comment"&gt;# Hacked to use image_science's #cropped_thumbnail method&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;resize_image&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;img&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;size&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="comment"&gt;# create a dummy temp file to write to&lt;/span&gt;
    &lt;span class="ident"&gt;filename&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;sub!&lt;/span&gt; &lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;gif&lt;/span&gt;&lt;span class="global"&gt;$/&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;png&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
    &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;temp_path&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;write_to_temp_file&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;filename&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;grab_dimensions&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;lambda&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;img&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;width&lt;/span&gt;  &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;img&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;width&lt;/span&gt;  &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;respond_to?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:width&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;height&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;img&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;height&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;respond_to?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:height&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="ident"&gt;img&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;save&lt;/span&gt; &lt;span class="ident"&gt;temp_path&lt;/span&gt;
      &lt;span class="ident"&gt;callback_with_args&lt;/span&gt; &lt;span class="symbol"&gt;:after_resize&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;img&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="ident"&gt;size&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;size&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;first&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;size&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;is_a?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;Array&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="ident"&gt;size&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;size&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;is_a?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;Fixnum&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;||&lt;/span&gt; 
        &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;size&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;is_a?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;Array&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="ident"&gt;size&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;first&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;is_a?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;Fixnum&lt;/span&gt;&lt;span class="punct"&gt;))&lt;/span&gt;
      &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;size&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;is_a?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;Fixnum&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
        &lt;span class="ident"&gt;img&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;cropped_thumbnail&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;size&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ident"&gt;grab_dimensions&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="keyword"&gt;else&lt;/span&gt;
        &lt;span class="ident"&gt;img&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;cropped_thumbnail&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;size&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;first&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ident"&gt;grab_dimensions&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;else&lt;/span&gt; 
      &lt;span class="ident"&gt;new_size&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;img&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;width&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;img&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;height&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;dim&lt;/span&gt; &lt;span class="ident"&gt;size&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt;

      &lt;span class="ident"&gt;img&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;cropped_thumbnail&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;new_size&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;first&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ident"&gt;grab_dimensions&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;end&lt;/span&gt; 
&lt;/pre&gt;

	&lt;p&gt;Works like a charm.&lt;/p&gt;


	&lt;p&gt;When &lt;a href="http://locusfoc.us/"&gt;heavysixer&lt;/a&gt; wanted to hack &lt;span class="code"&gt;acts_as_taggable&lt;/span&gt;, he took the same approach: &lt;a href="http://pastie.caboo.se/119904"&gt;http://pastie.caboo.se/119904&lt;/a&gt;.  Feel free to follow suit.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/errtheblog?a=xhJF3rC"&gt;&lt;img src="http://feeds.feedburner.com/~f/errtheblog?i=xhJF3rC" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
    <author>
      <name>Chris</name>
    </author>
  </entry>
  <entry>
    <id>tag:errtheblog.com,2008:Post/66</id>
    <published>2007-09-18T20:49:30+00:00</published>
    <updated>2007-12-07T00:20:28+00:00</updated>
    <link type="text/html" rel="alternate" href="http://errtheblog.com/posts/66-view-testing-20" />
    <title>View Testing 2.0</title>
    <content type="html">&lt;p&gt;I&amp;#8217;ve come to realize how anti-web 2.0 this blog really is.  Why are we, the authors, doing all the work?!  Where is the user generated content?  How can we pretend to be Rails developers when we waste our time writing all these blog posts!&lt;/p&gt;


	&lt;p&gt;No longer.  Today all that changes.  It&amp;#8217;s time you guys start pulling your weight.&lt;/p&gt;


&lt;div align="center" style="margin-bottom:5px;"&gt;&lt;a href="http://errtheblog.com/static/images/web20.png"&gt;&lt;img src="http://errtheblog.com/static/images/web20-small.png" /&gt;&lt;/a&gt;&lt;/div&gt;

	&lt;h3&gt;Let&amp;#8217;s Talk About Testing Views&lt;/h3&gt;


	&lt;p&gt;There seem to be about a bajillion different solutions to the &amp;#8216;problem&amp;#8217; of testing views.  If you&amp;#8217;re into testing and also into Rails, my guess is you&amp;#8217;ve tried a few different styles before settling on your current method.  (hey, me too)&lt;/p&gt;


	&lt;p&gt;What I would love is for you to post your current, favorite, flavor-of-the-month style of view testing.  What library do you use, where can we download it, and how about some sample code?&lt;/p&gt;


	&lt;p&gt;When commenting, wrap your code in &amp;lt;code&amp;gt;code tags&amp;lt;/code&amp;gt; and use &amp;quot;textile&amp;quot;:http://textism.com/tools/textile/ for links.&lt;/p&gt;


	&lt;p&gt;Everyone has different taste, but the hope is we&amp;#8217;ll have enough options for people to find something they like.  Something tasty.&lt;/p&gt;


	&lt;p&gt;Hit me!&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/errtheblog?a=n6YvtqC"&gt;&lt;img src="http://feeds.feedburner.com/~f/errtheblog?i=n6YvtqC" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
    <author>
      <name>Chris</name>
    </author>
  </entry>
</feed>
