<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Lambda Calculator (Alex Reisner)</title>
    <link>http://code.alexreisner.com/</link>
    <description></description>
    <ttl>30</ttl>
    <language>en-us</language>


    <item>
      <title>Eff You Foo Bar</title>
      <author>Alex Reisner</author>
      <pubDate>2012-11-11T00:00:00-08:00</pubDate>
      <link>http://code.alexreisner.com/articles/eff-you-foo-bar.html</link>
      <guid>http://code.alexreisner.com/articles/eff-you-foo-bar.html</guid>
      <description>&lt;p&gt;Consider this Ruby code:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new?&lt;/span&gt;
  &lt;span class=&quot;vi&quot;&gt;@new_bar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;
  &lt;span class=&quot;vi&quot;&gt;@new_bar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;baz&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_current_baz_value&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bars&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:baz&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Whoever writes code like this should receive a swift foo in the baz.&lt;/p&gt;
&lt;p&gt;In case you didn&amp;#8217;t know, variables in programming are used to represent &lt;em&gt;things&lt;/em&gt;. Let&amp;#8217;s examine:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;foo &amp;#8211; &lt;em&gt;not a thing&lt;/em&gt; (unless you know your military terminology)&lt;/li&gt;
	&lt;li&gt;bar &amp;#8211; a place to drink; a rod; 100,000 N/m²&lt;/li&gt;
	&lt;li&gt;baz &amp;#8211; &lt;em&gt;not a thing&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Variable names are important because they illustrate the relationships between objects in code. If you&amp;#8217;re using sample code to &lt;em&gt;explain&lt;/em&gt; something to someone then variable names are equally, if not more important. Let&amp;#8217;s say you have two objects with a hierarchical relationship. Why would you write this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Larry&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add_moe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shemp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;when you can write this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Node&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add_child&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;With proper variable names you don&amp;#8217;t need to explain that a Larry is a thing that has one shemp and many moes. It&amp;#8217;s obvious to anyone who knows about tree-like data structures. When you use the word &amp;#8216;shemp&amp;#8217; in your code you have to explain what a &amp;#8216;shemp&amp;#8217; is, and &lt;strong&gt;if you need to explain your variable names then your variable names suck&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Not only are foo, bar, and baz completely uninformative and requiring of external explanation, they are &lt;em&gt;even worse&lt;/em&gt; than larry, moe, and shemp because &amp;#8220;bar&amp;#8221; and &amp;#8220;baz&amp;#8221; look the same!&lt;/p&gt;
&lt;p&gt;Please, stop using foo, bar, and baz. You can do so much better.&lt;/p&gt;</description>
    </item>

    <item>
      <title>Building APIs With Rails</title>
      <author>Alex Reisner</author>
      <pubDate>2011-05-20T00:00:00-07:00</pubDate>
      <link>http://code.alexreisner.com/articles/building-apis-with-rails.html</link>
      <guid>http://code.alexreisner.com/articles/building-apis-with-rails.html</guid>
      <description>&lt;p&gt;Yesterday at RailsConf Yehuda Katz gave an excellent talk on &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; design with Rails. He gave some good advice, including:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Use Rails. Most people don&amp;#8217;t realize how much Rails does for them and try to use Sinatra instead. Don&amp;#8217;t do it.&lt;/li&gt;
	&lt;li&gt;Always include keys at the root level that explain what the data is. (That is, don&amp;#8217;t just return a bunch of attributes. Note that valid &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; requires this but somehow people forget that it&amp;#8217;s a good idea when they start using &lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt;.)&lt;/li&gt;
	&lt;li&gt;Don&amp;#8217;t use nested resources because there&amp;#8217;s no way to automatically infer the &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt; for a given object if it&amp;#8217;s nested.&lt;/li&gt;
	&lt;li&gt;Be consistent with your attribute names.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The talk was in his usual straightforward and well-reasoned style and I found myself agreeing with most of it. However, there were a couple points on which I did not agree, which I would like to summarize here.&lt;/p&gt;
&lt;h2&gt;Naming Conventions&lt;/h2&gt;
&lt;p&gt;When talking about naming consistency, Yehuda explained that certain conventions don&amp;#8217;t yet exist so you need to just pick something and be consistent throughout your &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt;. He gave this example: let&amp;#8217;s say your &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; reponds with a &lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt; representation of an article with associated comments. When you render the &lt;code&gt;comments&lt;/code&gt; attribute for each article object do you include the attributes for each comment or do you just print an array of comment ids?&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// 1. comments = array of comment IDs&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;articles&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;title&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;...&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;body&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;...&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;comments&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 2. comments = array of full comment objects&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;posts&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;title&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;...&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;body&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;...&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;comments&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;body&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;...&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;body&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;...&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;body&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;...&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;To me, the first approach is wrong. Why? Because the attribute is called &lt;code&gt;comments&lt;/code&gt; and, with ActiveRecord, if you load an Article object and call its &lt;code&gt;comments&lt;/code&gt; method you get an array of Comment objects, not just ids. If you want just the ids you call &lt;code&gt;comment_ids&lt;/code&gt;. So if you print just the ids in your &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; you should call the attributre &lt;code&gt;comment_ids&lt;/code&gt;. This is how ActiveRecord works, and in the course of building several APIs I&amp;#8217;ve found that if we just follow ActiveRecord&amp;#8217;s existing conventions we already have solutions to most of the problems we will encounter.&lt;/p&gt;
&lt;p&gt;Another example: let&amp;#8217;s say we have an &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; that returns articles with a &lt;code&gt;comment_ids&lt;/code&gt; attribute (array of IDs) by default. We choose this as the default because in 90% of our &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; calls we don&amp;#8217;t need access to comment details, but what about the 10% of requests for which we do? Well, let&amp;#8217;s ask ourselves: &amp;#8220;What would ActiveRecord do?&amp;#8221; If you want to load articles with their full associated comment objects you do it like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Article.includes(:comments)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;and we can get very close to that in our &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt;:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/articles?includes=comments&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Since APIs are often an interface to ActiveRecord &lt;em&gt;written for&lt;/em&gt; programmers who already know ActiveRecord I see no reason not to mimick ActiveRecord as closely as possible in our &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; design. Even if the &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; clients will not be written by developers familiar with ActiveRecord, why not go with a familiar and successful solution? The problems of fetching data via an &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; are not &lt;em&gt;that&lt;/em&gt; different from the problems of fetching data from a database. It seems like it should be possible to create a set of rules for translating ActiveRecord expressions (including &lt;code&gt;includes&lt;/code&gt;, &lt;code&gt;where&lt;/code&gt;, and custom scopes) into query-string compatible &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; calls, but I leave this exercise to the reader (and potential gem author).&lt;/p&gt;
&lt;h2&gt;Bulk Operations&lt;/h2&gt;
&lt;p&gt;Yehuda also covered the &lt;a href=&quot;http://github.com/drogus/bulk_api&quot;&gt;bulk_api&lt;/a&gt; gem in his talk, which allows you to act on multiple objects in a single &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; call through a &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt; like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;POST /bulk/api&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The request body should contain a &lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt; representation of the objects to be created, modified, or deleted. A lot of people don&amp;#8217;t like this because it&amp;#8217;s not RESTful. It also doesn&amp;#8217;t follow any ActiveRecord-like convention. However, as someone who&amp;#8217;s added an &lt;code&gt;update_multiple&lt;/code&gt; action to a controller on more than one occasion I will say that I strongly prefer the approach of the bulk_api gem. It doesn&amp;#8217;t follow ActiveRecord because there&amp;#8217;s &lt;em&gt;nothing to follow&lt;/em&gt;: ActiveRecord does not provide a good way to do bulk updates. It&amp;#8217;s also better than adding an action to each existing controller because it allows you to work with different types of objects in a single request, and the routing is simpler (one route, as opposed to an additional route for every controller).&lt;/p&gt;
&lt;p&gt;Furthermore, I would suggest that a RESTful approach is possible (and desirable) with some modification to the bulk_api gem. What if we think of a resource called a BulkUpdater, and we &amp;#8220;create&amp;#8221; a new BulkUpdater when we want to make changes in bulk? Then we&amp;#8217;d have actions like these:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;POST&lt;/code&gt;: create a new BulkUpdater (which starts running immediately)&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;GET&lt;/code&gt;: display status of a running BulkUpdater (for long-running updates)&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;DELETE&lt;/code&gt;: cancel bulk changes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This would support polling the server to check on the progress of a bulk request. It would also not bind the action to be performed on the objects to the &lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt; method used for the request, allowing different actions to be performed on different objects in the same request.&lt;/p&gt;
&lt;p&gt;Note that I&amp;#8217;m not yet very familiar with the bulk_api gem so take this for what it&amp;#8217;s worth. Corrections and other feedback welcome.&lt;/p&gt;</description>
    </item>

    <item>
      <title>What the ɮɊɣͲɁѬȱ Is UTF-8? A Character Encoding Primer</title>
      <author>Alex Reisner</author>
      <pubDate>2011-04-14T00:00:00-07:00</pubDate>
      <link>http://code.alexreisner.com/articles/character-encoding.html</link>
      <guid>http://code.alexreisner.com/articles/character-encoding.html</guid>
      <description>&lt;p&gt;If you&amp;#8217;ve ever had character encoding problems and looked up &lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-8 to find out what it really is, you&amp;#8217;ve probably encountered definitions like &amp;#8220;a multibyte character encoding for Unicode&amp;#8221; or &amp;#8220;a mapping of the Unicode character set.&amp;#8221; These definitions, while correct, don&amp;#8217;t really tell you much unless you already understand character encodings. Let me try to explain it simply.&lt;/p&gt;
&lt;h2&gt;&lt;span class=&quot;caps&quot;&gt;ASCII&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;All data stored on every modern computer system looks like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;011010000110010101101100011011000110111100100000&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;0111011101101111011100100110110001100100&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Whether it&amp;#8217;s an image, an audio file, or plain text, it&amp;#8217;s all just ones and zeros (each one is called a &lt;em&gt;bit&lt;/em&gt;). Different programs interpret the ones and zeros with the assumption that they are arranged according to the rules of a particular &lt;em&gt;file format&lt;/em&gt;. For example the first bits of a &lt;span class=&quot;caps&quot;&gt;GIF&lt;/span&gt; file express the &lt;span class=&quot;caps&quot;&gt;GIF&lt;/span&gt; format version and the image dimensions. If you try to open an audio file in an image editor the program usually won&amp;#8217;t let you because the sequence of ones and zeros doesn&amp;#8217;t look like what it expects so it doesn&amp;#8217;t know how to interpret the data. But text editors will let you open just about anything, and if you open an audio file you&amp;#8217;ll get a lot of garbage. But it&amp;#8217;s not ones and zeros, it&amp;#8217;s funny looking characters. Why? Because text editors are made for working with text so they interpret the bits as text characters. Let&amp;#8217;s look at how they do it.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s say we have a file consisting of the ones and zeros given above. If we open this in a simple text editor, the editor will first separate the bits into groups of 8, each one called a &lt;em&gt;byte&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;01101000 01100101 01101100 01101100 01101111 00100000&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;01110111 01101111 01110010 01101100 01100100&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;It then reads each byte as a &lt;a href=&quot;http://www.math.grin.edu/~rebelsky/Courses/152/97F/Readings/student-binary&quot;&gt;binary number&lt;/a&gt;. The lowest value an 8-digit binary number can have is zero (&lt;code&gt;00000000&lt;/code&gt;) and the highest is 255 (&lt;code&gt;11111111&lt;/code&gt;). So the text editor sees the data as a sequence of numbers between 0 and 255. Translating the above bytes we get:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;104 101 108 108 111 32 119 111 114 108 100&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;It then looks up each of these numbers in a table to find out what character each number corresponds to. Part of the table might look like this:&lt;/p&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;32:&lt;/td&gt;
		&lt;td&gt;&lt;code&gt;&amp;lt;space&amp;gt;&lt;/code&gt;&lt;/td&gt;
		&lt;td&gt;&lt;/td&gt;
		&lt;td&gt;&lt;/td&gt;
		&lt;td&gt;109:&lt;/td&gt;
		&lt;td&gt;&lt;code&gt;m&lt;/code&gt;&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;..&lt;/td&gt;
		&lt;td&gt;&lt;/td&gt;
		&lt;td&gt;&lt;/td&gt;
		&lt;td&gt;&lt;/td&gt;
		&lt;td&gt;110:&lt;/td&gt;
		&lt;td&gt;&lt;code&gt;n&lt;/code&gt;&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;100:&lt;/td&gt;
		&lt;td&gt;&lt;code&gt;d&lt;/code&gt;&lt;/td&gt;
		&lt;td&gt;&lt;/td&gt;
		&lt;td&gt;&lt;/td&gt;
		&lt;td&gt;111:&lt;/td&gt;
		&lt;td&gt;&lt;code&gt;o&lt;/code&gt;&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;101:&lt;/td&gt;
		&lt;td&gt;&lt;code&gt;e&lt;/code&gt;&lt;/td&gt;
		&lt;td&gt;&lt;/td&gt;
		&lt;td&gt;&lt;/td&gt;
		&lt;td&gt;112:&lt;/td&gt;
		&lt;td&gt;&lt;code&gt;p&lt;/code&gt;&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;102:&lt;/td&gt;
		&lt;td&gt;&lt;code&gt;f&lt;/code&gt;&lt;/td&gt;
		&lt;td&gt;&lt;/td&gt;
		&lt;td&gt;&lt;/td&gt;
		&lt;td&gt;113:&lt;/td&gt;
		&lt;td&gt;&lt;code&gt;q&lt;/code&gt;&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;103:&lt;/td&gt;
		&lt;td&gt;&lt;code&gt;g&lt;/code&gt;&lt;/td&gt;
		&lt;td&gt;&lt;/td&gt;
		&lt;td&gt;&lt;/td&gt;
		&lt;td&gt;114:&lt;/td&gt;
		&lt;td&gt;&lt;code&gt;r&lt;/code&gt;&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;104:&lt;/td&gt;
		&lt;td&gt;&lt;code&gt;h&lt;/code&gt;&lt;/td&gt;
		&lt;td&gt;&lt;/td&gt;
		&lt;td&gt;&lt;/td&gt;
		&lt;td&gt;115:&lt;/td&gt;
		&lt;td&gt;&lt;code&gt;s&lt;/code&gt;&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;105:&lt;/td&gt;
		&lt;td&gt;&lt;code&gt;i&lt;/code&gt;&lt;/td&gt;
		&lt;td&gt;&lt;/td&gt;
		&lt;td&gt;&lt;/td&gt;
		&lt;td&gt;116:&lt;/td&gt;
		&lt;td&gt;&lt;code&gt;t&lt;/code&gt;&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;106:&lt;/td&gt;
		&lt;td&gt;&lt;code&gt;j&lt;/code&gt;&lt;/td&gt;
		&lt;td&gt;&lt;/td&gt;
		&lt;td&gt;&lt;/td&gt;
		&lt;td&gt;117:&lt;/td&gt;
		&lt;td&gt;&lt;code&gt;u&lt;/code&gt;&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;107:&lt;/td&gt;
		&lt;td&gt;&lt;code&gt;k&lt;/code&gt;&lt;/td&gt;
		&lt;td&gt;&lt;/td&gt;
		&lt;td&gt;&lt;/td&gt;
		&lt;td&gt;118:&lt;/td&gt;
		&lt;td&gt;&lt;code&gt;v&lt;/code&gt;&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;108:&lt;/td&gt;
		&lt;td&gt;&lt;code&gt;l&lt;/code&gt;&lt;/td&gt;
		&lt;td&gt;&lt;/td&gt;
		&lt;td&gt;&lt;/td&gt;
		&lt;td&gt;119:&lt;/td&gt;
		&lt;td&gt;&lt;code&gt;w&lt;/code&gt;&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;So, translating the above numbers into characters we get:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;hello world&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Pretty simple right? What we&amp;#8217;ve been looking at so far is called &lt;span class=&quot;caps&quot;&gt;ASCII&lt;/span&gt; encoding, which basically means that the table or &lt;em&gt;map&lt;/em&gt; used to translate numbers into characters is called &lt;span class=&quot;caps&quot;&gt;ASCII&lt;/span&gt;.&lt;/p&gt;
&lt;h2&gt;See It For Yourself&lt;/h2&gt;
&lt;p&gt;If you&amp;#8217;re a healthy skeptic you may be wondering if this isn&amp;#8217;t an oversimplification. If you&amp;#8217;re on a Unix-like system with the &lt;code&gt;xxd&lt;/code&gt; command (comes with Vim) you can see for yourself that it isn&amp;#8217;t. The &lt;code&gt;xxd&lt;/code&gt; command creates a &amp;#8220;hex dump&amp;#8221; of its input. That is, it converts its input to raw bits. So let&amp;#8217;s give it the &lt;code&gt;&quot;hello world&quot;&lt;/code&gt; string and set the &lt;code&gt;-b&lt;/code&gt; option (which displays output in binary instead of the default hexadecimal):&lt;/p&gt;
&lt;p&gt;&lt;code&gt;echo 'hello world' | xxd -b&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;You should get this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;0000000: 01101000 01100101 01101100 01101100 01101111 00100000  hello&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;0000006: 01110111 01101111 01110010 01101100 01100100 00001010  world.&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Which is the same as my example above plus an extra character on the end (10: line break) which is added by &lt;code&gt;echo&lt;/code&gt;. So there.&lt;/p&gt;
&lt;h2&gt;Unicode&lt;/h2&gt;
&lt;p&gt;Unicode is basically a character lookup table that was designed to include every single character used in any language, anywhere. Needless to say, it&amp;#8217;s huge. There are over 100,000 characters. You can buy a hard copy of Unicode v5.0 which is &lt;a href=&quot;http://unicode.org/book/aboutbook.html&quot;&gt;a 1400 page book&lt;/a&gt;, and more characters were added in Unicode 6.0. Obviously 8 bits isn&amp;#8217;t enough to represent all these characters. In fact, Unicode character numbers go up to over 1.1 million (there are gaps in the numbering) so we need at least 21 bits (2&lt;sup&gt;21&lt;/sup&gt;= 2,097,152) to encode them all. There have been many attempts to create &lt;em&gt;character encodings&lt;/em&gt; (roughly synonymous with &lt;em&gt;file formats&lt;/em&gt; for purposes of this discussion) for the entire set of Unicode characters, each with its own benefits and drawbacks.&lt;/p&gt;
&lt;h3&gt;&lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-32&lt;/h3&gt;
&lt;p&gt;&lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-32 is one such encoding which uses 32 bits to encode every character, so &lt;code&gt;&quot;hello world&quot;&lt;/code&gt; looks like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;01101000 00000000 00000000 00000000&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;01100101 00000000 00000000 00000000&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;01101100 00000000 00000000 00000000&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;01101100 00000000 00000000 00000000&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;01101111 00000000 00000000 00000000&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;00100000 00000000 00000000 00000000&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;01110111 00000000 00000000 00000000&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;01101111 00000000 00000000 00000000&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;01110010 00000000 00000000 00000000&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;01101100 00000000 00000000 00000000&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;01100100 00000000 00000000 00000000&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-32 has more than enough numbers for every Unicode character but clearly this in not a very compact format. &lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-32 files are four times as large as &lt;span class=&quot;caps&quot;&gt;ASCII&lt;/span&gt; files with the same text.&lt;/p&gt;
&lt;h3&gt;&lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-16&lt;/h3&gt;
&lt;p&gt;Another encoding, &lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-16, uses (you guessed it) 16 bits per character. Files are half the size of &lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-32 but with only 16 bits some of the Unicode character set is missing. The good thing is that Unicode was designed so that the most common characters have the lowest numbers, and the group of characters that form what&amp;#8217;s known as the &amp;#8220;Basic Multilingual Plane&amp;#8221; are all covered by &lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-16. (There is also a way to encode additional characters using &lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-16 but that is beyond the scope of this article.)&lt;/p&gt;
&lt;p&gt;Another very practical problem with &lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-16 and -32 is that you need a text editor that knows how to read them. That is, even if you&amp;#8217;re just writing normal English text with no characters beyond those in the standard &lt;span class=&quot;caps&quot;&gt;ASCII&lt;/span&gt; range, if you save the file as &lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-16 and send it to a friend who opens it in an &lt;span class=&quot;caps&quot;&gt;ASCII&lt;/span&gt;-only text editor, it will look like jibberish.&lt;/p&gt;
&lt;h3&gt;&lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-8&lt;/h3&gt;
&lt;p&gt;Wouldn&amp;#8217;t it be great if there was an encoding that was compact, backwards compatible with &lt;span class=&quot;caps&quot;&gt;ASCII&lt;/span&gt;, &lt;strong&gt;and&lt;/strong&gt; included all the Unicode characters too? &lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-8 is a &lt;em&gt;variable length encoding&lt;/em&gt; which uses 1 to 4 bytes for each character and can represent the entire Unicode character repertoire without creating huge files (or, for web pages, slow downloads) like &lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-32.&lt;/p&gt;
&lt;p&gt;How is that possible? How does the computer know how many bytes to read for each character? Don&amp;#8217;t feel bad if you can&amp;#8217;t figure it out because it took someone as smart as &lt;a href=&quot;http://en.wikipedia.org/wiki/Ken_Thompson&quot;&gt;Ken Thompson&lt;/a&gt; to design it.&lt;/p&gt;
&lt;p&gt;Basically it works like this: for characters in the &lt;span class=&quot;caps&quot;&gt;ASCII&lt;/span&gt; range, &lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-8 is identical to &lt;span class=&quot;caps&quot;&gt;ASCII&lt;/span&gt; (and remember: every &lt;span class=&quot;caps&quot;&gt;ASCII&lt;/span&gt; byte starts with a &lt;code&gt;0&lt;/code&gt;). To represent a character beyond the &lt;span class=&quot;caps&quot;&gt;ASCII&lt;/span&gt; range, the first byte starts with the number of &lt;tt&gt;1&lt;/tt&gt;s which is the number of total bytes used to represent the character (followed by a zero), and each successive byte starts with &lt;code&gt;10&lt;/code&gt; so that every byte can quickly be identified:&lt;/p&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;if it starts with &lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
		&lt;td&gt;it&amp;#8217;s an &lt;span class=&quot;caps&quot;&gt;ASCII&lt;/span&gt; character&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;if it starts with &lt;code&gt;10&lt;/code&gt;&lt;/td&gt;
		&lt;td&gt;it&amp;#8217;s a continuation of a multi-byte character&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;if it starts with &lt;code&gt;110&lt;/code&gt;&lt;/td&gt;
		&lt;td&gt;it&amp;#8217;s the first byte of a 2-byte character&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;if it starts with &lt;code&gt;1110&lt;/code&gt;&lt;/td&gt;
		&lt;td&gt;it&amp;#8217;s the first byte of a 3-byte character&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;if it starts with &lt;code&gt;11110&lt;/code&gt;&lt;/td&gt;
		&lt;td&gt;it&amp;#8217;s the first byte of a 4-byte character&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;All other bits are then concatenated to get the binary number which will be mapped to a character. With all these &amp;#8220;metadata&amp;#8221; bits we don&amp;#8217;t have true 32-bit character numbers like in &lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-32, so can we really represent the full Unicode character set? Remember, we need 21 bits to do that, so let&amp;#8217;s see how many actual data bits there are in the largest &lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-8 character (data bits are bold):&lt;/p&gt;
&lt;p&gt;&lt;tt&gt;11110&lt;strong&gt;111&lt;/strong&gt; 10&lt;strong&gt;111111&lt;/strong&gt; 10&lt;strong&gt;111111&lt;/strong&gt; 10&lt;strong&gt;111111&lt;/strong&gt;&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;If you count them you&amp;#8217;ll see there are exactly the 21 required for Unicode.&lt;/p&gt;
&lt;h2&gt;The End&lt;/h2&gt;
&lt;p&gt;Now it should be clear why in some programming languages you get strange results when counting the number of characters in a non-&lt;span class=&quot;caps&quot;&gt;ASCII&lt;/span&gt; string: they&amp;#8217;re assuming the string is &lt;span class=&quot;caps&quot;&gt;ASCII&lt;/span&gt; and counting the number of bytes it takes in memory. To count the characters accurately the language has to be told what encoding the string uses and it has to know how to parse that encoding.&lt;/p&gt;
&lt;p&gt;There are a lot of other concerns that character encoding designers must deal with like compatibility with different platforms and performance in search/manipulation operations, but this is as far as I&amp;#8217;m going to go in this article. For more information, check out these resources:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://dev.networkerror.org/utf8/&quot;&gt;&lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-8 character map&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Comparison_of_Unicode_encodings&quot;&gt;Comparison of Unicode encodings&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://doc.cat-v.org/plan_9/4th_edition/papers/utf&quot;&gt;Ken Thompson and Rob Pike&amp;#8217;s original &lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-8 writeup&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Epilogue&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;April 19, 2011&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;After I posted this article there was a &lt;a href=&quot;http://www.reddit.com/r/programming/comments/gqash/simple_fun_character_encoding_explanation/&quot;&gt;discussion on Reddit&lt;/a&gt; in which &lt;a href=&quot;http://www.reddit.com/user/muyuu&quot;&gt;muyuu&lt;/a&gt; made some excellent points which I thought were worth posting here:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;&lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-32 files are four times as large as &lt;span class=&quot;caps&quot;&gt;ASCII&lt;/span&gt; files with the same text&amp;#8221; seems to imply &lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-32 is retarded (or &lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-16 for that matter). You should add that obviously neither was designed to store &lt;span class=&quot;caps&quot;&gt;ASCII&lt;/span&gt; text and that you can&amp;#8217;t represent Unicode text in &lt;span class=&quot;caps&quot;&gt;ASCII&lt;/span&gt; at all, unless the whole text happens to fall into the very small &lt;span class=&quot;caps&quot;&gt;ASCII&lt;/span&gt; subset.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;You should also add that &lt;strong&gt;&lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-8 text is only compact when something like 3/4+ of your text is plain &lt;span class=&quot;caps&quot;&gt;ASCII&lt;/span&gt;&lt;/strong&gt;. If your text is in Japanese or Chinese, for example, then &lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-8 is ridiculously inefficient and &lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-16 is much better (or even better, their respective local encodings; they have many and most of them are variable-length). 30-40% extra size in text makes a lot of difference when the majority of your users connect from their cell phones.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;It&amp;#8217;s also worth mention that variable-length encodings compress a lot worse than fixed length encodings, especially in the case of &lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-16 &amp;#8211; because codepage grouping and character order are not random, and any trivial compressor will greatly benefit from that. Things are routinely compressed when transmitted over networks.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;This is for the &amp;#8220;&lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-8 is all we need&amp;#8221; brigade. If you have many users in countries with different writing systems, supporting different encodings might be a good idea. Obviously it can be a complex issue, but &amp;#8211; for instance &amp;#8211; an additional 20% wait to the ping your users may have, it can be a deal breaker for your microblogging site in favour of a local one.&lt;/p&gt;
&lt;/blockquote&gt;</description>
    </item>

    <item>
      <title>Database Translation Guide</title>
      <author>Alex Reisner</author>
      <pubDate>2010-10-14T00:00:00-07:00</pubDate>
      <link>http://code.alexreisner.com/articles/database-translation.html</link>
      <guid>http://code.alexreisner.com/articles/database-translation.html</guid>
      <description>&lt;p&gt;Web frameworks that come with database abstraction layers like ActiveRecord have given us a degree of freedom in the database software we use. Database portability increases the number of platforms on which we can deploy our apps, but you still need to know how to use the different databases. For those of you who are used to MySQL or PostgreSQL and need to learn SQLite (or some other combination of those), here are some rough command equivalents in each to get you started.&lt;/p&gt;
&lt;h2&gt;Basic Administration&lt;/h2&gt;
&lt;p&gt;Some of these commands are given at your operating system command prompt and others are given at the database client command prompt. I have indicated the prompt in each command below: &lt;code&gt;$&lt;/code&gt; is your OS, and &lt;code&gt;db&amp;gt;&lt;/code&gt; is your database client.&lt;/p&gt;
&lt;h3&gt;Start the Database Client&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.sqlite.org&quot;&gt;&lt;strong&gt;SQLite&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;sqlite &amp;lt;db file&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://www.mysql.com&quot;&gt;&lt;strong&gt;MySQL&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mysql -u&amp;lt;user&amp;gt; -p &amp;lt;db name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://www.postgresql.org&quot;&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;psql -U &amp;lt;user&amp;gt; &amp;lt;db name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;List Available Databases&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.sqlite.org&quot;&gt;&lt;strong&gt;SQLite&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Databases are stored in separate files, usually with a &lt;code&gt;.sqlite3&lt;/code&gt; or &lt;code&gt;.db&lt;/code&gt; extension. SQLite cannot find these files for you.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.mysql.com&quot;&gt;&lt;strong&gt;MySQL&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;db&amp;gt; SHOW DATABASES;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://www.postgresql.org&quot;&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;db&amp;gt; SELECT datname FROM pg_database;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;Create a Database&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.sqlite.org&quot;&gt;&lt;strong&gt;SQLite&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;sqlite3 &amp;lt;db file&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://www.mysql.com&quot;&gt;&lt;strong&gt;MySQL&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mysqladmin -u&amp;lt;user&amp;gt; -p create &amp;lt;db name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://www.postgresql.org&quot;&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;createdb &amp;lt;db name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;Change the Current Database&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.sqlite.org&quot;&gt;&lt;strong&gt;SQLite&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Close the client and re-open with another file.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.mysql.com&quot;&gt;&lt;strong&gt;MySQL&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;db&amp;gt; USE &amp;lt;db name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://www.postgresql.org&quot;&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;db&amp;gt; &lt;span class=&quot;se&quot;&gt;\c&lt;/span&gt;onnect &amp;lt;db name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;List Tables in a Database&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.sqlite.org&quot;&gt;&lt;strong&gt;SQLite&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;db&amp;gt; .schema
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://www.mysql.com&quot;&gt;&lt;strong&gt;MySQL&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;db&amp;gt; SHOW tables;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://www.postgresql.org&quot;&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;db&amp;gt; &lt;span class=&quot;se&quot;&gt;\d&lt;/span&gt;t
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;Display Schema for a Table&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.sqlite.org&quot;&gt;&lt;strong&gt;SQLite&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;db&amp;gt; .schema &amp;lt;table&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://www.mysql.com&quot;&gt;&lt;strong&gt;MySQL&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;db&amp;gt; DESCRIBE &amp;lt;table&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://www.postgresql.org&quot;&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;db&amp;gt; &lt;span class=&quot;se&quot;&gt;\d&lt;/span&gt; &amp;lt;table&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2&gt;Functions&lt;/h2&gt;
&lt;p&gt;Where there is more than one way to accomplish the same thing I have chosen the most generally-usable functions since that is normally what you&amp;#8217;ll want to use for cross-database compatibility. There are some common things which SQLite cannot do out of the box, but a lot of useful functions can be added with the &lt;a href=&quot;http://www.sqlite.org/contrib/download/extension-functions.c?get=25&quot;&gt;extension-functions&lt;/a&gt;. Compilation instructions are in the downloaded file. Load the extension at the SQLite prompt:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;.load &amp;lt;compiled extension filename&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;Select a Substring&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.sqlite.org&quot;&gt;&lt;strong&gt;SQLite&lt;/strong&gt;&lt;/a&gt;, &lt;a href=&quot;http://www.mysql.com&quot;&gt;&lt;strong&gt;MySQL&lt;/strong&gt;&lt;/a&gt;, and &lt;a href=&quot;http://www.postgresql.org&quot;&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;SUBSTR&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&amp;lt;string&amp;gt;, &amp;lt;start&amp;gt;, &amp;lt;length&amp;gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# length argument is optional&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;Find the Position of a Substring&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.sqlite.org&quot;&gt;&lt;strong&gt;SQLite&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;CHARINDEX&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&amp;lt;sta&amp;gt;, &amp;lt;haystack&amp;gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# requires extension-functions&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://www.mysql.com&quot;&gt;&lt;strong&gt;MySQL&lt;/strong&gt;&lt;/a&gt;, and &lt;a href=&quot;http://www.postgresql.org&quot;&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;POSITION&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&amp;lt;sta&amp;gt; IN &amp;lt;haystack&amp;gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;Raise a Number to a Power&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.sqlite.org&quot;&gt;&lt;strong&gt;SQLite&lt;/strong&gt;&lt;/a&gt;, &lt;a href=&quot;http://www.mysql.com&quot;&gt;&lt;strong&gt;MySQL&lt;/strong&gt;&lt;/a&gt;, and &lt;a href=&quot;http://www.postgresql.org&quot;&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;POWER&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&amp;lt;base&amp;gt;, &amp;lt;exponent&amp;gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# requires extension-functions in SQLite&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;Get the Year From a Date&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.sqlite.org/lang_datefunc.html&quot;&gt;&lt;strong&gt;SQLite&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;STRFTIME&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;%Y&amp;quot;&lt;/span&gt;, &amp;lt;date&amp;gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_year&quot;&gt;&lt;strong&gt;MySQL&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;YEAR&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&amp;lt;date&amp;gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://www.postgresql.org/docs/8.3/static/functions-datetime.html#FUNCTIONS-DATETIME-TABLE&quot;&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;EXTRACT&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;YEAR FROM &amp;lt;date&amp;gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;If/Then/Else&lt;/h3&gt;
&lt;p&gt;MySQL provides an IF() function that many people are used to:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://dev.mysql.com/doc/refman/5.0/en/if-statement.html&quot;&gt;&lt;strong&gt;MySQL&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;IF&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&amp;lt;condition&amp;gt;, &amp;lt;&lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;-expression&amp;gt;, &amp;lt;&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;-expression&amp;gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This is convenient but not supported by other databases. It&amp;#8217;s better to use the more widely-implemented &lt;span class=&quot;caps&quot;&gt;CASE&lt;/span&gt; statement:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.sqlite.org/lang_expr.html#case&quot;&gt;&lt;strong&gt;SQLite&lt;/strong&gt;&lt;/a&gt;, &lt;a href=&quot;http://dev.mysql.com/doc/refman/5.0/en/case-statement.html&quot;&gt;&lt;strong&gt;MySQL&lt;/strong&gt;&lt;/a&gt;, and &lt;a href=&quot;http://www.postgresql.org/docs/8.4/interactive/functions-conditional.html#AEN15210&quot;&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;CASE WHEN &amp;lt;condition&amp;gt; THEN &amp;lt;expression&amp;gt; ELSE &amp;lt;expression&amp;gt; END
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;Select an Alternative to Null&lt;/h3&gt;
&lt;p&gt;This is commonly achieved in MySQL through the use of &lt;code&gt;IFNULL(x, y)&lt;/code&gt;, but the &lt;code&gt;COALESCE&lt;/code&gt; function is equivalent in the case of two arguments, more general, and more widely implemented. It takes any number of arguments and returns the first one which is not null.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.sqlite.org/lang_corefunc.html#coalesce&quot;&gt;&lt;strong&gt;SQLite&lt;/strong&gt;&lt;/a&gt;, &lt;a href=&quot;http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_coalesce&quot;&gt;&lt;strong&gt;MySQL&lt;/strong&gt;&lt;/a&gt;, and &lt;a href=&quot;http://www.postgresql.org/docs/8.3/interactive/functions-conditional.html#AEN14491&quot;&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;COALESCE&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&amp;lt;value1&amp;gt;, &amp;lt;value2&amp;gt;, ...&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;That&amp;#8217;s all for now, though I will probably add to this list in the future. If there is anything you would like to see added, please let me know.&lt;/p&gt;</description>
    </item>

    <item>
      <title>Vim Heresy</title>
      <author>Alex Reisner</author>
      <pubDate>2010-09-24T00:00:00-07:00</pubDate>
      <link>http://code.alexreisner.com/articles/vim-heresy.html</link>
      <guid>http://code.alexreisner.com/articles/vim-heresy.html</guid>
      <description>&lt;p&gt;I don&amp;#8217;t expect anyone to like this article.&lt;/p&gt;
&lt;p&gt;Nevertheless, I feel it needs to be written.&lt;/p&gt;
&lt;p&gt;I first used Vi about 18 years ago. I thought it was pretty weird, but it was the only text editor I knew of on Unix so I learned the basics. My main editor, however, has always been one with a &amp;#8220;normal&amp;#8221; &lt;span class=&quot;caps&quot;&gt;GUI&lt;/span&gt; (EditPlus, Gedit, etc). I&amp;#8217;ve tried, on probably eight different occasions, to make Vi/Vim/Gvim my main tool, each time learning a little more, picking up my .vimrc from where I left off, but never successfully making the switch.&lt;/p&gt;
&lt;p&gt;Until now.&lt;/p&gt;
&lt;p&gt;To explain briefly: I&amp;#8217;ve tried switching to Vim so many times because no matter what editor I&amp;#8217;ve used I&amp;#8217;ve always needed to resort to Vim for something. Whether it&amp;#8217;s opening very large files, doing complex regex search and replace, column selection, or various types of advanced text formatting, Vim is the only editor I&amp;#8217;ve used that does &lt;em&gt;everything&lt;/em&gt; I want it to. But along with Vim comes a dogmatic, somewhat macho, insistence that the only way to use it is with the alphanumeric part of the keyboard. No mouse, no arrow keys. And over and over, after a few days of giving it a good try, I would give up.&lt;/p&gt;
&lt;p&gt;Then, a few months ago I read a great article called &lt;a href=&quot;http://yehudakatz.com/2010/07/29/everyone-who-tried-to-convince-me-to-use-vim-was-wrong&quot;&gt;Everyone Who Tried to Convince Me to use Vim was Wrong&lt;/a&gt;. The author&amp;#8217;s point is not that you shouldn&amp;#8217;t use Vim, but that you shouldn&amp;#8217;t &lt;em&gt;necessarily&lt;/em&gt; learn it the way everyone says you should. His successful conversion happened like this: he got MacVim, installed NERDTree, used his mouse, and stayed mostly in insert mode. As the days went by he learned new commands and gradually became more productive.&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;re a hardcore Vim user no doubt you&amp;#8217;re leaning over to throw up in your trash can right now.&lt;/p&gt;
&lt;p&gt;But this is how I finally made the transition too. I already knew a lot of commands. I got around with H, J, K, and L, and also W, B, and E. But moving blocks of text constitutes a significant portion of my work and I always had a hard time doing it quickly in Vim. Select/drag/drop with the mouse in a &lt;span class=&quot;caps&quot;&gt;GUI&lt;/span&gt; editor is pretty hard to beat and this was one of the main reasons I wasn&amp;#8217;t using Vim. When I read Yehuda Katz&amp;#8217;s article and finally realized I was subjecting myself unnecessarily to the Vim dogma, I again loaded up Gvim and my old .vimrc and proceeded to select text with the mouse and cut and paste with d and p. It felt &amp;#8220;wrong,&amp;#8221; but it worked.&lt;/p&gt;
&lt;p&gt;To be clear: I find the mouse as frustrating as anyone. To me, a mouse is good for applications like drawing programs where there is an actual two-dimensional space to navigate. There simply aren&amp;#8217;t enough commands in most applications that aiming an arrow at a point among the hundreds of thousands of pixels on a monitor makes sense. We already have a control device with over 50 &lt;em&gt;physical&lt;/em&gt; buttons right under our fingers that we&amp;#8217;re all very familiar with. But the mouse is apparently less threatening to new computer users so most &lt;span class=&quot;caps&quot;&gt;GUI&lt;/span&gt; software is intended to be used with a mouse, and if you work in any standard OS you probably have to use the mouse for &lt;em&gt;some&lt;/em&gt; things, right?&lt;/p&gt;
&lt;p&gt;The only thing I find more frustrating than using the mouse is moving my hand to it, and then back again to type. But here&amp;#8217;s the thing: if your hand is already on the mouse, because you were just doing something in a web browser or some other mouse-operated program, it might be faster to keep it there. &lt;strong&gt;If you&amp;#8217;re returning to Gvim with your hand on the mouse, might it not be faster to place the cursor with a click than with a sequence of keystrokes?&lt;/strong&gt; I&amp;#8217;m not saying you keep your hand on the mouse after that, but unless you &lt;em&gt;never&lt;/em&gt; use the mouse at all, doesn&amp;#8217;t Gvim/MacVim give you a pretty significant convenience over non-&lt;span class=&quot;caps&quot;&gt;GUI&lt;/span&gt; Vim?&lt;/p&gt;
&lt;p&gt;Don&amp;#8217;t worry, your disgust at this idea is endorsed by O&amp;#8217;Reilly, whose book &lt;em&gt;Learning the Vi and Vim Editors&lt;/em&gt; includes the following:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;&amp;#8230;some veteran Vim users (this author included!) may cringe at the thought of grafting a &lt;span class=&quot;caps&quot;&gt;GUI&lt;/span&gt; onto their workhorse editor&amp;#8230;&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;He goes on to show that Gvim actually adds some very nice features, but why does he need this qualification? I suspect he worries about losing credibility if he doesn&amp;#8217;t remind the reader that he&amp;#8217;s a Vi Tough Guy. Why does Vi seem to inspire the worst kind of religious fervor, the kind that says there&amp;#8217;s only one way to do things?&lt;/p&gt;
&lt;p&gt;As programmers we have a tendency to defend the technology we use and attack the things we don&amp;#8217;t. Ruby programmers tend to despise Python, and vice versa, when the languages are awfully similar. There are some superficial differences like Python&amp;#8217;s use of significant whitespace, but in more significant ways the languages are very comparable, and the communities feed off of each other&amp;#8217;s work. It&amp;#8217;s always looked like a symbiotic relationship to me, but it&amp;#8217;s one in which the majority of participants are kicking and screaming the whole time. People will also swear that one distribution of Linux is amazing while another is awful. Again, they&amp;#8217;re all different, and certainly everyone has a favorite, but is any Linux distribution really deserving of the hatred they sometimes receive?&lt;/p&gt;
&lt;p&gt;I think, because we work in an industry where keeping up with the latest inventions is vital to our survival, and because we depend on a large body of somewhat esoteric knowledge to stay relevant, we put pressure on ourselves to know &lt;em&gt;everything&lt;/em&gt;. Not knowing things means such certain death in the field of computer programming that we prefer to put down things we don&amp;#8217;t know about than admit they might be worth knowing. We&amp;#8217;re so afraid of being non-experts that we shrink our universe down to include just what we know. And we build up what we do know. Not just its relevance and sophistication, but its complexity. And I think that&amp;#8217;s what happens with Vim. If we let people use the arrow keys, we somehow know less. Suddenly the thing we mastered is no longer as amazing and esoteric.&lt;/p&gt;
&lt;p&gt;This is obviously not productive. Ignoring things we don&amp;#8217;t know only leads to stasis and eventually boredom. And telling people to burn their mouse and chop off their arrow keys only ensures that fewer people use Vim, which is not a good thing in the long run. More users means more, better plugins. And yeah, &lt;strong&gt;everyone&lt;/strong&gt; has used an arrow key in Vim at least once, so that plugin you love was written by a former arrow key user. Aaahhhh! The horror! Newbies become masters. It&amp;#8217;s amazing how that never seems to stop happening.&lt;/p&gt;
&lt;p&gt;Anyway, I guess my point is that these rules we have for talking about Vim are insane. I often need to open a lot of files at once and keep them in logical groups so I use tabs, which is another Vim no-no. Most Vim guides either don&amp;#8217;t mention them or recommend against using them. But why? Of all the possible methods for working with multiple files in Vim, tabs should be the most familiar to new users. Why wouldn&amp;#8217;t we tell beginners to use them? Why is Yehuda Katz in the minority when he suggests wading into Vim gradually, rather than jumping off the high dive?&lt;/p&gt;
&lt;p&gt;Because it makes some people feel less smart.&lt;/p&gt;
&lt;p&gt;That just ain&amp;#8217;t right.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;
&lt;em&gt;Check out my constantly-evolving &lt;a href=&quot;http://github.com/alexreisner/dotfiles/blob/master/.vimrc&quot;&gt;.vimrc&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;</description>
    </item>

    <item>
      <title>Testing Serialized Fixtures in Rails 3</title>
      <author>Alex Reisner</author>
      <pubDate>2010-09-02T00:00:00-07:00</pubDate>
      <link>http://code.alexreisner.com/articles/serialized-fixtures-in-rails-3.html</link>
      <guid>http://code.alexreisner.com/articles/serialized-fixtures-in-rails-3.html</guid>
      <description>&lt;p&gt;As you may know, you can use Rails to store serialized values in your database. ActiveRecord silently handles the conversion of values to and from &lt;span class=&quot;caps&quot;&gt;YAML&lt;/span&gt; as objects are stored and loaded. If you have some data that you need to keep around but which you don&amp;#8217;t ever need to perform queries on, such as raw PayPal Instant Payment Notification parameters (presumably you extract any important information into separate attributes) you can store it in a serialized hash. Let&amp;#8217;s say you have a Payment model with an &lt;code&gt;ipn_params&lt;/code&gt; attribute. In your model you just need a line like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;serialize&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:ipn_params&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;and you will be able to use the attribute for storing a Ruby hash, array, or anything that can be converted to &lt;span class=&quot;caps&quot;&gt;YAML&lt;/span&gt;. However, what do you do when you&amp;#8217;re testing such a model using fixtures? In Rails 2 there was very convenient (though not well-documented) technique; you could do something like this, assuming &lt;code&gt;params&lt;/code&gt; and &lt;code&gt;ducks&lt;/code&gt; are serialized attributes (hash and array respectively):&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;yaml&quot;&gt;&lt;span class=&quot;l-Scalar-Plain&quot;&gt;payment1&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;2010-09-02&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p-Indicator&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;2010-09-02&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;102.45&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;visa&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;ducks&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p-Indicator&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;97&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Note that you &lt;em&gt;must&lt;/em&gt; include a space after each colon. However, in Rails 3, some time after 3.0.0.beta4, this stopped working. I&amp;#8217;m not sure if there is an official alternate syntax, but I&amp;#8217;ve been using this, which has worked so far:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;yaml&quot;&gt;&lt;span class=&quot;l-Scalar-Plain&quot;&gt;payment1&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;2010-09-02&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;&amp;lt;%= {&lt;/span&gt;
    &lt;span class=&quot;l-Scalar-Plain&quot;&gt;&amp;quot;date&amp;quot; =&amp;gt; &amp;quot;2010-09-02&amp;quot;,&lt;/span&gt;
    &lt;span class=&quot;l-Scalar-Plain&quot;&gt;&amp;quot;amount&amp;quot; =&amp;gt; &amp;quot;102.45&amp;quot;,&lt;/span&gt;
    &lt;span class=&quot;l-Scalar-Plain&quot;&gt;&amp;quot;method&amp;quot; =&amp;gt; &amp;quot;visa&amp;quot;}.to_yaml.inspect %&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;ducks&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;&amp;lt;%= [4, 5, 6, 3, 12, 97].to_yaml.inspect %&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If someone has a more elegant method please post it in the comments, but for now this is at least a quick fix to stop your tests from failing.&lt;/p&gt;</description>
    </item>

    <item>
      <title>Duplicate link_to_remote With Rails 3 and UJS</title>
      <author>Alex Reisner</author>
      <pubDate>2010-07-20T00:00:00-07:00</pubDate>
      <link>http://code.alexreisner.com/articles/link-to-remote-with-ujs.html</link>
      <guid>http://code.alexreisner.com/articles/link-to-remote-with-ujs.html</guid>
      <description>&lt;p&gt;In &lt;a href=&quot;http://railscasts.com/episodes/205-unobtrusive-javascript&quot;&gt;Railscast #205&lt;/a&gt; Ryan Bates shows how to use &lt;span class=&quot;caps&quot;&gt;UJS&lt;/span&gt; to update an element using &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt;. However, with his technique the server returns a JavaScript response: code which inserts a string into an element on the page. The problem with this approach is that the server needs to know where to insert its response (&lt;span class=&quot;caps&quot;&gt;DOM&lt;/span&gt; ID of the target element). Most of my Rails 2 applications were designed so that each page is a &amp;#8220;client&amp;#8221; which receives a plain &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; response from the server and inserts the body of that response into the appropriate element on the page. This means the same server action (&lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt;) can be used to generate content that gets inserted into different pages on the site. Not only does this make server actions simpler and more general, it makes their output easier to test.&lt;/p&gt;
&lt;p&gt;Turning &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; into a JavaScript-escaped string on the server just doesn&amp;#8217;t feel right.&lt;/p&gt;
&lt;h2&gt;How To Do It&lt;/h2&gt;
&lt;p&gt;Rails 3 dictates that we replace things like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;erb&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;link_to_remote&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;more&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;with things like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;erb&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;link_to&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;more&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:remote&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;With good old &lt;code&gt;link_to_remote&lt;/code&gt; we could pass an &lt;code&gt;:update&lt;/code&gt; option to achieve the system described above, in which the page receives a generic response and updates the specified element with it. But &lt;code&gt;link_to&lt;/code&gt; doesn&amp;#8217;t accept an &lt;code&gt;:update&lt;/code&gt; option because with Rails 3 and &lt;span class=&quot;caps&quot;&gt;UJS&lt;/span&gt; we want to avoid putting JavaScript in our &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag attributes. In Rails 3 &lt;code&gt;link_to&lt;/code&gt; with &lt;code&gt;remote=&quot;true&quot;&lt;/code&gt; renders something like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;...&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-remote=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;true&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;more...&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Then the Rails &lt;span class=&quot;caps&quot;&gt;UJS&lt;/span&gt; drivers (currently available for Prototype and jQuery) look for links and forms with a &lt;code&gt;data-remote=&quot;true&quot;&lt;/code&gt; attribute and &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt;-ify them. So how do we do this? If we don&amp;#8217;t write the code that makes the &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt; request, how can we access the response? The answer is: events.&lt;/p&gt;
&lt;p&gt;The &lt;span class=&quot;caps&quot;&gt;UJS&lt;/span&gt; drivers trigger six events on every &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt; call:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;ajax:before&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;ajax:loading&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;ajax:success&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;ajax:failure&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;ajax:complete&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;ajax:after&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You should recognize these event names from the old &lt;code&gt;link_to_remote&lt;/code&gt; method options, and we simply need to listen for them on our &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt;-triggering elements.&lt;/p&gt;
&lt;h2&gt;Example&lt;/h2&gt;
&lt;p&gt;Let&amp;#8217;s say we have a page that lists the ten most popular products in our database. At the end is a link to load all the remaining products via &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;erb&quot;&gt;&lt;span class=&quot;x&quot;&gt;&amp;lt;ul id=&amp;quot;products-list&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;  &amp;lt;li&amp;gt;...&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;  &amp;lt;li&amp;gt;...&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;  &amp;lt;li&amp;gt;...&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;  ...&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;link_to&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;more...&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;/products/all&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;load-more&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:remote&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The server returns plain &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; and we use the &lt;code&gt;ajax:x&lt;/code&gt; events triggered by the Rails &lt;span class=&quot;caps&quot;&gt;UJS&lt;/span&gt; drivers (here jQuery) to grab the server&amp;#8217;s response and insert it into the right element on the page:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;erb&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;javascript_tag&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;  $(&amp;quot;#load-more&amp;quot;).bind(&amp;quot;ajax:complete&amp;quot;, function(et, e){&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;    $(&amp;quot;#products-list&amp;quot;).html(e.responseText); // insert content&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;  });&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If desired, we can also use the &lt;code&gt;ajax:loading&lt;/code&gt; event to change the link text (or show a spinner):&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;erb&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;javascript_tag&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;  $(&amp;quot;#load-more&amp;quot;).bind(&amp;quot;ajax:loading&amp;quot;, function(et, e){&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;    $(this).html(&amp;quot;Loading...&amp;quot;); // swap link text&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;  });&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2&gt;Unexpected Token Error&lt;/h2&gt;
&lt;p&gt;In implementing the above solution you may receive a JavaScript error, something like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;Uncaught SyntaxError: Unexpected token
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Nathaniel Bibler explains:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s the problem: if you&amp;#8217;re building a RESTful interface in Rails, then you&amp;#8217;ve probably got &lt;code&gt;respond_to&lt;/code&gt;s setup for &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; and JS. So, in this case, the browser load hits &lt;code&gt;/products&lt;/code&gt; and loads the original product list. It renders a link to &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt; load the additional products. Let&amp;#8217;s say that action is also to &lt;code&gt;/products&lt;/code&gt; (but for JS). So, as you&amp;#8217;ve described in your tutorial, you&amp;#8217;d like to just render &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; back to the client for the JS request. That&amp;#8217;s fine, except that by default jQuery will expect that it&amp;#8217;s executable JavaScript, since it&amp;#8217;s making a JavaScript request (this is defined by the &lt;code&gt;jQuery.ajax(:dataType)&lt;/code&gt;). So it&amp;#8217;ll get the &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; string back and attempt to interpret it as javascript and blow up.&lt;/p&gt;
&lt;p&gt;To fix that, you&amp;#8217;d think you can just set the &lt;code&gt;dataType&lt;/code&gt; to &lt;code&gt;'html'&lt;/code&gt;. Well, yes, and no. That fixes it from jQuery&amp;#8217;s perspective. It will no longer try to execute it and you&amp;#8217;ve now gotten past the Unexpected token issue. But, in doing so, jQuery will now make the &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt; request with an &lt;code&gt;Accept: text/html&lt;/code&gt; header. So, Rails will now think you&amp;#8217;re a web browser requesting the standard &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; page and will not render your JS view. So, now you&amp;#8217;re sending back the page with full layout. To sum up, jQuery and Rails are not quite on the same page if you&amp;#8217;re making a &amp;#8220;javascript&amp;#8221; request but returning &amp;#8220;html.&amp;#8221; It breaks things.&lt;/p&gt;
&lt;p&gt;By the way, you can dictate the &lt;code&gt;dataType&lt;/code&gt; to use by setting a &lt;code&gt;&quot;data-type&quot;&lt;/code&gt; attribute on your remote link:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;erb&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;link_to&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;foo&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;/foo&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:remote&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;data-type&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;html&amp;#39;&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;which renders:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;/foo&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-remote=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;true&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;html&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;foo&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If, however, you want this functionality, I would suggest using the &lt;code&gt;&quot;text&quot;&lt;/code&gt; data-type. Basically what would happen here is that jQuery will not execute the returned content. So, that fixes your first issue. Rails will still, however, attempt to render a &lt;span class=&quot;caps&quot;&gt;TEXT&lt;/span&gt; response, since jQuery will post an Accept header with &lt;code&gt;&quot;text/plain&quot;&lt;/code&gt; in it, first. As long as you don&amp;#8217;t have a &lt;code&gt;respond_to&lt;/code&gt; defined for &lt;code&gt;&quot;txt&quot;&lt;/code&gt; (or some other &lt;code&gt;&quot;text/plain&quot;&lt;/code&gt;), then Rails will continue down the &lt;code&gt;Accept&lt;/code&gt; header string to locate an acceptable response. jQuery is smart enough to also contain an &lt;code&gt;application/javascript&lt;/code&gt; string in there, so, eventually, Rails will decide that a JavaScript response is acceptable, and render the JS response you&amp;#8217;re expecting. It&amp;#8217;s very slightly hacky, but it works.&lt;/p&gt;</description>
    </item>

    <item>
      <title>You Don't Understand Edward Tufte</title>
      <author>Alex Reisner</author>
      <pubDate>2010-04-23T00:00:00-07:00</pubDate>
      <link>http://code.alexreisner.com/articles/edward-tufte.html</link>
      <guid>http://code.alexreisner.com/articles/edward-tufte.html</guid>
      <description>&lt;p&gt;Or at least there are a lot of people writing about data graphics right now who don&amp;#8217;t. This is not to say that &lt;a href=&quot;http://www.edwardtufte.com/&quot;&gt;Tufte&lt;/a&gt; is the end-all for data graphics design, but that if you&amp;#8217;re going to call something &amp;#8220;Tufte-esque&amp;#8221; you should understand what Tufte is preaching.&lt;/p&gt;
&lt;p&gt;Tufte preaches a lot of things, actually, but I believe his philosophy can be summed up like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Be efficient. Show as many &lt;em&gt;relationships&lt;/em&gt; as can be clearly read, and maximize the amount of information conveyed by every drop of ink on the page.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Of course there&amp;#8217;s more to his philosophy, but that&amp;#8217;s the crux of it. Tufte wants you to be concise, and remove everything that isn&amp;#8217;t necessary. In a way he is to graphic design what &lt;a href=&quot;http://www.useit.com/papers/webwriting/&quot;&gt;Jakob Nielsen&lt;/a&gt; is to writing. Here are some things which have been referred to as &amp;#8220;Tufte-esque&amp;#8221; (not necessarily by the authors):&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://lumberjaph.net/blog/index.php/2010/03/25/github-explorer/&quot;&gt;Github explorer&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.flickr.com/photos/bartonpoulson/3239934482/&quot;&gt;medical graphics&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.youtube.com/watch?v=lBvaHZIrt0o&quot;&gt;Royksopp&amp;#8217;s &amp;#8216;Remind Me&amp;#8217; video&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tufte is not about being slick, colorful, or particularly &amp;#8220;pretty.&amp;#8221; His graphics are beautiful in their expressive power, not necessarily in their aesthetic appeal (though they sometimes are that as well). This is not a criticism of the above graphics, it is just to say that they are not &amp;#8220;Tufte-esque.&amp;#8221;&lt;/p&gt;</description>
    </item>

    <item>
      <title>Time in Words</title>
      <author>Alex Reisner</author>
      <pubDate>2010-04-15T00:00:00-07:00</pubDate>
      <link>http://code.alexreisner.com/articles/time-in-words.html</link>
      <guid>http://code.alexreisner.com/articles/time-in-words.html</guid>
      <description>&lt;p&gt;The trend during the past several years towards labels like:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;2 hours ago&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;instead of timestamps like:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;3:47pm&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;is something I&amp;#8217;ve never been completely comfortable with. I think the problem the wordy labels try to solve (quick understanding of a point in time relative to the present) is real and I think they are a decent solution, but they create another problem in the process.&lt;/p&gt;
&lt;p&gt;I experience this new problem most often on my cell phone which tells me that I received a call &lt;code&gt;1 hour ago&lt;/code&gt;, meaning anything from 60 to 119 minutes ago. If I was on a call with a client and I need to know how long it was for billing purposes, &lt;code&gt;1 hour ago&lt;/code&gt; is not good enough. Why do I get a more precise time if I look at the call log in a week when it gives up trying to use words and tells me the actual date and time the call was started?&lt;/p&gt;
&lt;p&gt;Web sites which list user content in non-chronological order (eg: &lt;a href=&quot;http://www.stackoverflow.com&quot;&gt;Stack Overflow&lt;/a&gt;) often do this too, making it hard to determine what was written first, which is vital if the content is at all conversational. Again, come back in a week and it will be &lt;code&gt;10:42am&lt;/code&gt; instead of &lt;code&gt;2 hours ago&lt;/code&gt;, but why can&amp;#8217;t we know the exact time when it was just a few hours ago? Often that&amp;#8217;s when you need it the most.&lt;/p&gt;
&lt;p&gt;Unfortunately I don&amp;#8217;t have a great alternative solution to this problem. Using a combination of the two:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;2 hours ago (10:42am)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;p&gt;&lt;code&gt;10:42am (2 hours ago)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;is a obvious but inelegant (and potentially confusing) answer. In some situations colors or shading could be used to indicate the relative position of a given timestamp, for example:&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color:#222&quot;&gt;08:50pm&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color:#333&quot;&gt;07:02pm&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color:#444&quot;&gt;06:43pm&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color:#555&quot;&gt;05:33pm&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color:#666&quot;&gt;04:17pm&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color:#777&quot;&gt;03:30pm&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color:#888&quot;&gt;02:38pm&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color:#999&quot;&gt;01:35pm&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color:#aaa&quot;&gt;12:34pm&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color:#bbb&quot;&gt;11:05am&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color:#ccc&quot;&gt;10:42am&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;But this is only applicable in situations like above where many timestamps are listed together, since we don&amp;#8217;t have any natural associations between colors and the idea of &amp;#8220;recentness&amp;#8221; (though perhaps there&amp;#8217;s a metaphor that I haven&amp;#8217;t thought of like red for hot/recent). Text size could also be used, like this:&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size:125%&quot;&gt;08:50pm&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-size:120%&quot;&gt;07:02pm&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-size:115%&quot;&gt;06:43pm&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-size:110%&quot;&gt;05:33pm&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-size:105%&quot;&gt;04:17pm&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-size:100%&quot;&gt;03:30pm&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-size:95%&quot;&gt;02:38pm&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-size:90%&quot;&gt;01:35pm&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-size:85%&quot;&gt;12:34pm&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-size:80%&quot;&gt;11:05am&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-size:75%&quot;&gt;10:42am&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;but it looks a little goofy. &lt;a href=&quot;http://en.wikipedia.org/wiki/Tag_cloud&quot;&gt;Tag clouds&lt;/a&gt; seem to work, but again that&amp;#8217;s many things listed together so the visual differences become immediately apparent, if not their meaning.&lt;/p&gt;
&lt;p&gt;If anyone has a better idea, please post a comment.&lt;/p&gt;</description>
    </item>

    <item>
      <title>When You Disagree With Your Client</title>
      <author>Alex Reisner</author>
      <pubDate>2010-03-17T00:00:00-07:00</pubDate>
      <link>http://code.alexreisner.com/articles/the-disagree-list.html</link>
      <guid>http://code.alexreisner.com/articles/the-disagree-list.html</guid>
      <description>&lt;p&gt;Another programmer was recently looking over the code for one of my clients&amp;#8217; web sites and remarked that I should write about a file in my Git repository called &lt;span class=&quot;caps&quot;&gt;DISAGREE&lt;/span&gt;. Here&amp;#8217;s a quick explanation.&lt;/p&gt;
&lt;h2&gt;What It Is&lt;/h2&gt;
&lt;p&gt;The &amp;#8220;disagree list&amp;#8221; (&lt;code&gt;doc/DISAGREE&lt;/code&gt;) is a file I maintain with my for-hire projects. It&amp;#8217;s basically a list of points on which I disagree with the client. Let&amp;#8217;s say the client wants to add 15 new items to the web site&amp;#8217;s main navigation bar. I say that it&amp;#8217;s not good idea to have so many links up there and I recommend against it. Why not create a sub-navbar or a sidebar instead?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;No, these all &lt;em&gt;need&lt;/em&gt; to be in the &lt;em&gt;main navigation bar at the top, very big, OK?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Fine, I relent. I do the job and I make a note in the disagree list that gets committed to the repo along with the code. The disagree list entry has a title, a date, and briefly summarizes the discussion: what the client wanted, why I disagreed, and what alternative I proposed. It also refers to dates and subjects of emails if relevant.&lt;/p&gt;
&lt;h2&gt;Why?&lt;/h2&gt;
&lt;p&gt;In the course of technical projects, there are always disagreements. Documenting them has several benefits:&lt;/p&gt;
&lt;p&gt;It &lt;strong&gt;adds a dimension to the code&lt;/strong&gt;, providing some meta-information on top of the &lt;span class=&quot;caps&quot;&gt;VCS&lt;/span&gt; log entries. It provides good introductory material for new programmers coming on the job, and gives you something to refer to in your code comments when you&amp;#8217;re explaining that you &amp;#8220;wouldn&amp;#8217;t normally do this, but&amp;#8230;&amp;#8221;&lt;/p&gt;
&lt;p&gt;It &lt;strong&gt;helps you feel better about your work&lt;/strong&gt; by allowing you to take a positive action (writing prose) to counteract work which feels negative.&lt;/p&gt;
&lt;p&gt;It &lt;strong&gt;keeps you honest&lt;/strong&gt; by reminding you about when you&amp;#8217;ve been wrong, and also when you pushed too hard to support a plan or idea that just didn&amp;#8217;t matter that much. This kind of self-reflection helps you become a better programmer, and a more valuable team member.&lt;/p&gt;
&lt;p&gt;It &lt;strong&gt;helps you gently remind the client about the times you&amp;#8217;ve been right&lt;/strong&gt;. Being able to quickly and eloquently defend yourself gives you some extra bargaining power in future discussions about the project. If you can refer to specific instances when the client &lt;em&gt;should&lt;/em&gt; have heeded your advice, there is a better chance that your current position will be taken seriously.&lt;/p&gt;
&lt;p&gt;It &lt;strong&gt;backs you up&lt;/strong&gt; in case something you disagreed with goes &lt;em&gt;really&lt;/em&gt; wrong. Fortunately I have no personal experience with this, but I imagine that if a situation gets to a point where legal action is involved, having a written, dated record of your position could help.&lt;/p&gt;
&lt;p&gt;It &lt;strong&gt;lets you know when to quit&lt;/strong&gt;. On those days when you&amp;#8217;re fed up, take a look at the disagree list. It will remind you of the kind of discussions and behavior you&amp;#8217;ve been around. Do the arguments seem important? Interesting? When decisions are finally made, do you have as much input as you need to feel professionally satisfied? You can easily show the list to someone you trust for an outside opinion.&lt;/p&gt;
&lt;p&gt;In my experience, disagreements are worth documenting, and the time to document them is when they arise. Since they are often emotionally charged, memory is not reliable in recalling details. To the extent that your happiness on the job depends on the way conflicts are resolved, the disagree list is important.&lt;/p&gt;</description>
    </item>

    <item>
      <title>Sending Email From Your Web Site</title>
      <author>Alex Reisner</author>
      <pubDate>2010-03-10T00:00:00-08:00</pubDate>
      <link>http://code.alexreisner.com/articles/sending-email.html</link>
      <guid>http://code.alexreisner.com/articles/sending-email.html</guid>
      <description>&lt;p&gt;If you&amp;#8217;ve ever run a web site which sends email to its users you may have found yourself on the opposite end of the spam problem. That is, receiving servers think your emails are spam and refuse to accept them. If you&amp;#8217;re sending customer invoices, order confirmations, or product download instructions, this is a serious problem. You may be tempted to use an external service for sending emails, and this may be a good solution in your case, but I would argue that any well-configured web server should be able to successfully send emails. What about the output of cron jobs? Or developer notifications when errors occur? Web servers need to communicate with us, and *nix systems are naturally inclined to do it through email. So how to we make it work?&lt;/p&gt;
&lt;p&gt;There is a &lt;em&gt;lot&lt;/em&gt; of advice out there on how to make sure messages are delivered properly (and if you&amp;#8217;ve visited some of the URLs strewn about your mail server logs you may be wondering if any of it is worthwhile). Some actions you can take are very helpful. Some, like getting yourself off Comcast&amp;#8217;s blacklist, are recipient-specific and probably not worth your time. Some are completely useless. In the following paragraphs I&amp;#8217;ll summarize the advice that has worked for me, in roughly descending order of importance. Please note that I am not an expert on mail server admininstration, just a web developer who needs to send some emails!&lt;/p&gt;
&lt;h2&gt;1. Avoid Sending Spam&lt;/h2&gt;
&lt;p&gt;This may sound either obvious or irrelevant, but it&amp;#8217;s really important to be familiar with the ways you could be sending spam without even knowing it.&lt;/p&gt;
&lt;h3&gt;Don&amp;#8217;t Send Email To People Who Don&amp;#8217;t Want It&lt;/h3&gt;
&lt;p&gt;Much spam filtering these days is done by techniques (such as Bayesian classification) which rely on users reporting received messages as spam or not-spam. If you don&amp;#8217;t want your messages marked as spam, you should avoid sending them to people who might do so. You should also provide clear instructions for un-subscribing from your mailing list (and have an &lt;em&gt;actual working un-subscribe procedure&lt;/em&gt;).&lt;/p&gt;
&lt;h3&gt;Configure Your &lt;span class=&quot;caps&quot;&gt;MTA&lt;/span&gt; Properly&lt;/h3&gt;
&lt;p&gt;Before you install an &lt;span class=&quot;caps&quot;&gt;MTA&lt;/span&gt; (Message Transfer Agent, eg: Sendmail, Postfix), make sure you&amp;#8217;re familiar with basic configuration of the software, and the implications of running an &lt;span class=&quot;caps&quot;&gt;MTA&lt;/span&gt;. &lt;strong&gt;Running an &lt;span class=&quot;caps&quot;&gt;MTA&lt;/span&gt; is not like running a web server. You can cause real problems for yourself and others (see below).&lt;/strong&gt; Be sure to read &lt;em&gt;more than one&lt;/em&gt; tutorial on setting up your particular &lt;span class=&quot;caps&quot;&gt;MTA&lt;/span&gt;, and don&amp;#8217;t forget &amp;#8220;obvious&amp;#8221; things like setting the proper hostname/mailname so your messages come from the correct domain.&lt;/p&gt;
&lt;h4&gt;Don&amp;#8217;t Be an Open Relay&lt;/h4&gt;
&lt;p&gt;An open relay is an &lt;span class=&quot;caps&quot;&gt;MTA&lt;/span&gt; which can be used by anyone to send mail to any address. Unfortunately this is the default configuration for some MTAs. &lt;a href=&quot;http://www.abuse.net/relay.html&quot;&gt;If you are an open relay&lt;/a&gt; it&amp;#8217;s just a matter of time until a spammer finds you and uses your server to send thousands of emails, getting you blacklisted in the process. Repeat: you will certainly be blacklisted if you are an open relay.&lt;/p&gt;
&lt;h4&gt;Avoid Backscatter&lt;/h4&gt;
&lt;p&gt;Backscatter are bounced emails, usually that were never intended to be successfully delivered. Suppose a spammer wants to send an email to victim@poorsaps.com. If they send an email to a non-existent user on your system that appears to be &lt;em&gt;from&lt;/em&gt; victim@poorsaps.com (forged sender address), your server will &amp;#8220;return&amp;#8221; that message to the victim. Clever, eh?&lt;/p&gt;
&lt;h4&gt;Easy Solution to Open Relay and Backscatter Problems&lt;/h4&gt;
&lt;p&gt;If your server&amp;#8217;s main function is to be a web server, and it doesn&amp;#8217;t host any user accounts that need to send email, I recommend simply rejecting non-local connections on port 25 (&lt;span class=&quot;caps&quot;&gt;SMTP&lt;/span&gt;). I do this in Postfix with this line at the top of &lt;code&gt;/etc/postfix/master.cf&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;127.0.0.1:smtp   inet   n   -   n   -   -   smtpd
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This ensures that you&amp;#8217;re not even wasting &lt;span class=&quot;caps&quot;&gt;CPU&lt;/span&gt; cycles communicating over malicious connections. If you need to accept &lt;span class=&quot;caps&quot;&gt;SMTP&lt;/span&gt; connections, use authentication and &lt;a href=&quot;http://unixwiz.net/techtips/postfix-HELO.html&quot;&gt;make sure your &lt;span class=&quot;caps&quot;&gt;HELO&lt;/span&gt; response matches your hostname&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;2. Remove Your Server From Spamhaus&amp;#8217;s Blocklists&lt;/h2&gt;
&lt;p&gt;Start by &lt;a href=&quot;http://www.spamhaus.org/lookup.lasso&quot;&gt;checking if you&amp;#8217;re on Spamhaus&amp;#8217;s blocklists&lt;/a&gt;. Chances are your server&amp;#8217;s IP address is on the Policy Block List (&lt;span class=&quot;caps&quot;&gt;PBL&lt;/span&gt;). If so, &lt;strong&gt;don&amp;#8217;t get mad at Spamhaus&lt;/strong&gt;. The &lt;span class=&quot;caps&quot;&gt;PBL&lt;/span&gt; is a &lt;strong&gt;block&lt;/strong&gt; list, not a &lt;strong&gt;black&lt;/strong&gt; list, and Spamhaus isn&amp;#8217;t telling everyone that you&amp;#8217;re a spammer. Because most computers connected to the Internet don&amp;#8217;t send email, all IP addresses are on the &lt;span class=&quot;caps&quot;&gt;PBL&lt;/span&gt; by default. If you want to send email you simply get yourself de-listed (it doesn&amp;#8217;t take long). This is a good thing. The only unfortunate part is that most people don&amp;#8217;t know about it.&lt;/p&gt;
&lt;p&gt;If your IP address is on the &lt;span class=&quot;caps&quot;&gt;SBL&lt;/span&gt; or &lt;span class=&quot;caps&quot;&gt;XBL&lt;/span&gt; you may have a problem. Before doing anything else, go back to step #1 and make sure you&amp;#8217;re not sending spam. If you&amp;#8217;re absolutely certain that your server is not sending spam you can try to get yourself removed from Spamhaus&amp;#8217;s list, or contact your hosting provider for a new IP address (you may have inherited a previous customer&amp;#8217;s problem).&lt;/p&gt;
&lt;h2&gt;3. Configure Reverse &lt;span class=&quot;caps&quot;&gt;DNS&lt;/span&gt; Lookups&lt;/h2&gt;
&lt;p&gt;Not configuring reverse &lt;span class=&quot;caps&quot;&gt;DNS&lt;/span&gt; is nearly equivalent in effect to being listed in Spamhaus&amp;#8217;s &lt;span class=&quot;caps&quot;&gt;PBL&lt;/span&gt;: many servers simply will not accept your messages. Look for reverse &lt;span class=&quot;caps&quot;&gt;DNS&lt;/span&gt; configuration in your hosting provier&amp;#8217;s control panel. To configure, just map your server&amp;#8217;s IP address to your site&amp;#8217;s domain name. Simple, yet effective.&lt;/p&gt;
&lt;h2&gt;4. Format Messages Properly&lt;/h2&gt;
&lt;p&gt;This is just common sense. There is a standard format for email (&lt;a href=&quot;http://www.ietf.org/rfc/rfc2822.txt&quot;&gt;&lt;span class=&quot;caps&quot;&gt;RFC&lt;/span&gt; 2821: Internet Message Format&lt;/a&gt;), so you should adhere to it. Some highlights from the &lt;span class=&quot;caps&quot;&gt;RFC&lt;/span&gt;:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;each line &lt;em&gt;should&lt;/em&gt; be no more than 78 and &lt;em&gt;must&lt;/em&gt; be no more than 998 characters&lt;/li&gt;
	&lt;li&gt;each line &lt;em&gt;must&lt;/em&gt; be terminated with a &lt;span class=&quot;caps&quot;&gt;CRLF&lt;/span&gt;&lt;/li&gt;
	&lt;li&gt;headers &lt;em&gt;must&lt;/em&gt; contain &lt;em&gt;only&lt;/em&gt; US-&lt;span class=&quot;caps&quot;&gt;ASCII&lt;/span&gt; characters (&lt;span class=&quot;caps&quot;&gt;ASCII&lt;/span&gt; 32-126 inclusive)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You should also follow &lt;a href=&quot;http://www.w3.org/standards/webdesign/htmlcss&quot;&gt;W3C &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; standards&lt;/a&gt; if you&amp;#8217;re sending &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; email.&lt;/p&gt;
&lt;h2&gt;5. Create &lt;span class=&quot;caps&quot;&gt;SPF&lt;/span&gt; Records&lt;/h2&gt;
&lt;p&gt;This is an important step for delivering messages to Google accounts. An &lt;span class=&quot;caps&quot;&gt;SPF&lt;/span&gt; record is a &lt;span class=&quot;caps&quot;&gt;TXT&lt;/span&gt; record in your domain&amp;#8217;s zone configuration which authorizes servers to send mail from your domain. For example, to authorize only the servers named in your A and MX records, create a &lt;span class=&quot;caps&quot;&gt;TXT&lt;/span&gt; record with this content:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;v=spf1 a mx ~all&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Be sure to include the quotes. If you need a different configuration you can use &lt;a href=&quot;http://old.openspf.org/wizard.html&quot;&gt;OpenSPF&amp;#8217;s wizard&lt;/a&gt; to generate the record for you. I was able to confirm that my &lt;span class=&quot;caps&quot;&gt;SPF&lt;/span&gt; record was working by noting the following header in an email sent from my server:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;Received-SPF: pass &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;google.com: domain of admin@domain.com designates
  xxx.xxx.xxx.xxx as permitted sender&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; client-ip&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;xxx.xxx.xxx.xxx;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;and the following in some spam which appeared to be from my domain:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;Received-SPF: softfail &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;google.com: best guess record &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;domain of
  transitioning spammer@alexreisner.com does not designate
  yyy.yyy.yyy.yyy as permitted sender&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; client-ip&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;yyy.yyy.yyy.yyy;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I use Google Apps for email, and I imagine that if you use a different service which doesn&amp;#8217;t care about &lt;span class=&quot;caps&quot;&gt;SPF&lt;/span&gt; records, you will see no such confirmation. If anyone knows of a general method for checking &lt;span class=&quot;caps&quot;&gt;SPF&lt;/span&gt; configuration could you please explain it in a comment?&lt;/p&gt;
&lt;h2&gt;6. Send All Messages From the Same Address&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://mail.google.com/support/bin/answer.py?answer=81126#authentication&quot;&gt;Google says you should do this&lt;/a&gt;, presumably so that you can be more accurately followed by address-based reputation tracking mechanisms.&lt;/p&gt;
&lt;h2&gt;7. Sign Email With DomainKeys or &lt;span class=&quot;caps&quot;&gt;DKIM&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;I haven&amp;#8217;t actually set up my &lt;span class=&quot;caps&quot;&gt;MTA&lt;/span&gt; with DomainKeys or &lt;span class=&quot;caps&quot;&gt;DKIM&lt;/span&gt;, but my guess is that they will be help when delivering messages to Yahoo! accounts. Basically, they provide cryptographic verification of an email&amp;#8217;s origin. DomainKeys and &lt;span class=&quot;caps&quot;&gt;DKIM&lt;/span&gt; are &lt;a href=&quot;http://blogs.boomerang.com/blog/2009/07/21/domain-keys-vs-dkim/&quot;&gt;two different standards&lt;/a&gt; (you only need to implement one).&lt;/p&gt;
&lt;h2&gt;8. Use &amp;#8216;Precedence: bulk&amp;#8217; for Bulk Emails?&lt;/h2&gt;
&lt;p&gt;This one is a little confusing. &lt;a href=&quot;https://mail.google.com/support/bin/answer.py?answer=81126&quot;&gt;Google recommends using the Precedence header&lt;/a&gt; while &lt;a href=&quot;http://www.faqs.org/rfcs/rfc2076.html&quot;&gt;&lt;span class=&quot;caps&quot;&gt;RFC&lt;/span&gt; 2076&lt;/a&gt; recommends &lt;em&gt;against&lt;/em&gt; it. Ostensibly setting &lt;code&gt;Precedence: bulk&lt;/code&gt; lets recipient servers know that your email is not urgent and therefore helps the Internet operate more smoothly. You might think that this would identify your email as spam, but think about it: would a spammer really mark their messages as bulk email?&lt;/p&gt;
&lt;p&gt;Use or not, as you see fit.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Sending email from a web server can be daunting, and repeated failure can be discouraging. I hope the above tips are helpful to you. You can check your status as a sender on Cisco&amp;#8217;s &lt;a href=&quot;http://www.senderbase.org/&quot;&gt;SenderBase&lt;/a&gt; and try to move from Poor to Good. You can go from Poor to Neutral in just a few days, so don&amp;#8217;t despair.&lt;/p&gt;</description>
    </item>

    <item>
      <title>JavaScript Framework Translation Guide</title>
      <author>Alex Reisner</author>
      <pubDate>2010-03-05T00:00:00-08:00</pubDate>
      <link>http://code.alexreisner.com/articles/javascript-framework-translation.html</link>
      <guid>http://code.alexreisner.com/articles/javascript-framework-translation.html</guid>
      <description>&lt;p&gt;You may have already chosen your favorite JavaScript framework, but if you&amp;#8217;re working on many different sites, chances are you need to know how to use some other frameworks as well. What follows is a mini translation dictionary: instructions for accomplishing some common tasks in &lt;a href=&quot;http://jquery.com/&quot;&gt;jQuery&lt;/a&gt;, &lt;a href=&quot;http://prototypejs.org/&quot;&gt;Prototype&lt;/a&gt;, &lt;a href=&quot;http://mootools.net/&quot;&gt;MooTools&lt;/a&gt;, and &lt;a href=&quot;http://developer.yahoo.com/yui/&quot;&gt;&lt;span class=&quot;caps&quot;&gt;YUI&lt;/span&gt;&lt;/a&gt; (versions 2 and 3). This should also serve as a means for superficial comparison of the libraries.&lt;/p&gt;
&lt;h2&gt;Event Listeners&lt;/h2&gt;
&lt;h3&gt;&lt;span class=&quot;caps&quot;&gt;DOM&lt;/span&gt; Ready&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://api.jquery.com/ready&quot;&gt;&lt;strong&gt;jQuery&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ready&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(...);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://www.prototypejs.org/api/document/observe&quot;&gt;&lt;strong&gt;Prototype&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;observe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;dom:loaded&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://mootools.net/docs/core/Utilities/DomReady&quot;&gt;&lt;strong&gt;MooTools&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;domready&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://developer.yahoo.com/yui/examples/event/event-timing.html&quot;&gt;&lt;strong&gt;YUI2&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;YAHOO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;onDOMReady&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(...);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://developer.yahoo.com/yui/3/examples/event/event-timing.html&quot;&gt;&lt;strong&gt;YUI3&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;YUI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;base&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;Y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;domready&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;Page Fully Loaded (including images, etc)&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://api.jquery.com/load-event&quot;&gt;&lt;strong&gt;jQuery&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(...);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://www.prototypejs.org/api/document/observe&quot;&gt;&lt;strong&gt;Prototype&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;observe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;load&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://demos111.mootools.net/DomReadyVS.Load&quot;&gt;&lt;strong&gt;MooTools&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;load&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://developer.yahoo.com/yui/examples/event/event-timing.html&quot;&gt;&lt;strong&gt;YUI2&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;YAHOO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;onContentReady&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(...);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://developer.yahoo.com/yui/3/examples/event/event-timing.html&quot;&gt;&lt;strong&gt;YUI3&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;YUI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;base&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;Y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;load&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;Respond to Click Event&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://api.jquery.com/bind&quot;&gt;&lt;strong&gt;jQuery&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;#id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;click&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){...});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://www.prototypejs.org/api/event/observe&quot;&gt;&lt;strong&gt;Prototype&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;observe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;click&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){...});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://mootools.net/docs/core/Element/Element.Event#Element:addEvent&quot;&gt;&lt;strong&gt;MooTools&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;click&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){...});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://developer.yahoo.com/yui/event&quot;&gt;&lt;strong&gt;YUI2&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;YAHOO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addListener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;click&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){...});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://developer.yahoo.com/yui/3/event&quot;&gt;&lt;strong&gt;YUI3&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;YUI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;node-base&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;Y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;click&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){...},&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;#id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2&gt;&lt;span class=&quot;caps&quot;&gt;DOM&lt;/span&gt; Manipulation&lt;/h2&gt;
&lt;p&gt;Note that most frameworks&amp;#8217; selectors return proxies (eg, a &lt;code&gt;jQuery&lt;/code&gt; object) instead of actual &lt;span class=&quot;caps&quot;&gt;DOM&lt;/span&gt; objects. Please see each framework&amp;#8217;s documentation for methods of manipulating &lt;span class=&quot;caps&quot;&gt;DOM&lt;/span&gt; elements.&lt;/p&gt;
&lt;h3&gt;Get Element By ID&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://api.jquery.com/jQuery&quot;&gt;&lt;strong&gt;jQuery&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;#id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://api.prototypejs.org/dom/dollar.html&quot;&gt;&lt;strong&gt;Prototype&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// or $$(&amp;quot;#id&amp;quot;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://mootools.net/docs/core/Utilities/Selectors&quot;&gt;&lt;strong&gt;MooTools&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://developer.yahoo.com/yui/docs/YAHOO.util.Dom.html#method_get&quot;&gt;&lt;strong&gt;YUI2&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;YAHOO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Dom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://developer.yahoo.com/yui/3/api/Node.html#method_one&quot;&gt;&lt;strong&gt;YUI3&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;YUI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;node&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;Y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;one&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;#id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;Get All &amp;lt;p&amp;gt;s Within an Element&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://api.jquery.com/jQuery/&quot;&gt;&lt;strong&gt;jQuery&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;#id p&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// returns a jQuery object&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://api.prototypejs.org/dom/dollardollar.html&quot;&gt;&lt;strong&gt;Prototype&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;$$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;#id p&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://mootools.net/docs/core/Utilities/Selectors#Element:getElements&quot;&gt;&lt;strong&gt;MooTools&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;p&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://developer.yahoo.com/yui/docs/YAHOO.util.Dom.html#method_getChildrenBy&quot;&gt;&lt;strong&gt;YUI2&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;YAHOO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Dom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getChildrenBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;nodeName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;p&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://developer.yahoo.com/yui/3/api/Node.html#method_one&quot;&gt;&lt;strong&gt;YUI3&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;YUI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;node&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;Y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;one&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;#id p&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;Append Child Element to a Parent&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://api.jquery.com/append&quot;&gt;&lt;strong&gt;jQuery&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;#id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(...);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://www.prototypejs.org/api/element/insert&quot;&gt;&lt;strong&gt;Prototype&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(...);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://mootools.net/docs/core/Element/Element#Element:inject&quot;&gt;&lt;strong&gt;MooTools&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;inject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(...);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://developer.yahoo.com/yui/docs/YAHOO.util.Element.html#method_appendChild&quot;&gt;&lt;strong&gt;YUI2&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;YAHOO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Dom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(...);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://developer.yahoo.com/yui/3/api/Node.html#method_appendChild&quot;&gt;&lt;strong&gt;YUI3&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;YUI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;node&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;Y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;one&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;#id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(...);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2&gt;&lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;span class=&quot;caps&quot;&gt;GET&lt;/span&gt; Request With Parameters (and Handle Successful Response)&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://api.jquery.com/jQuery.get/&quot;&gt;&lt;strong&gt;jQuery&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;/url&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;params&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){...});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://api.prototypejs.org/ajax/ajax/request.html&quot;&gt;&lt;strong&gt;Prototype&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Ajax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;/url&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;     &lt;span class=&quot;s2&quot;&gt;&amp;quot;get&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;parameters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;params&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;onSuccess&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){...}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://mootools.net/docs/core/Request/Request&quot;&gt;&lt;strong&gt;MooTools&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;    &lt;span class=&quot;s2&quot;&gt;&amp;quot;get&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;       &lt;span class=&quot;s2&quot;&gt;&amp;quot;/url&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;params&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;onSuccess&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xml&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){...}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://developer.yahoo.com/yui/connection/&quot;&gt;&lt;strong&gt;YUI2&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;YAHOO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Connect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;asyncRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;GET&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;/url?with=params&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;success&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){...}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://developer.yahoo.com/yui/3/io/&quot;&gt;&lt;strong&gt;YUI3&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;YUI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;io&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;Y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;/url?with=params&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;success&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){...}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;</description>
    </item>

    <item>
      <title>Keeping Daemons Alive With Upstart</title>
      <author>Alex Reisner</author>
      <pubDate>2010-02-10T00:00:00-08:00</pubDate>
      <link>http://code.alexreisner.com/articles/upstart.html</link>
      <guid>http://code.alexreisner.com/articles/upstart.html</guid>
      <description>&lt;p&gt;As web programmers we&amp;#8217;re generally pretty comfortable with daemon processes like web and database servers. These programs (eg: Apache and MySQL) have robust and proven methods of keeping themselves alive. Even if they occasionally die they seem to come back to life on their own, and no real knowledge of this mechanism is necessary for their use.&lt;/p&gt;
&lt;p&gt;But maybe you&amp;#8217;re starting to use other daemons like &lt;a href=&quot;http://memcached.org/&quot;&gt;Memcached&lt;/a&gt;, &lt;a href=&quot;http://code.google.com/p/redis/&quot;&gt;Redis&lt;/a&gt;, or &lt;a href=&quot;http://github.com/collectiveidea/delayed_job&quot;&gt;Delayed Job&lt;/a&gt; which don&amp;#8217;t come with your operating system in convenient pre-configured packages, or you need a newer version than your package manager provides. What then? Will your daemons be as reliable as the popular server software we&amp;#8217;re accustomed to? What are the risks?&lt;/p&gt;
&lt;h2&gt;What Can Go Wrong?&lt;/h2&gt;
&lt;p&gt;In a live web application? Lots of things. Let&amp;#8217;s say you&amp;#8217;re on vacation&amp;#8212;these things usually happen when you&amp;#8217;re on vacation&amp;#8212;and you get an email one morning from your hosting provider stating that your machine was &amp;#8220;unresponsive&amp;#8221; and needed to be rebooted. You then discover that while Apache or Nginx started up automatically, your Mongrels didn&amp;#8217;t, and your site has been down for the past 10 hours.&lt;/p&gt;
&lt;p&gt;There are a lot of Bad Things that can happen to daemons, but I think about them in terms of three basic types:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;A daemon doesn&amp;#8217;t start up after a machine re-boot (often by your hosting provider due to maintenance or malfunction).&lt;/li&gt;
	&lt;li&gt;A daemon crashes due to a software bug or a hardware problem (eg: bad memory).&lt;/li&gt;
	&lt;li&gt;A daemon is running but unresponsive: hogging resources and doing nothing.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;A Simple Safety Mechanism&lt;/h2&gt;
&lt;p&gt;Protecting yourself from all three types of problems requires monitoring software, like &lt;a href=&quot;http://mmonit.com/monit/&quot;&gt;Monit&lt;/a&gt;. However, in my experience, the first two problems (non-running daemons) are by far the most common, and I&amp;#8217;d like to propose a solution to them which is still new to me, but which is very appealing due to its simplicity.&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;re using a recent version of Ubuntu or Fedora Linux your system uses &lt;a href=&quot;http://upstart.ubuntu.com/&quot;&gt;Upstart&lt;/a&gt; instead of the traditional &lt;a href=&quot;http://en.wikipedia.org/wiki/Sysvinit&quot;&gt;SysVInit&lt;/a&gt; for controlling processes on system boot. Upstart, which is &lt;strong&gt;far&lt;/strong&gt; more powerful and interesting than SysVInit, can (1) start daemons when your machine boots up, and (2) re-start them when they crash. It requires no additional software, and is extraordinarily easy to configure. For example, to have Upstart manage my Delayed Job daemon, I add this config file to my Rails application at &lt;code&gt;config/delayed_job&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Start when system enters runlevel 2 (multi-user mode).&lt;/span&gt;
start on runlevel 2

&lt;span class=&quot;c&quot;&gt;# Start delayed_job via the daemon control script.&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; /usr/bin/env &lt;span class=&quot;nv&quot;&gt;RAILS_ENV&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;production /path/to/app/script/delayed_job start

&lt;span class=&quot;c&quot;&gt;# Restart the process if it dies with a signal&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# or exit code not given by the &amp;#39;normal exit&amp;#39; stanza.&lt;/span&gt;
respawn

&lt;span class=&quot;c&quot;&gt;# Give up if restart occurs 10 times in 90 seconds.&lt;/span&gt;
respawn limit 10 90
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I then create a symbolic link to it in the Upstart config directory:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /etc/event.d
sudo ln -s /path/to/app/config/delayed_job
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;That&amp;#8217;s it! Delayed Job will now restart if it crashes or the machine is rebooted. To start the daemon for the first time I run:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;sudo initctl start delayed_job
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Again, this is something I&amp;#8217;ve just started using. I found out about Upstart recently and it seems like a good solution to a problem which doesn&amp;#8217;t always warrant a process monitor (ie, for non-critical services on small sites). I&amp;#8217;m sure there&amp;#8217;s a better way to configure Upstart. In fact, I suspect there&amp;#8217;s a way to configure Upstart (in the current or a future version) to handle unresponsive daemons. Upstart is a powerful event-driven tool which may eventually replace cron on Ubuntu. If you can make any improvements to the code I&amp;#8217;ve posted here, &lt;em&gt;please&lt;/em&gt; leave a comment below.&lt;/p&gt;</description>
    </item>

    <item>
      <title>Intro to Event-Driven Programming: Using a SAX Parser</title>
      <author>Alex Reisner</author>
      <pubDate>2010-01-27T00:00:00-08:00</pubDate>
      <link>http://code.alexreisner.com/articles/sax-parser.html</link>
      <guid>http://code.alexreisner.com/articles/sax-parser.html</guid>
      <description>&lt;p&gt;Event-driven programming is not a new paradigm: the concepts were developed in the late 1970s and most UI programming is event-driven. Until recently, however, it has not been a major topic in the back-end web programming world. Now, thanks in part to the proliferation of &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt; and excellent libraries like &lt;a href=&quot;http://www.twistedmatrix.com/&quot;&gt;Twisted&lt;/a&gt; and &lt;a href=&quot;http://nodejs.org/&quot;&gt;node.js&lt;/a&gt;, it is beginning to enter the consciousness of Ruby, Python, and &lt;span class=&quot;caps&quot;&gt;PHP&lt;/span&gt; developers. As an introduction to event-driven programming outside of a UI context I will present a solution to a common problem: parsing a large &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; file without running out of memory.&lt;/p&gt;
&lt;h2&gt;The Conventional Method&lt;/h2&gt;
&lt;p&gt;What you&amp;#8217;ve probably been doing is basically batch programming. In batch programming, the flow of execution is completely determined by the programmer via method calls, object instantiation, etc. If you write a batch script to parse an &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; file, the sequence of events is something like this:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Load &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; file (preferably with a file/IO object).&lt;/li&gt;
	&lt;li&gt;Parse file, building a huge data structure in memory.&lt;/li&gt;
	&lt;li&gt;Iterate through each element in the structure and do your business.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If your &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; file is very large, this approach is going to fail (or at least become very slow) at step #2 when the data structure won&amp;#8217;t fit in memory. In Ruby code, using the &lt;a href=&quot;http://nokogiri.org/&quot;&gt;Nokogiri&lt;/a&gt; gem, the code might look like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# Load file.&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;users.xml&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Parse file.&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;doc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Nokogiri&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;XML&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Do some business with each element.&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;doc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;user&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_s&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# more business...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The parser used here uses the &lt;em&gt;&lt;span class=&quot;caps&quot;&gt;DOM&lt;/span&gt; parsing&lt;/em&gt; method, in which the entire Document Object Model is loaded into memory in one step. Fortunately there is another technique for reading an &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; document, known as &lt;em&gt;&lt;span class=&quot;caps&quot;&gt;SAX&lt;/span&gt; parsing&lt;/em&gt; (Simple &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; for &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt;), which allows us to deal with elements in the document as they come off the grill, rather than waiting for the whole enchilada to finish cooking.&lt;/p&gt;
&lt;h2&gt;The Event-Driven Solution&lt;/h2&gt;
&lt;p&gt;The event-driven solution, using a &lt;span class=&quot;caps&quot;&gt;SAX&lt;/span&gt; parser, looks something like this:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Create event handlers which take parsed &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; elements and perform business on them.&lt;/li&gt;
	&lt;li&gt;Give your parser the event handler and the &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; file, and set it in motion.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Instead of creating an enormous data structure, the parser reads the file from disk and passes each &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; element to the event handler as it is encountered. The event handler deals with the data and then becomes idle again, waiting for the next event.&lt;/p&gt;
&lt;p&gt;Program execution is therefore somewhat different than what you are probably used to: the parser runs linearly, but the event handler (which contains the important business logic) is being called willy nilly as the parser goes through the file. Here&amp;#8217;s some code demonstrating this technique with Nokogiri&amp;#8217;s &lt;span class=&quot;caps&quot;&gt;SAX&lt;/span&gt; parser:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;##&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Class representing a parse-able XML document&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# with a known set of elements.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UsersData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Nokogiri&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;XML&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;SAX&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Document&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;##&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# Handle the start_element event:&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# process element if it&amp;#39;s a &amp;lt;user&amp;gt;.&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;#&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;start_element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;element&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;user&amp;#39;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Hash&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# more business...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Create a parser and give it an event handler object.&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Nokogiri&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;XML&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;SAX&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;UsersData&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Turn the parser loose on the data file.&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;users.xml&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This design is a little counter-intuitive at first but, in addition to being memory-efficient, it can help organize your code. For example, as an &lt;span class=&quot;caps&quot;&gt;OOP&lt;/span&gt; programmer, I like the way a class is created to model the &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; document. Once you&amp;#8217;re comfortable with the idea of an event it makes a lot of sense to do it this way, especially when parsing multiple files of the same format. In fact, I would argue that creating a class representing the document is a good design even when parsing with the traditional approach.&lt;/p&gt;
&lt;p&gt;I haven&amp;#8217;t gone into the theory behind event-driven programming, but hopefully this has helped you get your feet wet and made you feel a little more comfortable with event-driven design.&lt;/p&gt;</description>
    </item>

    <item>
      <title>Anatomy of a Ruby Web Application</title>
      <author>Alex Reisner</author>
      <pubDate>2010-01-18T00:00:00-08:00</pubDate>
      <link>http://code.alexreisner.com/articles/anatomy-of-a-ruby-web-application.html</link>
      <guid>http://code.alexreisner.com/articles/anatomy-of-a-ruby-web-application.html</guid>
      <description>&lt;p&gt;So, you&amp;#8217;ve heard about some fancy (and supposedly fast) deployment strategy for Rails applications and you want to try it out, but it&amp;#8217;s sounds complicated. Application servers? Rack? Reverse proxies? What are these things and how do they all fit together?&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s start exploring at the bottom of the stack, with our Rails (or other) application code, and work our way up. I&amp;#8217;ll give names of various libraries and servers along the way, but this is not a tutorial on setting up Mongrel with Nginx, or any other configuration. This article is about understanding Ruby web application deployment in general, so you are better informed and more able to evaluate new technologies and participate in conversations.&lt;/p&gt;
&lt;h2&gt;Application Code&lt;/h2&gt;
&lt;p&gt;At the bottom of the stack is your application code. It may be written for a web framework like Rails, Sinatra, or Camping, or it may be a simple stand-alone script. The key point is that, while your code describes the behavior of a web site, there is usually no obvious way to &amp;#8220;run&amp;#8221; the code by itself. Sure, if you&amp;#8217;re using Rails you can type &lt;code&gt;ruby script/server&lt;/code&gt; and you can see it in your browser at localhost:3000, but you didn&amp;#8217;t write the code that makes this happen, there&amp;#8217;s something else (WEBrick, Mongrel, etc) which is part of your framework that does this: a Ruby web server.&lt;/p&gt;
&lt;h2&gt;Ruby Web Server&lt;/h2&gt;
&lt;p&gt;You&amp;#8217;re probably used to thinking of Apache, Lighttpd, and Nginx when you think of web servers, but what is a &lt;em&gt;web server&lt;/em&gt; in a generic sense? A &amp;#8220;server&amp;#8221; is a daemon (program running in the background) that communicates with clients, and &amp;#8220;web&amp;#8221; indicates the language of the world wide web: &lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt;. A &lt;em&gt;Ruby&lt;/em&gt; web server uses a Ruby application to generate its responses (it &amp;#8220;serves the application&amp;#8221;).&lt;/p&gt;
&lt;p&gt;More succinctly: a Ruby web server is a daemon that listens for &lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt; requests, gives them to your Ruby application, and responds with a web page (the output of your app).&lt;/p&gt;
&lt;p&gt;It may be educational to see this in action with a very simple app. If you have Mongrel installed, save this script as &lt;code&gt;app.rb&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;rubygems&amp;#39;&lt;/span&gt;  
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;mongrel&amp;#39;&lt;/span&gt;  
  
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BareApp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Mongrel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;HttpHandler&lt;/span&gt;  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  
    &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;  
      &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inspect&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;  
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;  
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;  
  
&lt;span class=&quot;n&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Mongrel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;HttpServer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;0.0.0.0&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;5000&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  
&lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;BareApp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  
&lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Then type &lt;code&gt;ruby app.rb&lt;/code&gt; and visit &lt;a href=&quot;http://localhost:5000/&quot;&gt;http://localhost:5000&lt;/a&gt; in your web browser. You should see a dump of the &lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt; request parameters sent by your browser (generated by &lt;code&gt;request.params.inspect&lt;/code&gt;) with names like &lt;code&gt;REQUEST_METHOD&lt;/code&gt;, &lt;code&gt;PATH_INFO&lt;/code&gt;, &lt;code&gt;QUERY_STRING&lt;/code&gt;, etc. You just ran what is known as a &amp;#8220;bare Mongrel handler&amp;#8221;&amp;#8212;an extremely simple application served by Mongrel.&lt;/p&gt;
&lt;p&gt;The exact same thing happens when a complex Rails application is served by Mongrel: your application code is executed within in the &lt;code&gt;process&lt;/code&gt; method of a Mongrel::HttpHandler instance. &lt;strong&gt;This &lt;em&gt;isn&amp;#8217;t&lt;/em&gt; an oversimplification:&lt;/strong&gt; the next time you get a development error page in a Mongrel-served Rails application, take a look at the full backtrace; somewhere near the bottom you&amp;#8217;ll see something like &lt;code&gt;.../mongrel.rb:64:in `process'&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So, &lt;a href=&quot;http://mongrel.rubyforge.org/&quot;&gt;Mongrel&lt;/a&gt; is a Ruby web server, or a &lt;em&gt;Ruby app server&lt;/em&gt;. Some other Ruby app servers are:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://swiftiply.swiftcore.org/mongrel.html&quot;&gt;Evented Mongrel&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://code.macournoyer.com/thin/&quot;&gt;Thin&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://microjet.ath.cx/webrickguide/html/&quot;&gt;WEBrick&lt;/a&gt; (comes with Ruby)&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://raa.ruby-lang.org/project/unicorn/&quot;&gt;Unicorn&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.modrails.com/&quot;&gt;Passenger&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As seen in the above example, if our web application is to be served by Mongrel, it needs to know about Mongrel&amp;#8217;s &lt;code&gt;process&lt;/code&gt; method. If it is to be served by a different app server, it needs to know how to interact with that server.&lt;/p&gt;
&lt;h2&gt;Rack&lt;/h2&gt;
&lt;p&gt;The first line of the &lt;a href=&quot;http://rack.rubyforge.org/doc/SPEC.html&quot;&gt;Rack interface specification&lt;/a&gt; is very readable:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A Rack application is an Ruby object (not a class) that responds to &lt;code&gt;call&lt;/code&gt;. It takes exactly one argument, the &lt;strong&gt;environment&lt;/strong&gt; and returns an Array of exactly three values: The &lt;strong&gt;status&lt;/strong&gt;, the &lt;strong&gt;headers&lt;/strong&gt;, and the &lt;strong&gt;body&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That&amp;#8217;s an awfully good summary of what Rack does. The &lt;code&gt;environment&lt;/code&gt; parameter is that hash we displayed in our bare Mongrel handler above, and the &lt;code&gt;call&lt;/code&gt; method is like Mongrel&amp;#8217;s &lt;code&gt;process&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve gone out of order here&amp;#8212;Rack fits in between your code and the app server. It basically turns your application into the object described in the Rack interface specification and passes input/output from/to the web server so that your application/framework doesn&amp;#8217;t need to know how the app server works.&lt;/p&gt;
&lt;p&gt;Rack is a piece of software, but it&amp;#8217;s small, and its main purpose is to enforce an interface specification. (Rack is similar to Python&amp;#8217;s &lt;a href=&quot;http://wsgi.org/wsgi/&quot;&gt;&lt;span class=&quot;caps&quot;&gt;WSGI&lt;/span&gt;&lt;/a&gt;.)&lt;/p&gt;
&lt;h2&gt;Another Web Server?&lt;/h2&gt;
&lt;p&gt;At this point you may be wondering why people are talking about using Apache or Nginx in their stack. Don&amp;#8217;t we already have a web server? We do, but the Ruby app server is not a full-featured web server, and it&amp;#8217;s not very good at sending images and other kinds of static files (in fact all app servers are terrible at this, which is why it&amp;#8217;s better to call them &amp;#8220;app servers&amp;#8221; than &amp;#8220;web servers,&amp;#8221; though the two terms are often used interchangeably). So what we want to do is use a general purpose web server for static files, and pass other requests along to our app server.&lt;/p&gt;
&lt;p&gt;This is one of the most complicated and least standardized parts of Ruby web app configuration. Serving static files and handing off requests doesn&amp;#8217;t take much processor power, so for a small web site our web server shouldn&amp;#8217;t be too busy. The app server, on the other hand, is running our complicated Ruby application, and could be quite busy. For this reason one usually deploys multiple app servers (listening on different ports) for the web server to choose from when a request comes in. The process of handing requests off to these servers is called &lt;em&gt;reverse proxy&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;(If you&amp;#8217;ve worked for a large company you&amp;#8217;re probably familiar with accessing the Internet through a forward proxy server. Forward proxy is for outbound&amp;#8212;client-side&amp;#8212;requests, reverse proxy is for inbound&amp;#8212;server-side&amp;#8212;requests.)&lt;/p&gt;
&lt;p&gt;One of the most difficult parts of a reverse proxy server&amp;#8217;s job is load balancing: handing off a given request to the most available app server. How this works in various setups is beyond the scope of this article, but you should know that there are many solutions to this problem, and none of the good ones are as trivial as you might think at first.&lt;/p&gt;
&lt;h2&gt;Learning More&lt;/h2&gt;
&lt;p&gt;To learn more you might want to read about &lt;a href=&quot;http://github.com/blog/530-how-we-made-github-fast&quot;&gt;GitHub&amp;#8217;s setup&lt;/a&gt;. It&amp;#8217;s fairly complicated due to their need to work extensively with the filesystem, but their choices of technology are thoroughly researched and very smart, and the article is fairly readable.&lt;/p&gt;
&lt;p&gt;Thanks to Phusion Passenger (easy-to-install app server, reverse proxy, and load balancer in one), it is no longer necessary to fully understand the intricacies of Ruby web application deployment. However, there is a lot of interesting technology out there, and I believe that some investigation will enhance your appreciation for web programming, and make you a more complete developer. Plus, you never know when you&amp;#8217;ll outgrow Passenger!&lt;/p&gt;</description>
    </item>

    <item>
      <title>Single Table Inheritance in Rails</title>
      <author>Alex Reisner</author>
      <pubDate>2009-12-10T00:00:00-08:00</pubDate>
      <link>http://code.alexreisner.com/articles/single-table-inheritance-in-rails.html</link>
      <guid>http://code.alexreisner.com/articles/single-table-inheritance-in-rails.html</guid>
      <description>&lt;p&gt;&lt;em&gt;Updated 18 May 2011&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Because single table inheritance (&lt;span class=&quot;caps&quot;&gt;STI&lt;/span&gt;) has been invaluable to me in some recent Rails projects, I thought I&amp;#8217;d try to dispel a little of its negative reputation by writing about some reasons you might use it, when to avoid it, and some &lt;a href=&quot;#tips&quot;&gt;tips&lt;/a&gt; for working with it. If you gave up on Rails&amp;#8217;s &lt;span class=&quot;caps&quot;&gt;STI&lt;/span&gt; a while ago because it required too many workarounds, I&amp;#8217;d recommend giving it another look, as some annoyances (eg, regarding &lt;a href=&quot;http://webonrails.com/2007/10/26/single-table-inheritance-validates_uniqueness_of-problem/&quot;&gt;validation&lt;/a&gt; and &lt;a href=&quot;http://ananasblau.com/2008/6/1/single-table-inheritance-in-rails-2-1&quot;&gt;demodulization&lt;/a&gt;) have recently been fixed.&lt;/p&gt;
&lt;p&gt;For this article I&amp;#8217;m assuming you know what &lt;span class=&quot;caps&quot;&gt;STI&lt;/span&gt; is and how to set it up (add a &lt;code&gt;type&lt;/code&gt; column and inherit from a parent class). I&amp;#8217;m also assuming that you&amp;#8217;re familiar with &lt;a href=&quot;http://www.andygoh.net/2008/06/19/ruby-on-rails-polymorphic-association&quot;&gt;polymorphic associations&lt;/a&gt; and using modules to share code among different classes. Just because you know how to use these techniques doesn&amp;#8217;t mean deciding which one to use is easy.&lt;/p&gt;
&lt;h2&gt;When To Use It&lt;/h2&gt;
&lt;p&gt;Suppose you have three classes in your application which model similar things. To make this easier to think about I&amp;#8217;ll be referring to some hypothetical classes by name: &lt;code&gt;Car&lt;/code&gt;, &lt;code&gt;Truck&lt;/code&gt;, and &lt;code&gt;Motorcycle&lt;/code&gt;. Let&amp;#8217;s consider three choices for modeling this situation:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Polymorphic Associations&lt;/strong&gt; (separate classes, multiple tables)&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Single Table Inheritance&lt;/strong&gt; (separate classes, one table)&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Single Class&lt;/strong&gt; with conditionals (one class, one table)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With &lt;em&gt;Polymorphic Associations&lt;/em&gt; we use modules to share code among classes. A Single Class is not exactly a design pattern, or anything particularly interesting. I&amp;#8217;m thinking of a model with a &lt;code&gt;type&lt;/code&gt;-like attribute (maybe called &lt;code&gt;kind&lt;/code&gt;) and some &lt;code&gt;if&lt;/code&gt; statements in methods where you need different behavior for different kinds of objects. &lt;span class=&quot;caps&quot;&gt;OOP&lt;/span&gt; purists &lt;em&gt;hate&lt;/em&gt; this, but it works well in the real world when there are only a few slight differences between object types and separate classes are overkill.&lt;/p&gt;
&lt;p&gt;When deciding how to design your data models, here are some questions to ask yourself:&lt;/p&gt;
&lt;h3&gt;1. Are the objects, conceptually, children of a single parent?&lt;/h3&gt;
&lt;p&gt;First and foremost, your design choice needs to be understandable. In the case of a car, a truck, and a motorcycle, it seems perfectly reasonable to think of them all as vehicles. If you add a bicycle and a wheelbarrow it may become confusing because, in our minds, these things are not as vehicle-like as a car. This is to say: don&amp;#8217;t use single table inheritance just because your classes share some attributes (eg: &lt;code&gt;num_wheels&lt;/code&gt;, &lt;code&gt;color&lt;/code&gt;, &lt;code&gt;length&lt;/code&gt;), make sure there is actually an OO inheritance relationship between each of them and an understandable parent class. And be sure to choose class names carefully.&lt;/p&gt;
&lt;h3&gt;2. Do you need to do database queries on all objects together?&lt;/h3&gt;
&lt;p&gt;If you want to list the objects together or run aggregate queries on all of the data, you&amp;#8217;ll probably want everything in the same database table for speed and simplicity, especially if there is a lot of data. This points to a &lt;em&gt;Single Table Inheritance&lt;/em&gt; or a &lt;em&gt;Single Class&lt;/em&gt; design.&lt;/p&gt;
&lt;p&gt;Remember that while &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt; is optimized for doing joins and ActiveRecord provides tools to make them easier, data separation may not be worth the increase in complexity for database operations. In the real world, 100% normalized data is not always the best design.&lt;/p&gt;
&lt;h3&gt;3. Do the objects have similar data but different behavior?&lt;/h3&gt;
&lt;p&gt;How many database columns are shared by every model? If there are going to be many model-specific columns, you should consider &lt;em&gt;Polymorphic Associations&lt;/em&gt;. On the other hand, if a Car, Truck, and Motorcycle all have the same attributes, eg:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;color&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;engine_size&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;price&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;but different method implementations, eg:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;drivetrain_weight&lt;/code&gt;                # sums different components&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;value_after_depreciation(years)&lt;/code&gt;  # uses different depreciation rates&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;drivers_license_certifications&lt;/code&gt;   # references different certifications&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;then &lt;em&gt;Single Table Inheritance&lt;/em&gt; is probably a good design choice. If there are only minor differences in a few methods, you may want to &amp;#8220;cheat&amp;#8221; and go with a &lt;em&gt;Single Class&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&quot;tips&quot;&gt;Single Table Inheritance Tips&lt;/h2&gt;
&lt;p&gt;Here are some things that can make your &lt;span class=&quot;caps&quot;&gt;STI&lt;/span&gt; experience more enjoyable.&lt;/p&gt;
&lt;h3&gt;Use a Single Controller&lt;/h3&gt;
&lt;p&gt;This may not &lt;em&gt;always&lt;/em&gt; apply, but I have yet to see a case where &lt;span class=&quot;caps&quot;&gt;STI&lt;/span&gt; works well with multiple controllers. If we are using &lt;span class=&quot;caps&quot;&gt;STI&lt;/span&gt;, our objects share a set of IDs and attributes, and therefore should all be accessed in basically the same way (find by some attribute, sort by some attribute, restrict to administrators, etc). If presentation varies greatly we may want to render different model-specific views from our controller. But if object access varies so much that it suggests separate controllers, then &lt;span class=&quot;caps&quot;&gt;STI&lt;/span&gt; may not have been the correct design choice.&lt;/p&gt;
&lt;h3&gt;Put All Fixtures in the Parent&amp;#8217;s File&lt;/h3&gt;
&lt;p&gt;If you&amp;#8217;re using Rails&amp;#8217;s fixtures for testing your app, remember that there is a one-to-one relationship between fixture files and database tables. With &lt;span class=&quot;caps&quot;&gt;STI&lt;/span&gt;, everything is in one table, so in our example we&amp;#8217;d have a single &lt;code&gt;test/fixtures/vehicles.yml&lt;/code&gt; file with all our fixtures in it (be sure to provide a &lt;code&gt;type&lt;/code&gt; attribute value for every record).&lt;/p&gt;
&lt;h3&gt;Allow Children To Use Their Parent&amp;#8217;s Routes&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Updated Dec 14, 2010&lt;/strong&gt;: Now more robust, courtesy of Nathan McWilliams.&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;ve ever tried to add &lt;span class=&quot;caps&quot;&gt;STI&lt;/span&gt; to an existing Rails application you probably know that many of your &lt;code&gt;link_to&lt;/code&gt; and &lt;code&gt;form_for&lt;/code&gt; methods throw errors when you add a parent class. This is because ActionPack looks at the class of an object to determine its path and &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt;, and you haven&amp;#8217;t mapped routes for your new subclasses. You can add the routes like so, though I don&amp;#8217;t recommend it:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# NOT recommended:&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;resources&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:cars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;        &lt;span class=&quot;ss&quot;&gt;:as&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:vehicles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:controller&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:vehicles&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;resources&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:trucks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;      &lt;span class=&quot;ss&quot;&gt;:as&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:vehicles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:controller&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:vehicles&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;resources&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:motorcycles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:as&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:vehicles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:controller&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:vehicles&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This only alleviates a particular symptom. If we use &lt;code&gt;form_for&lt;/code&gt;, our form fields will still not have the names we expect (eg: &lt;code&gt;params[:car][:color]&lt;/code&gt; instead of &lt;code&gt;params[:vehicle][:color]&lt;/code&gt;). Instead, we should attack the root of the problem by implementing the &lt;code&gt;model_name&lt;/code&gt; method in our parent class. I haven&amp;#8217;t seen any documentation for this technique, so this is very unofficial, but it makes sense and it works perfectly for me in Rails 2.3 and 3:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inherited&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;child&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;child&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance_eval&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;model_name&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;Vehicle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;model_name&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This probably looks confusing, so let me explain:&lt;/p&gt;
&lt;p&gt;When you call a &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt;-generating method (eg: &lt;code&gt;link_to(&quot;car&quot;, car)&lt;/code&gt;), ActionPack calls &lt;code&gt;model_name&lt;/code&gt; on the class of the given object (here &lt;code&gt;car&lt;/code&gt;). This returns a special type of string that determines what the object is called in URLs. All we&amp;#8217;re doing here is overriding the &lt;code&gt;model_name&lt;/code&gt; method for subclasses of &lt;code&gt;Vehicle&lt;/code&gt; so ActionPack will see &lt;code&gt;Car&lt;/code&gt;, &lt;code&gt;Truck&lt;/code&gt;, and &lt;code&gt;Motorcycle&lt;/code&gt; subclasses as belonging to the parent class (&lt;code&gt;Vehicle&lt;/code&gt;), and thus use the parent class&amp;#8217;s named routes (&lt;code&gt;VehiclesController&lt;/code&gt;) wherever URLs are generated. This is all assuming you&amp;#8217;re using Rails resource-style (RESTful) URLs. (If you&amp;#8217;re not, please do.)&lt;/p&gt;
&lt;p&gt;To investigate the &lt;code&gt;model_name&lt;/code&gt; invocation yourself, see the Rails source code for the &lt;code&gt;ActionController::RecordIdentifier#model_name_from_record_or_class&lt;/code&gt; method. In Rails 2.3 the special string is an instance of &lt;code&gt;ActiveSupport::ModelName&lt;/code&gt;, in Rails 3 it&amp;#8217;s an &lt;code&gt;ActiveModel::Name&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;Make The Parent Class Aware of Its Children&lt;/h3&gt;
&lt;p&gt;Let&amp;#8217;s say we want to provide a single form for creating a Vehicle object, so the first field is a select menu where the user chooses the object class (Car, Truck, or Motorcycle). How do we know what the options are without hard-coding the class names into the select field? We can use Ruby&amp;#8217;s &lt;code&gt;inherited&lt;/code&gt; hook method to keep a running list of children as they inherit from the parent. It turns out that ActiveRecord actually does this already, so we could implement a &lt;code&gt;Vehicle.select_options&lt;/code&gt; method like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;select_options&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;descendants&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_s&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sort&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Internally, ActiveRecord uses ActiveSupport&amp;#8217;s &lt;code&gt;DescendantsTracker&lt;/code&gt; module (versions prior to Rails 3 use a class variable &lt;code&gt;@@subclasses&lt;/code&gt; which is accessible only through the protected method &lt;code&gt;subclasses&lt;/code&gt;). This is another trick I discovered while reading the Rails source code (&amp;#8220;unofficial&amp;#8221; as far as I know), so if you don&amp;#8217;t like the feel of it we can re-implement the behavior directly in our parent class:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;vi&quot;&gt;@child_classes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inherited&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;child&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;vi&quot;&gt;@child_classes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;child&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# important!&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;child_classes&lt;/span&gt;
  &lt;span class=&quot;vi&quot;&gt;@child_classes&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In either case, we still have one more problem to solve: child classes are not recognized by the parent until they are loaded. In typical Rails production and test environments this happens right away, but in development, where &lt;code&gt;config.cache_classes == false&lt;/code&gt;, classes aren&amp;#8217;t loaded until you call upon them. So, for this to work consistently in our development environment we need to manually require classes:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# add config/initializers/preload_sti_models.rb:&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;development?&lt;/span&gt;
  &lt;span class=&quot;sx&quot;&gt;%w[vehicle car truck motorcycle]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;require_dependency&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;app&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;models&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.rb&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;It&amp;#8217;s important to understand that classes are lazy loaded in the development environment so you avoid &lt;a href=&quot;http://sean-carley.blogspot.com/2006/05/when-rails-needs-clue-single-table.html&quot;&gt;serious problems&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That&amp;#8217;s all for now. Good luck.&lt;/p&gt;</description>
    </item>

    <item>
      <title>A Standard for Open Source Code Documentation</title>
      <author>Alex Reisner</author>
      <pubDate>2009-12-04T00:00:00-08:00</pubDate>
      <link>http://code.alexreisner.com/articles/code-documentation-standard.html</link>
      <guid>http://code.alexreisner.com/articles/code-documentation-standard.html</guid>
      <description>&lt;p&gt;While the idea may at first seem silly, oversimplified, and too general, I&amp;#8217;d like to propose a standard format for documentation of open source projects. I know that every project is different and that this sounds ludicrous, but bear with me for just a few paragraphs and I think you&amp;#8217;ll see why I think this is a good idea.&lt;/p&gt;
&lt;h2&gt;Motivation&lt;/h2&gt;
&lt;p&gt;As code writers, a standard format would save us from having to design documentation for every project we create. It&amp;#8217;s much faster and easier to write when you&amp;#8217;re filling in blanks than when you&amp;#8217;re thinking about structure. My hope is that if the process is faster and easier then more of us will write better documentation.&lt;/p&gt;
&lt;p&gt;A standard format may also make documentation easier to understand because readers come to it possessing a basic familiarity with its structure. In most types of product design it&amp;#8217;s best to imagine a single user (real or hypothetical) and design exactly what they want. Trying to include something for everyone is a great way to satisfy no one, and the same principle applies to documentation. While it&amp;#8217;s true that everyone learns differently, I think a carefully-planned and well-edited document will accommodate a high percentage of readers. Trying to satisfy everyone leads to too much documentation, which is impractical for the maintainer and overwhelming to the reader.&lt;/p&gt;
&lt;p&gt;Anyway, without further delay, here is a first draft of my proposed standard. I seek your feedback.&lt;/p&gt;
&lt;h2&gt;The Standard (First Draft)&lt;/h2&gt;
&lt;p&gt;Documentation should be broken up into five sections. All sections do &lt;strong&gt;not&lt;/strong&gt; need to appear on the same page, and it is often most practical (and appropriate) for sections to appear on different sites (eg, a auto-generated &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; doc host, an &amp;#8220;official&amp;#8221; home page, a video tutorial host, etc). However, each section must contain links to every other section to give context and easy access.&lt;/p&gt;
&lt;p&gt;There should also be a clear order to the sections. Two of the sections I propose (IV and V) will have non-linear content within, but the overall starting point should be obvious to the newcomer. One shouldn&amp;#8217;t need to &amp;#8220;figure out&amp;#8221; how to read the documentation.&lt;/p&gt;
&lt;p&gt;In the following sections I frequently write as if you are the documentation reader, not the writer. I do this to put you in what I hope is a useful mindset. It&amp;#8217;s hard to make yourself unfamiliar with your own project so it&amp;#8217;s good to think about experiences you&amp;#8217;ve had with other people&amp;#8217;s documentation. And it should be obvious that documentation should be designed based on what is useful to the reader, not what is easy for the writer.&lt;/p&gt;
&lt;p&gt;Note that at this stage I am not proposing formal names for the sections, and am not sure whether or not specific names should be part of the standard.&lt;/p&gt;
&lt;h3&gt;I. What it is and why you might want to use it&lt;/h3&gt;
&lt;p&gt;This is very important, and often overlooked. Frequently we look up a piece of software because we heard the name, it sounded exciting, and we want to know if we have a use for it. We may not know:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;what problems it solves&lt;/li&gt;
	&lt;li&gt;how it works (environment, dependencies)&lt;/li&gt;
	&lt;li&gt;its shortcomings&lt;/li&gt;
	&lt;li&gt;what it&amp;#8217;s &lt;em&gt;not&lt;/em&gt; intended for&lt;/li&gt;
	&lt;li&gt;how it compares to alternatives&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All this information is extremely useful, and it is perhaps the most difficult section for the software author to write. As programmers we know intimately what our code does, and this familiarity makes it hard for us to understand what it&amp;#8217;s like for someone not to know. For this reason it&amp;#8217;s good to write this part of the documentation early in the development of your project, ideally even before it&amp;#8217;s started. Of course you&amp;#8217;ll tweak it as you go along and add features or change the focus, but it&amp;#8217;s important to lay the groundwork and set the tone while you&amp;#8217;re a sort of newcomer to your project. Once you know something, it&amp;#8217;s hard to forget it.&lt;/p&gt;
&lt;h3&gt;II. How to download/purchase, install, and configure it&lt;/h3&gt;
&lt;p&gt;In the case of free open source software, a download will often be available very near the documentation, but there&amp;#8217;s no telling where your documentation will appear in the future (you might need to move a section somewhere else), so it&amp;#8217;s best to pretend that you are writing a good old-fashioned book without clickable hyperlinks. Tell your readers:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;how to obtain your software (download &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt;, package manager command)&lt;/li&gt;
	&lt;li&gt;how to install it (on any platform where it runs)&lt;/li&gt;
	&lt;li&gt;what the most common, basic configuration options are (if any)&lt;/li&gt;
	&lt;li&gt;a method for confirming that the software is installed successfully&lt;/li&gt;
	&lt;li&gt;common problems encountered with installation&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;span class=&quot;caps&quot;&gt;III&lt;/span&gt;. How to get started with it (a tutorial)&lt;/h3&gt;
&lt;p&gt;Once a piece of software is installed, you want to get started using it by doing something simple to get a feel for the style and operational paradigm of the interface. It may not be what you ultimately want to do with the software, but if you have &lt;em&gt;something&lt;/em&gt; working within five or ten minutes you&amp;#8217;re usually feeling pretty confident. Make this happen for your readers.&lt;/p&gt;
&lt;h3&gt;IV. How to do more advanced things with it (topical guides)&lt;/h3&gt;
&lt;p&gt;The above three sections will often be located in the code&amp;#8217;s &lt;span class=&quot;caps&quot;&gt;README&lt;/span&gt; file. This is the first section which will probably be located elsewhere, as it may grow to be fairly long and is not intended to be read linearly. To that end, it should be well-indexed (with table of contents) with subjects ordered from easy to hard. It&amp;#8217;s difficult to come up with interesting examples in the abstract, so explain the ways you&amp;#8217;ve used the project yourself, or ways you could use it that you actually find interesting. As people contact you with &amp;#8220;How do I ___?&amp;#8221; questions, add guides for them.&lt;/p&gt;
&lt;h3&gt;V. &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; documentation (auto-generated)&lt;/h3&gt;
&lt;p&gt;Finally, good &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; documentation is very important for large projects. If you are writing a Rails plugin that provides two methods you probably don&amp;#8217;t need &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; documentation. However, your code should &lt;em&gt;always&lt;/em&gt; be well-commented and part of writing documentation is going back and cleaning up your in-code comments. If you&amp;#8217;re like me, you&amp;#8217;ll be surprised at how useless many of your method descriptions are.&lt;/p&gt;
&lt;p&gt;The code-writing mindset is very different from the documentation-writing mindset. Usually you will find that your code comments are too specific, that you presume too much knowledge of the context in which a method is called. This is because when you&amp;#8217;re writing a method you usually immerse yourself so deeply in a particular use case that you can&amp;#8217;t see beyond that use case (eg, why someone might be in that situation and how they got there). This mindset is necessary for writing code, and useless for explaining it.&lt;/p&gt;
&lt;p&gt;In short: &lt;em&gt;when you&amp;#8217;re not writing code&lt;/em&gt;, go back and add context to your method comments, and make sure to explain all parameters.&lt;/p&gt;
&lt;h2&gt;Questions, Concerns, and Ideas&lt;/h2&gt;
&lt;p&gt;I&amp;#8217;ve said it several times already, but I think it bears repeating one more time: &lt;strong&gt;it&amp;#8217;s very hard to explain your own code&lt;/strong&gt;. An obvious solution is to have someone else write your documentation. Something I&amp;#8217;d love to see is more contributions to documentation of open source projects. The first reading of a project&amp;#8217;s documentation by a new user is critical. They are in a unique position to make clarifications due to their unfamiliarity with the project. This is why I strongly recommend that sections I, II, and &lt;span class=&quot;caps&quot;&gt;III&lt;/span&gt; above be included in a project&amp;#8217;s code repository where they can be checked out and edited by anyone. This is also a great way to get people into the habit of contributing to the open source projects they use. That first open source contribution is usually the hardest, and contributing English can be less intimidating than contributing code.&lt;/p&gt;
&lt;p&gt;What about the ever-evolving nature of APIs? Does rapid change suggest that comments or discussions are perhaps a better way to document a project than a single large document? I&amp;#8217;ve probably spent more time reading blog posts and other non-official documentation than I have reading the official documentation for every open source projects I&amp;#8217;ve worked with. Once I&amp;#8217;ve read the official documentation, I&amp;#8217;m unlikely to go back to it to see what&amp;#8217;s new, because it feels so static. I may re-read useful sections I know are there, but unless there&amp;#8217;s some indicator that something has been added (since when? when did I last read this?) I&amp;#8217;m not likely to scan for changes. This problem is beyond the scope of this article, but it&amp;#8217;s an important one because it may suggest that the standard I&amp;#8217;m proposing is not ideal. It may mean comments must be allowed on documentation (in addition to edits) or that we need some way of quickly showing what&amp;#8217;s new (maybe edits appear in some comment-like fashion). Wiki-style revisions preserve history, but I think a more explicit indication of changes is needed.&lt;/p&gt;
&lt;p&gt;We also need a way of specifying dates and software version numbers. I think the condition of official documentation is generally so bad that we&amp;#8217;ve become accustomed to assuming it&amp;#8217;s out of date. A mechanism for someone to quickly timestamp a paragraph or section to indicate its up-to-date-ness would be very helpful. (Conversely, users could mark sections or paragraphs as out of date, but this doesn&amp;#8217;t solve the problem of presenting a &amp;#8220;current as of&amp;#8221; date to new users.) I think official documentation often appears old simply because it displays no date.&lt;/p&gt;
&lt;p&gt;Anyway, I hope I&amp;#8217;ve written enough here to convince you that a documentation standard is both possible and useful to the open source community, and that both writers and readers of documentation stand to benefit. Please leave a comment below and let me know what you think.&lt;/p&gt;</description>
    </item>

    <item>
      <title>Troubleshooting Ubuntu Boot Problems</title>
      <author>Alex Reisner</author>
      <pubDate>2009-12-01T00:00:00-08:00</pubDate>
      <link>http://code.alexreisner.com/articles/ubuntu-boot-problems.html</link>
      <guid>http://code.alexreisner.com/articles/ubuntu-boot-problems.html</guid>
      <description>&lt;p&gt;A few weeks ago my computer (then Ubuntu 9.04 Jaunty) froze. I rebooted and received this error message:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;Kernel Panic &amp;#8212; not syncing: No init found.&lt;br /&gt;Try passing init= option to kernel&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I eventually determined that the cause was a bad &lt;span class=&quot;caps&quot;&gt;RAID&lt;/span&gt; controller, but you might see this message due to some other disk problem. You might also see a message like:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;Target filesystem doesn&amp;#8217;t have /sbin/init.  No init found.&lt;br /&gt;Try passing init= bootarg.&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I was a little disappointed with the various message board posts out there for troubleshooting such boot problems so I thought I&amp;#8217;d document what I did. Hopefully it will help someone.&lt;/p&gt;
&lt;p&gt;First, boot from the Ubuntu Live CD (either to command line or X-windows with a terminal app) so you get a working system without using the hard disk. To check the filesystem and correct minor problems you want to run &lt;code&gt;fsck&lt;/code&gt;. First, you have to find the disk and partition:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;sudo fdisk -l&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Usually it will be &lt;code&gt;/dev/sda1&lt;/code&gt; but look over the output of &lt;code&gt;fdisk&lt;/code&gt; to be sure. To run &lt;code&gt;fsck&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;sudo fsck /dev/sda1&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you get a message about a bad superblock you may be in trouble, otherwise there&amp;#8217;s a decent chance &lt;code&gt;fsck&lt;/code&gt; will fix your drive so that you can boot normally again.&lt;/p&gt;</description>
    </item>

    <item>
      <title>Ruminating on Text Editors</title>
      <author>Alex Reisner</author>
      <pubDate>2009-11-25T00:00:00-08:00</pubDate>
      <link>http://code.alexreisner.com/articles/text-editors.html</link>
      <guid>http://code.alexreisner.com/articles/text-editors.html</guid>
      <description>&lt;p&gt;I write code primarily on Ubuntu, and I mostly use the included (and very extensible) GEdit text editor for writing code. A week ago I started playing around with using GVim, which I discovered when I installed Karmic Koala (I knew about Vim, but not GVim). I let the experiment go a little longer than I originally intended, and yesterday I decided to &amp;#8220;stop screwing around&amp;#8221; and go back to GEdit. Moments later, to my surprise, I realized that GEdit is annoying.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve never been a fan of the mouse, which seems a rather primitive input device that has been lucky to survive this long. Many of the things we do on computers are done faster using linear navigation (cycling through a list of choices), and most tasks that do require two-dimensional movement (eg: drawing) are performed more comfortably with a pen and tablet. (I often wish for a good alternative to the free-floating window model, but I&amp;#8217;ve not yet seen a &amp;#8220;tiling&amp;#8221; window manager that&amp;#8217;s adequate.) Also, who wants to use two separate input devices? For reasons of speed ergonomics I&amp;#8217;d really prefer just one.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/images/content/gvim.png&quot;&gt;&lt;img src=&quot;/images/content/gvim.small.png&quot; class=&quot;right&quot; title=&quot;GVim&quot; alt=&quot;GVim&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Anyway, I originally learned Vi out of necessity&amp;#8212;I was working on machines where it was the only text editor installed. Over the years I&amp;#8217;ve used it from time to time, trying to keep the obscure commands in memory more out of some sort of geeky pride than of necessity (one &lt;em&gt;can&lt;/em&gt; use Pico on a headless machine, right?). But this week, after learning some more useful commands like &amp;#8220;fx&amp;#8221; for jumping to the next occurrence of &amp;#8220;x&amp;#8221; and how to yank (copy) and paste, I find I&amp;#8217;m really enjoying the task of editing itself being a bit more programmatic. Rather than rapid tapping on the arrow keys or moving a hand to the mouse and aiming: stop, take a breath, figure out where you need to go, and use the correct command to jump there. It&amp;#8217;s frustrating if you treat it like a &lt;span class=&quot;caps&quot;&gt;GUI&lt;/span&gt; editor and use the arrow keys, but gratifying, and much faster, to do it The VI Way.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/images/content/gedit.png&quot;&gt;&lt;img src=&quot;/images/content/gedit.small.png&quot; class=&quot;right&quot; title=&quot;GEdit&quot; alt=&quot;GEdit&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;My biggest complaint with GVim so far concerns the management of multiple files. This is a problem with every editor I&amp;#8217;ve used, and I&amp;#8217;m wondering if a radically new design is in order. Tabs along the top of the window are generally no good, because if you open too many files you can&amp;#8217;t see them all (and eight or ten files is not nearly enough for programmers). This problem is solvable by auto-adding a row of tabs but the editors I&amp;#8217;ve used don&amp;#8217;t do that, and you&amp;#8217;d still have to go to the mouse to switch. With GEdit you can get a vertical listing of open files along the left-hand side of the window. This works well, but it&amp;#8217;s unstructured (doesn&amp;#8217;t show &lt;em&gt;where&lt;/em&gt; the files are) and doesn&amp;#8217;t provide any easy way to open other files. The TextMate editor for OS X has a good solution to both of these problems with it&amp;#8217;s &lt;em&gt;project drawer&lt;/em&gt;: a collapsible directory tree which can be used for opening files. TextMate also has a row of tabs at the top listing the currently open files. This is all good, but you still have to use the mouse. There&amp;#8217;s a GVim plugin called &lt;a href=&quot;http://github.com/scrooloose/nerdtree&quot;&gt;NERDTree&lt;/a&gt; which gives you a similar directory tree navigator, but GVim has the not-enough-tabs problem and NERDTree itself doesn&amp;#8217;t offer a solution.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/images/content/textmate.png&quot;&gt;&lt;img src=&quot;/images/content/textmate.small.png&quot; class=&quot;right&quot; title=&quot;Textmate&quot; alt=&quot;Textmate&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m not sure what the answer is to all of this. I use a dual 24&amp;quot; widescreen monitor setup and my vision is always filled with windows. If I work on a laptop I make copious use of &amp;#8220;extended desktop&amp;#8221; features. Maybe there&amp;#8217;s a better way, but I find that the more I can see at once, the faster I can see connections and solve problems. If I can&amp;#8217;t see multiple files at once I need to be able to switch among them rapidly. Perhaps the solution is to open multiple text editors so less file switching is needed, though that sounds confusing. Maybe a split window is the less confusing equivalent. I don&amp;#8217;t know. At this point all I&amp;#8217;m suggesting is that there&amp;#8217;s a market for a radically new approach to file editing for programmers.&lt;/p&gt;
&lt;p&gt;And it&amp;#8217;d be great if it didn&amp;#8217;t use the mouse.&lt;/p&gt;</description>
    </item>

    <item>
      <title>CSS Consistency vs. Payload</title>
      <author>Alex Reisner</author>
      <pubDate>2009-11-18T00:00:00-08:00</pubDate>
      <link>http://code.alexreisner.com/articles/css-consistency-vs-payload.html</link>
      <guid>http://code.alexreisner.com/articles/css-consistency-vs-payload.html</guid>
      <description>&lt;p&gt;Managing stylesheets is a challenge in any web application. If you&amp;#8217;ve worked much with object-oriented programming you may be naturally inclined to use OO techniques when designing &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt;. This is a good idea, of course, as it leads to more modular and reusable code. However it&amp;#8217;s not always straightforward in practice because the size of the code itself (download time) can affect performance. In my experience it is sometimes necessary to sacrifice the benefits of an OO design for speed.&lt;/p&gt;
&lt;h2&gt;The Consistency Rule&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://www.stubbornella.org&quot;&gt;Nicole Miller&lt;/a&gt; has written eloquently about the use of &lt;a href=&quot;http://www.stubbornella.org/content/category/general/geek/css&quot;&gt;object-oriented programming concepts in &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt;&lt;/a&gt; to make your code more efficient and maintainable. She offers many specific recommendations, including the following:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Avoid location-dependent styles.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For example, if you have two second-level headers (&amp;lt;h2&amp;gt;s) that both &lt;em&gt;should&lt;/em&gt; be second level headers but need to look different, &lt;strong&gt;don&amp;#8217;t do this&lt;/strong&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;style &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;text/css&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;.header&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;125&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;green&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;.news&lt;/span&gt;   &lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;108&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;blue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;header&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;...&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
...
&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;news&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;...&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;...&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;...&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Instead, do this&lt;/strong&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;style &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;text/css&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;.header&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;125&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;green&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;.news&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;108&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;blue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;h2&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;header&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;...&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
...
&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;h2&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;news&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;...&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;h2&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;news&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;...&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;h2&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;news&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;...&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The reason for this is consistency: if you copy an &amp;lt;h2&amp;gt; from one part of a page and paste it somewhere else, it should look the same. It&amp;#8217;s kind of like encapsulation in &lt;span class=&quot;caps&quot;&gt;OOP&lt;/span&gt;: elements within a &amp;lt;div&amp;gt; shouldn&amp;#8217;t be stylable from outside the &amp;lt;div&amp;gt;, unless they themselves are members of a class which applies style.&lt;/p&gt;
&lt;p&gt;Another reason for this rule is that, &lt;a href=&quot;http://code.google.com/speed/page-speed/docs/rendering.html#UseEfficientCSSSelectors&quot;&gt;according to Google&lt;/a&gt;, &amp;#8220;inefficient&amp;#8221; location-based selectors are rendered more slowly by web browsers. Try Google&amp;#8217;s &lt;a href=&quot;http://code.google.com/speed/page-speed&quot;&gt;PageSpeed&lt;/a&gt; plugin for Firebug for more information and to see how your selectors rate.&lt;/p&gt;
&lt;h2&gt;The Problem&lt;/h2&gt;
&lt;p&gt;While I agree with most of Nicole Miller&amp;#8217;s advice, and use an object-oriented approach 80% of the time, I&amp;#8217;m a little hesitant about killing &lt;em&gt;all&lt;/em&gt; of my location-dependent selectors. Here&amp;#8217;s why: In the simple example above, the location-independent approach adds 26 bytes to the size of the &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;. Certainly 26 bytes is nothing to worry about, but what happens on an actual web page where you might need to add &lt;code&gt;class=&quot;...&quot;&lt;/code&gt; attributes to 50, 100, or 500 tags? Could the size increase become significant?&lt;/p&gt;
&lt;p&gt;I asked Nicole about this earlier today at the &lt;a href=&quot;http://www.web2expo.com/webexny2009&quot;&gt;Web 2.0 Expo&lt;/a&gt; and she cited real companies that have significantly reduced their &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; payload (eg: from 60 to 15 KB) by switching to her &lt;a href=&quot;http://github.com/stubbornella/oocss&quot;&gt;&lt;span class=&quot;caps&quot;&gt;OOCSS&lt;/span&gt;&lt;/a&gt; library. However, I question whether a one-time savings of 45 KB (assuming browsers properly cache your stylesheet) justifies an increase of perhaps 20 KB on every page of your site. (With caching configured correctly, a browser will load your stylesheet once, but if a user views 20 pages of a site they will load 20 &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; files, all of which will have grown.)&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s  say the average &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; class attribute (eg: &lt;code&gt;class=&quot;product&quot;&lt;/code&gt;) is 16 bytes long (a conservative figure, I think). Given a web page which lists 40 products in a table, the &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; with location-dependent will apply style to &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;table&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;products&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;td&amp;gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;...&amp;quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;td&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;...&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Product Name&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;td&amp;gt;&lt;/span&gt;Description&lt;span class=&quot;nt&quot;&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;td&amp;gt;&amp;lt;span&amp;gt;&lt;/span&gt;$9.99&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- 39 more rows like this --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If we get rid of location-dependent &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; selectors we need to do something like this instead:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;td&amp;gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;thumbnail&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;...&amp;quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;td&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;product-name&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;...&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Product Name&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;td&amp;gt;&lt;/span&gt;Description&lt;span class=&quot;nt&quot;&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;td&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;price&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;$9.99&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- 39 more rows like this --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;We remove one class attribute from the &amp;lt;table&amp;gt; tag, but we add 3 to each of the 40 rows:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;(3 * 40) * 16 bytes = 1920 bytes&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;We just added almost 2 KB to each product listing page, and will add more if multiple class names are used and more elements need class attributes. Whether the increase is meaningful is outside the scope of this article (watch &lt;a href=&quot;http://blip.tv/file/2279751&quot;&gt;this presentation by Microsoft and Google&lt;/a&gt;) and, to some extent, depends on your application. My point is only that there can be an increase in file size and a corresponding decrease in page performance when you use this technique. The magnitude of the change depends on your particular &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; and how your site is used. If you only expect people to view one page per visit then you probably only care about overall (&lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; + &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt;) file size, but if users will be viewing many pages, &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; file size may be the more important number. Saving 20 KB in your stylesheet may not make sense if it increases the size of each page by 10 KB.&lt;/p&gt;
&lt;p&gt;To be clear: I&amp;#8217;m not suggesting that you stop using OO design in stylesheets, or that you start using location-dependent selectors everywhere. Most sites I&amp;#8217;ve seen could benefit significantly from better &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; logic, and &lt;span class=&quot;caps&quot;&gt;OOP&lt;/span&gt; has many valuable lessons to teach. I&amp;#8217;m only saying this: be aware of the side effects of all design patterns, avoid becoming married to any one approach, and choose the right strategy for each problem. There are cases in which C is a more appropriate language than an object-oriented alternative. And there are cases&amp;#8212;and this is Nicole Miller&amp;#8217;s pitch&amp;#8212;where the increased file size will be negligible compared with the efficiency and maintainability gained by avoiding naive nested selectors. Be sure to know which case you&amp;#8217;re dealing with.&lt;/p&gt;</description>
    </item>

    <item>
      <title>Growing Up With Computers</title>
      <author>Alex Reisner</author>
      <pubDate>2009-11-06T00:00:00-08:00</pubDate>
      <link>http://code.alexreisner.com/articles/growing-up.html</link>
      <guid>http://code.alexreisner.com/articles/growing-up.html</guid>
      <description>&lt;p&gt;My first computer was a &lt;a href=&quot;http://en.wikipedia.org/wiki/Commodore_64&quot;&gt;Commodore 64C&lt;/a&gt; which I received from my parents for my 8th birthday in 1988. It had cartridges with exciting games like Frogger and Zaxxon, and we added an external 5.25&amp;quot; floppy disk drive so I could play boring games like Odell Lake, which I loved. It had a graphical user interface called Geos which required you to hook up a mouse, and was pointless.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/content/odell_lake.png&quot; class=&quot;right&quot; title=&quot;Odell Lake&quot; alt=&quot;Odell Lake&quot; /&gt;&lt;/p&gt;
&lt;p&gt;At some point I had a big book of &lt;span class=&quot;caps&quot;&gt;BASIC&lt;/span&gt; computer programs that I began typing into the computer. These programs were hundreds of lines long and never worked because I would make a lot of typing errors and never be able to find them. I understood variables, conditionals, and &lt;span class=&quot;caps&quot;&gt;GOTO&lt;/span&gt;, but not much else. Give me a break, I was eight.&lt;/p&gt;
&lt;p&gt;My friend Nick had a Tandy computer in his basement that ran MS-&lt;span class=&quot;caps&quot;&gt;DOS&lt;/span&gt;, which I thought was boring. Not boring in a good way like Odell Lake, just boring. The games only had 3 colors and there were a lot of directories on the system where you could get lost. Basically, there was too much typing, it took too long to boot up, and it didn&amp;#8217;t do much. Of course, we spent hours playing with it, mostly getting it to turn on, if I remember correctly.&lt;/p&gt;
&lt;p&gt;Later, my friend James had a 386 25 MHz PC with an enormous red on/off switch on the side. One day James came to school with a computer software catalog and pointed to a game called Wing Commander, which he said he was getting. Pretty soon I was at his house every day after school. He also had a Roland MT-32 which, in retrospect, was an expensive device probably used by his mom for something productive she actually did with her time. All we knew was when you turned that thing on, you&amp;#8217;d better cover your ears. Whenever a game started the volume level shot right up to 100. I have no idea why this happened, but it scared the hell out of me every time. To this day the sight of an MT-32 makes me jump backwards 5 feet.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/content/stunts.png&quot; class=&quot;right&quot; title=&quot;Stunts&quot; alt=&quot;Stunts&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Anyway, Wing Commander was amazing. There was also a game called Stunts, where you raced cars against computer-controlled drivers with names like Bernie Rubber and Skid Vicious. Skid was supposed to be the toughest, but they were all bad. It wasn&amp;#8217;t so much about winning in Stunts, it was more about crashing.&lt;/p&gt;
&lt;p&gt;My &lt;a href=&quot;http://lsetc.wordpress.com/&quot;&gt;younger brother&lt;/a&gt; had a 286 16 MHz computer that I was never too impressed by. One day James suggested installing Stunts on it. &amp;#8220;Install&amp;#8221; was still a new word to me: &amp;#8220;you mean transfer it from the disks so we can play it?&amp;#8221; That was the end of me not being impressed by my brother&amp;#8217;s computer. I finally started to grasp the power of PCs.&lt;/p&gt;
&lt;p&gt;In 1992 my dad and I read a lot of catalogs and eventually he bought us a brand new 486 33 MHz from Gateway 2000 (I think it was around $2400). It was a giant white tower with a 120 MB hard drive. It also took about two years for them to make it and send it to us. When it finally arrived, we all gathered in the den to set it up. We unpacked the boxes, hooked up the cables, and pressed the big round power button. It booted up. It worked! It ran Windows 3.1 which had Solitaire, the File Manager, and the &lt;span class=&quot;caps&quot;&gt;PIF&lt;/span&gt; editor.&lt;/p&gt;
&lt;p&gt;This computer was fast. Even James was impressed. But the extreme speed was sometimes a problem. For example, I tried to install Wing Commander but everything moved too fast, like a black and white film with people jittering all over the place. That wasn&amp;#8217;t good, but soon James got Wing Commander II and I copied it onto about 20 disks and somehow got it to work. This was the beginning of my floppy disk collection: hundreds of disks, all carefully labeled and color-coded, in drawers, alphabetically, beautiful.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/content/ms_dos.png&quot; class=&quot;left&quot; title=&quot;MS-DOS&quot; alt=&quot;MS-DOS&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I remember my horror in 1994 at learning that when Windows 95 came out, the computer would just boot right into it, skipping &lt;span class=&quot;caps&quot;&gt;DOS&lt;/span&gt; entirely. &amp;#8220;You&amp;#8217;re going to lose control of the computer,&amp;#8221; I thought. Of course, we did. That was the beginning of the end.&lt;/p&gt;
&lt;p&gt;Now computers aren&amp;#8217;t what they used to be. They&amp;#8217;re mostly a way to access the Internet. You don&amp;#8217;t spend much time putting disks into them (I&amp;#8217;m writing this on a MacBook Air which doesn&amp;#8217;t even have a disk drive), or installing software, or getting them to work. You can, of course, but basically they&amp;#8217;re just tools for doing other things.&lt;/p&gt;
&lt;p&gt;I don&amp;#8217;t get excited when my computer boots up anymore&amp;#8212;I get angry when it doesn&amp;#8217;t. As if it owes me something. Today&amp;#8217;s horseless carriage becomes yesterday&amp;#8217;s jalopy when you need it to get to work. I miss the era of The Marvelous PC to some extent, but I&amp;#8217;m enjoying The Marvelous Internet right now.&lt;/p&gt;</description>
    </item>

    <item>
      <title>Brief Timeline of the Internet</title>
      <author>Alex Reisner</author>
      <pubDate>2009-10-30T00:00:00-07:00</pubDate>
      <link>http://code.alexreisner.com/articles/internet-timeline.html</link>
      <guid>http://code.alexreisner.com/articles/internet-timeline.html</guid>
      <description>&lt;p&gt;Yesterday was the 40th birthday of the Internet. I don&amp;#8217;t know anyone who celebrated, but I&amp;#8217;ve been enjoying imagining what those early days were like and thought I&amp;#8217;d write a very brief history of what I think are the most exciting developments.&lt;/p&gt;
&lt;h2&gt;1945: The Idea of the World Wide Web&lt;/h2&gt;
&lt;p&gt;Engineer Vannevar Bush published an article in Atlantic Monthly entitled &lt;em&gt;As We May Think&lt;/em&gt; which described a theoretical device he called the Memex. The key feature of the Memex was its ability to link arbitrary microfilm frames to form a trail of related information. This is a precursor to various hypertext systems invented during the 1960s, and ultimately &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; and the World Wide Web.&lt;/p&gt;
&lt;h2&gt;1965: Email&lt;/h2&gt;
&lt;p&gt;Despite what you might expect, email pre-dates the Internet. Email began as a way for mainframe users to communicate with each other from their dial-up terminals. All emails were sent directly from one user&amp;#8217;s computer to another (as opposed to today, where there are many mail servers in between). In 1971, what we would think of as the first &amp;#8220;Internet email&amp;#8221; was sent over &lt;span class=&quot;caps&quot;&gt;ARPANET&lt;/span&gt;.&lt;/p&gt;
&lt;h2&gt;1969 October 29: &lt;span class=&quot;caps&quot;&gt;ARPANET&lt;/span&gt; Is Born&lt;/h2&gt;
&lt;p&gt;At 22:30 two computers were connected (UC Los Angeles and Stanford Research Institute) over the world&amp;#8217;s first packet-switched network, which would become known as &lt;span class=&quot;caps&quot;&gt;ARPANET&lt;/span&gt; (Advanced Research Projects Agency Network). This is probably the closest thing to the moment the Internet was born.&lt;/p&gt;
&lt;p&gt;Before &lt;span class=&quot;caps&quot;&gt;ARPANET&lt;/span&gt;, networks were circuit-switched, meaning each transmission prevented anyone else from using the line until it was completed. Packet switching broke transmissions up into pieces for more effective sharing of network resources.&lt;/p&gt;
&lt;h2&gt;1973-82: Evolution of Inter-Networking&lt;/h2&gt;
&lt;p&gt;Computers on &lt;span class=&quot;caps&quot;&gt;ARPANET&lt;/span&gt; could communicate with each other, but they couldn&amp;#8217;t yet communicate with computers on other networks because they all used different protocols. During the period of 1973-82, following the lead of the &lt;span class=&quot;caps&quot;&gt;CYCLADES&lt;/span&gt; network in France, various protocols were developed for communication across different networks. Transmission Control Protocol (&lt;span class=&quot;caps&quot;&gt;TCP&lt;/span&gt;) was invented in 1973, the International Standards Organization (&lt;span class=&quot;caps&quot;&gt;ISO&lt;/span&gt;) proposed the Open Systems Interconnection (&lt;span class=&quot;caps&quot;&gt;OSI&lt;/span&gt;) standard in 1977, and on January 1, 1983, &lt;span class=&quot;caps&quot;&gt;ARPANET&lt;/span&gt; was successfully migrated to the &lt;span class=&quot;caps&quot;&gt;TCP&lt;/span&gt;/IP protocol, which has been the standard ever since.&lt;/p&gt;
&lt;h2&gt;1990 December 25: The World Wide Web Is Born&lt;/h2&gt;
&lt;p&gt;Tim Berners-Lee proposed the World Wide Web in March of 1989 and almost two years later, with Robert Cailiau, executed the first communication over the Hypertext Transfer Protocol (&lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt;). This is the birth of the World Wide Web, the &amp;#8220;killer app&amp;#8221; which is probably what most people picture when they think of the Internet.&lt;/p&gt;
&lt;p&gt;Berners-Lee&amp;#8217;s web browser, called WorldWideWeb, was also an &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; editor. It was first officially released on February 26, 1991 and was soon renamed Nexus to avoid confusion with the actual World Wide Web. His server software became known as &lt;span class=&quot;caps&quot;&gt;CERN&lt;/span&gt; httpd. The W3C retains an archived copy of &lt;a href=&quot;http://www.w3.org/History/19921103-hypertext/hypertext/WWW/TheProject.html&quot;&gt;the first web site&lt;/a&gt; (originally at http://info.cern.ch/). The first official announcement of the World Wide Web was on August 6, 1991 when Berners-Lee posted a description of his project to the alt.hypertext newsgroup.&lt;/p&gt;
&lt;h2&gt;1993: The Accessible Web&lt;/h2&gt;
&lt;p&gt;The WorldWideWeb/Nexus browser ran on the NeXTSTEP operating system. Ever heard of it? I hadn&amp;#8217;t until I started researching this article. There were other browsers too, but &lt;span class=&quot;caps&quot;&gt;NCSA&lt;/span&gt; Mosaic, developed principally by Marc Andreesen, was the first cross-platform browser to provide a usable interface and hence was the first to hit it off with the general public. In 1994 Mosaic became Netscape Navigator, in 1995 Internet Explorer was released (packaged with Microsoft Plus!), and then the browser wars began&amp;#8230;&lt;/p&gt;
&lt;p&gt;I remember Netscape 2.0 so well&amp;#8212;the big buttons, the gray pages, the shooting stars in the logo. Now I carry a little box in my pocket with a touch screen that&amp;#8217;s faster than a desktop computer with a 14.4 kbps modem was just over a decade ago. The pace of evolution is only increasing and it&amp;#8217;s mindboggling to imagine where we could be in another ten years.&lt;/p&gt;</description>
    </item>

    <item>
      <title>The Influence of Vi</title>
      <author>Alex Reisner</author>
      <pubDate>2009-10-26T00:00:00-07:00</pubDate>
      <link>http://code.alexreisner.com/articles/vi.html</link>
      <guid>http://code.alexreisner.com/articles/vi.html</guid>
      <description>&lt;p&gt;About a year ago I switched to Google for hosting my email. I never thought I&amp;#8217;d be able to use an email reader that didn&amp;#8217;t run locally and store messages in mbox format, but Gmail&amp;#8217;s responsive interface and brilliant labeling system (folders were never really quite right) convinced me otherwise.&lt;/p&gt;
&lt;p&gt;Another deciding factor was Gmail&amp;#8217;s &lt;em&gt;Keyboard Shortcuts&lt;/em&gt; (if you haven&amp;#8217;t enabled them I highly recommend that you do, then type &amp;#8216;?&amp;#8217;), which made the responsive interface even quicker. But it wasn&amp;#8217;t until recently that I suddenly realized part of why the keyboard shortcuts seemed so natural: some of them are taken from Vi! Specifically:&lt;/p&gt;
&lt;p&gt;j = down&lt;br /&gt;
k = up&lt;br /&gt;
/ = search&lt;/p&gt;
&lt;p&gt;This made me wonder where else Vi&amp;#8217;s influence could be found, and I thought I&amp;#8217;d share the following links:&lt;/p&gt;
&lt;h2&gt;Vimperator&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://www.vimperator.org/trac/wiki/Vimperator&quot;&gt;vimperator.org/trac/wiki/Vimperator&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A Firefox plugin which adds vi-like keyboard commands, plus a &lt;span class=&quot;caps&quot;&gt;DOM&lt;/span&gt;/JavaScript object explorer, and an interactive JavaScript shell. Very disorienting yet somehow familiar. Worth at least 10 minutes of mayhem.&lt;/p&gt;
&lt;h2&gt;Vi in JavaScript&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://gpl.internetconnection.net/vi/&quot;&gt;gpl.internetconnection.net/vi&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Funny at first, then amazing as you realize how complete it is. Not 100% complete, but very usable.&lt;/p&gt;
&lt;h2&gt;Intro to Modal Editing&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://www.viemu.com/a-why-vi-vim.html&quot;&gt;viemu.com/a-why-vi-vim.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Classic piece on the benefits of Vi. Read this so you&amp;#8217;re prepared to smoothly field questions like &amp;#8220;Why the heck would I want to learn all those obscure commands? Aren&amp;#8217;t you crazy?&amp;#8221;&lt;/p&gt;</description>
    </item>

    <item>
      <title>Google Custom Search</title>
      <author>Alex Reisner</author>
      <pubDate>2009-10-14T00:00:00-07:00</pubDate>
      <link>http://code.alexreisner.com/code/google-custom-search.html</link>
      <guid>http://code.alexreisner.com/code/google-custom-search.html</guid>
      <description>&lt;p class=&quot;date&quot;&gt;Updated 14 Oct 2009&lt;/p&gt;
&lt;p&gt;If you want a Google-like search engine for your web site, why not use Google? For $100/yr (more if you have over 1,000 pages) you can get &lt;a href=&quot;http://www.google.com/cse&quot;&gt;access to Google search results&lt;/a&gt; for your site in &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; format. The google_custom_search gem helps you access this web service and publish the results on your site however you like (all covered under Google&amp;#8217;s acceptable use policy).&lt;/p&gt;
&lt;p&gt;To perform a search:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;results&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;GoogleCustomSearch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Hank Aaron&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;results&lt;/code&gt; variable is now a &lt;code&gt;GoogleCustomSearch::ResultSet&lt;/code&gt; object:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;total&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;# number of results (integer)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pages&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;# array of result objects&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;suggestion&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;# suggested search term, if any&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Iterate through the results:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pages&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;# result title&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;             &lt;span class=&quot;c1&quot;&gt;# result URL&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;# excerpt, with terms highlighted&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;For source code, installation instructions, and up-to-date &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; documentation please see the &lt;a href=&quot;http://github.com/alexreisner/google_custom_search&quot;&gt;project page at GitHub&lt;/a&gt;.&lt;/p&gt;</description>
    </item>

    <item>
      <title>Simulate Has Many Through HABTM</title>
      <author>Alex Reisner</author>
      <pubDate>2009-10-07T00:00:00-07:00</pubDate>
      <link>http://code.alexreisner.com/articles/has-many-through-habtm.html</link>
      <guid>http://code.alexreisner.com/articles/has-many-through-habtm.html</guid>
      <description>&lt;p&gt;If you work much with Rails and ActiveRecord you may have noticed that a certain commonly-used association is not allowed. I will show you how to simulate it. Let&amp;#8217;s say you have the following models and relationships:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Article&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;has_and_belongs_to_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:categories&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Category&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;belongs_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:section&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Section&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:categories&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now you want to find all the articles in a section, so you try the obvious solution, adding the following to &lt;code&gt;Section&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:articles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:though&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:categories&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This relationship seems reasonable enough, but an exception will be raised:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;erb&quot;&gt;&lt;span class=&quot;x&quot;&gt;ActiveRecord::HasManyThroughSourceAssociationMacroError:&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;Invalid source reflection macro :has_and_belongs_to_many&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;for has_many :articles, :through =&amp;gt; :categories.&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;Use :source to specify the source reflection.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Don&amp;#8217;t waste time trying to find the right &lt;code&gt;:source&lt;/code&gt;. The &lt;code&gt;has_many&lt;/code&gt; association through a &lt;code&gt;has_and_belongs_to_many&lt;/code&gt; is simply not allowed in Rails 2.3.4, but you can get the behavior you want by defining a &lt;code&gt;Section#articles&lt;/code&gt; method that returns a nice &lt;code&gt;ActiveRecord::NamedScope&lt;/code&gt; proxy. Just add this named scope to your &lt;code&gt;Article&lt;/code&gt; class:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;named_scope&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:in_section&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;lambda&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;section&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;:joins&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:categories&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;:conditions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:categories&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;section&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;category_ids&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}},&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;:select&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;DISTINCT `articles`.*&amp;quot;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# kill duplicates&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;and add this method to your &lt;code&gt;Section&lt;/code&gt; class:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;articles&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Article&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;in_section&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now, since this is a pure named scope, you can do things like &lt;code&gt;section.articles.published.recent&lt;/code&gt;. This technique also works in situations where you&amp;#8217;re stopped by a polymorphic association. If you find yourself using this technique a lot you might want to abstract it to a plugin. Open source, please!&lt;/p&gt;</description>
    </item>

    <item>
      <title>How to Cause Useful Accidents</title>
      <author>Alex Reisner</author>
      <pubDate>2009-09-22T00:00:00-07:00</pubDate>
      <link>http://code.alexreisner.com/articles/how-to-cause-useful-accidents.html</link>
      <guid>http://code.alexreisner.com/articles/how-to-cause-useful-accidents.html</guid>
      <description>&lt;p&gt;If you do any visual design work you&amp;#8217;ve probably discovered that many of the best results happen by accident. I start designing web pages in Adobe Illustrator or Photoshop but I usually create functional &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; and &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; mockups of my designs pretty quickly, one of the the main reasons being that it facilitates semi-controlled mutations. That is, to &lt;em&gt;cause an &amp;#8220;accident&amp;#8221;&lt;/em&gt; I apply various unrelated stylesheets from other sites, just to see what happens. A polished final design never results, but good ideas often do, and rigid thinking is often unclogged.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s difficult to do this in Photoshop or Illustrator, or any of the common visual layout/design tools I can think of. These programs usually apply changes to groups of objects or type, and even if you have you&amp;#8217;re using character or paragraph styles there&amp;#8217;s no easy way to apply &lt;em&gt;random&lt;/em&gt; changes, which is important because if you&amp;#8217;re &lt;em&gt;thinking&lt;/em&gt; about the mutations you will not cause an &lt;em&gt;accident&lt;/em&gt;. Even taking stylesheets from your favorite (or least favorite) sites is somewhat premeditated, but it&amp;#8217;s worked pretty well for me, provided I don&amp;#8217;t use the same stylesheets over and over again on different designs.&lt;/p&gt;
&lt;p&gt;Now, would someone please create a web site that generates random &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; and maybe even applies it to a page at a given &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt;? I&amp;#8217;d like that very much.&lt;/p&gt;
&lt;p&gt;PS: The folks at 37signals also &lt;a href=&quot;http://37signals.com/svn/posts/1061-why-we-skip-photoshop&quot;&gt;recommend working in &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;/&lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; early&lt;/a&gt;, and they have some more good reasons to do it (ease of sharing/collaboration, experiencing interactivity, etc).&lt;/p&gt;</description>
    </item>

    <item>
      <title>Build Web Applications In Static HTML</title>
      <author>Alex Reisner</author>
      <pubDate>2009-09-16T00:00:00-07:00</pubDate>
      <link>http://code.alexreisner.com/articles/build-web-applications-in-static-html.html</link>
      <guid>http://code.alexreisner.com/articles/build-web-applications-in-static-html.html</guid>
      <description>&lt;p&gt;If you enjoy writing small web applications in web microframeworks like Sinatra or web.py, consider this: no matter how quick and easy it is to write and deploy, your app will never be as quick and easy as no app at all.&lt;/p&gt;
&lt;p&gt;Every feature you implement means more code to maintain, and frequently you use the same feature for many web sites, resulting in a lot of duplicated code. You can package a feature as a plugin or gem for easy propagation to all of your sites, but upgrades may still require adjustments to database structure or application code, and you still have to re-install the plugins or update your gems manually which can be very time consuming if you have 20 or 40 sites sharing the code.&lt;/p&gt;
&lt;p&gt;What if you could forget about writing web applications entirely and just deploy some static &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; files, like in 1995 before you learned Perl?&lt;/p&gt;
&lt;p&gt;This web site you are reading now is deployed as a collection of static &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; files (thanks to &lt;a href=&quot;http://github.com/mojombo/jekyll&quot;&gt;Jekyll&lt;/a&gt;), but you can read and write comments because I&amp;#8217;m using a service called &lt;a href=&quot;http://disqus.com/&quot;&gt;Disqus&lt;/a&gt; to provide them via JavaScript. I&amp;#8217;ve added an application-like feature to a site without writing a single line of server-side code. I can deploy by uploading some files and telling Apache where they are. How far can we take this? Well&amp;#8230;&lt;/p&gt;
&lt;h2&gt;Beyond Comments&lt;/h2&gt;
&lt;p&gt;Programmers have been using services like &lt;a href=&quot;http://pastie.org&quot;&gt;Pastie&lt;/a&gt; and &lt;a href=&quot;http://gist.github.com&quot;&gt;Gist&lt;/a&gt; to add syntax highlighting to their sites which, like this one, could be implemented with static &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;. There are also services which offer entire customer feedback and discussion systems like &lt;a href=&quot;http://uservoice.com&quot;&gt;Uservoice&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In addition to pulling data into a site, we can push data out for processing and possibly for re-display at a later time. You&amp;#8217;ve likely heard of &lt;a href=&quot;http://www.google.com/analytics&quot;&gt;Google Analytics&lt;/a&gt;, which collects and analyzes web page usage data in this fashion.&lt;/p&gt;
&lt;p&gt;These are third-party solutions so the providers own your data. What I&amp;#8217;d like to see, and what I suspect we will start to see soon, is open source versions of this type of service which would give us back our data, as well as control of the interface. &lt;a href=&quot;http://rifgraf.heroku.com/&quot;&gt;Rifgraf&lt;/a&gt; is one such open source web service which will collect and graph whatever numeric data you send it (like a simple, generalized Analytics).&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;re familiar with Rails you should probably consider ActiveResource as a foundation when designing your own web service. It may not be your ultimate answer, but it may get you up and running quickly, and it integrates very easily with your Rails apps and standard &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt;-eating JavaScript libraries. I&amp;#8217;m also somewhat optimistic about Apache&amp;#8217;s &lt;a href=&quot;http://couchdb.apache.org&quot;&gt;CouchDB&lt;/a&gt; as an engine for these services. Its native interface is &lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt;, its query language is JavaScript, and it can serve &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;. It&amp;#8217;s currently at version 0.9.1 and probably not stable enough for serious production use, but I believe it will be soon.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.pragprog.com/titles/kpiod/interface-oriented-design&quot;&gt;Interface-Oriented Design&lt;/a&gt; is a book published by &lt;a href=&quot;http://www.pragprog.com&quot;&gt;Pragmatic Programmers&lt;/a&gt; which discusses many of the problems involved in designing such services. I recommend it to anyone conteplating getting involved. It&amp;#8217;s an oldie but a goodie (still relevant, and will remain so for a while since it&amp;#8217;s about design principles rather than specific technologies).&lt;/p&gt;
&lt;h2&gt;The Big Caveat&lt;/h2&gt;
&lt;p&gt;Sorry to say, there is a major problem with all of this, which is the limiting factor in how far we can practically take this idea of static &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; web applications: Google. As of now, Google does not index content added to a page by JavaScript. With Disqus comments this isn&amp;#8217;t ideal, but it isn&amp;#8217;t terrible either; at least your posted content is searchable. It&amp;#8217;s not too bad in the case of images or code snippets either, but it means that you don&amp;#8217;t really want any vital content to be provided by a JavaScript service.&lt;/p&gt;
&lt;p&gt;However, I believe&amp;#8212;and this is very unofficial&amp;#8212;that Google will eventually index this type of content. I have seen evidence of their spiders on my own sites poking at &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt;-only URLs. Repeat: I have no evidence that this means anything, I am simply guessing. If I were Google, I&amp;#8217;d be working on it.&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;re still with me on this, let me be more specific. I believe that Google will index content added &lt;em&gt;automatically&lt;/em&gt; after a page is loaded. This includes all of the technologies I&amp;#8217;ve discussed so far which simply fetch content as they are rendered by the browser. I am not as hopeful about content that is added to the page after a button or link is clicked (such as with &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt; pagination).&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I encourage you to consider the idea that functionality, and even data, can live outside of your web appli&amp;#8230;I mean &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; files. We&amp;#8217;re accustomed to avoiding code duplication within a project, but what about code duplication within our &lt;em&gt;portfolio&lt;/em&gt;? By considering all of our sites as a unit I hope we can lessen the pains of maintenance and prevent long-running sites from turning into un-upgradeable relics that we &amp;#8220;never want to look at again.&amp;#8221;&lt;/p&gt;
&lt;p&gt;If planned carefully, I think we can use this kind of distributed application design as a way to &lt;em&gt;simplify&lt;/em&gt; our sites, even if we don&amp;#8217;t go all the way back to static &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;.&lt;/p&gt;</description>
    </item>

    <item>
      <title>Informant</title>
      <author>Alex Reisner</author>
      <pubDate>2009-07-26T00:00:00-07:00</pubDate>
      <link>http://code.alexreisner.com/code/informant.html</link>
      <guid>http://code.alexreisner.com/code/informant.html</guid>
      <description>&lt;p class=&quot;date&quot;&gt;Updated 9 Oct 2009&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://github.com/alexreisner/informant&quot;&gt;Informant&lt;/a&gt; is a full-featured form builder for Ruby on Rails which promotes a simple syntax that keeps your views clean. Everything about a field (label, description, error display, etc) is encapsulated in a single method call. Three form layouts are included (Standard, Table, and Simple) and custom layouts can be created easily (write a new class, inherit, and overwrite whatever field templates you want).&lt;/p&gt;
&lt;p&gt;All field methods accept an options hash like the standard Rails FormBuilder methods, but with some extra features available. The simplest field takes just an object attribute name:&lt;/p&gt;
&lt;div id=&quot;car_name_field&quot; class=&quot;informant_field&quot;&gt;
  &lt;label for=&quot;car_name&quot;&gt;Name&lt;/label&gt;
&lt;input type=&quot;text&quot; id=&quot;car_name&quot; name=&quot;car[name]&quot; value=&quot;&quot; /&gt;
&lt;/div&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;erb&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text_field&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The label is inferred from the field name but can be specified manually with the &lt;code&gt;:label&lt;/code&gt; option. The second argument to a select field should be an array of options in the same format as used for the default Rails FormBuilder.&lt;/p&gt;
&lt;div id=&quot;car_manufacturer_field&quot; class=&quot;informant_field&quot;&gt;
  &lt;label for=&quot;car_manufacturer&quot;&gt;Brand &lt;span class=&quot;red&quot;&gt;*&lt;/span&gt;&lt;/label&gt;
&lt;select id=&quot;car_manufacturer&quot; name=&quot;car[manufacturer]&quot;&gt;
    &lt;option value=&quot;&quot;&gt;&lt;/option&gt;
    &lt;option value=&quot;Ascari&quot;&gt;Ascari&lt;/option&gt;
    &lt;option value=&quot;Ferrari&quot;&gt;Ferrari&lt;/option&gt;
    &lt;option value=&quot;Lamborghini&quot;&gt;Lamborghini&lt;/option&gt;
    &lt;option value=&quot;Pagani&quot;&gt;Pagani&lt;/option&gt;
&lt;/select&gt;
  &lt;p class=&quot;description&quot;&gt;Please choose an Italian manufacturer.&lt;/p&gt;
&lt;/div&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;erb&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;select&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:manufacturer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Manufacturer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;:label&lt;/span&gt;         &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Brand&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;:include_blank&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;:required&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;:description&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Please choose an Italian manufacturer.&amp;quot;&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In addition to the standard Rails FormBuilder options, you can also specify a label, a required marker, some descriptive text, decoration (such as a spinner for use with &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt; calls), and more. There are also some custom field types, such as &lt;code&gt;radio_buttons&lt;/code&gt; (for a set of radio buttons) and &lt;code&gt;habtm_check_boxes&lt;/code&gt;:&lt;/p&gt;
&lt;div id=&quot;car_features_field&quot; class=&quot;informant_field&quot;&gt;
  &lt;label for=&quot;car_feature_ids&quot; style=&quot;font-weight:bold&quot;&gt;Features&lt;/label&gt;&lt;p&gt;&lt;br /&gt;
  &lt;input type=&quot;checkbox&quot; id=&quot;car_feature_ids_1&quot; name=&quot;car[feature_ids][]&quot; value=&quot;1&quot; /&gt; &lt;label for=&quot;car_feature_ids_1&quot;&gt;power windows&lt;/label&gt;&lt;br /&gt;
  &lt;input type=&quot;checkbox&quot; id=&quot;car_feature_ids_2&quot; name=&quot;car[feature_ids][]&quot; value=&quot;2&quot; /&gt; &lt;label for=&quot;car_feature_ids_2&quot;&gt;gas guzzler tax&lt;/label&gt;&lt;br /&gt;
  &lt;input type=&quot;checkbox&quot; id=&quot;car_feature_ids_3&quot; name=&quot;car[feature_ids][]&quot; value=&quot;3&quot; /&gt; &lt;label for=&quot;car_feature_ids_3&quot;&gt;free cologne&lt;/label&gt;&lt;br /&gt;
  &lt;input type=&quot;checkbox&quot; id=&quot;car_feature_ids_4&quot; name=&quot;car[feature_ids][]&quot; value=&quot;4&quot; /&gt; &lt;label for=&quot;car_feature_ids_4&quot;&gt;full-length mirror&lt;/label&gt;&lt;br /&gt;
  &lt;input type=&quot;checkbox&quot; id=&quot;car_feature_ids_5&quot; name=&quot;car[feature_ids][]&quot; value=&quot;5&quot; /&gt; &lt;label for=&quot;car_feature_ids_5&quot;&gt;midlife crisis&lt;/label&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;erb&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;habtm_check_boxes&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:feature_ids&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Feature&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Note that this method takes an array of choices just like a select field. It also handles the all-unchecked case so you don&amp;#8217;t have to deal with it in the controller (if you&amp;#8217;ve ever set up has_and_belongs_to_many checkboxes you&amp;#8217;re familiar with this problem).&lt;/p&gt;
&lt;p&gt;In short, Informant will make your form code shorter and more readable. For complete &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; documentation see the &lt;a href=&quot;http://github.com/alexreisner/informant&quot;&gt;Informant project at GitHub&lt;/a&gt;.&lt;/p&gt;</description>
    </item>

    <item>
      <title>Punting on Feedzirra Dependencies</title>
      <author>Alex Reisner</author>
      <pubDate>2009-06-30T00:00:00-07:00</pubDate>
      <link>http://code.alexreisner.com/articles/punt-on-feedzirra-dependencies.html</link>
      <guid>http://code.alexreisner.com/articles/punt-on-feedzirra-dependencies.html</guid>
      <description>&lt;p&gt;After watching Ryan Bates&amp;#8217; &lt;a href=&quot;http://railscasts.com/episodes/168-feed-parsing&quot;&gt;video on feed parsing&lt;/a&gt; I decided to give &lt;a href=&quot;http://github.com/pauldix/feedzirra&quot;&gt;Feedzirra&lt;/a&gt; a try. Though I did eventually get the Feedzirra gem working, rounding up and installing the dependencies was painful enough that I decided not to use it.&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;re having trouble installing Feedzirra I encourage you to evaluate whether you really need it. In one application I needed to parse and display a Twitter feed and did the following to accomplish most of what was covered in &lt;a href=&quot;http://railscasts.com/episodes/168-feed-parsing&quot;&gt;Railscast #168&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;1. Install libxml-ruby&lt;/h2&gt;
&lt;p&gt;The libxml-ruby parser is quite fast. If you&amp;#8217;re using &lt;span class=&quot;caps&quot;&gt;REXML&lt;/span&gt; or hpricot to parse &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; you should consider switching as the difference in speed is &lt;em&gt;significant&lt;/em&gt;. To install, add the following to &lt;tt&gt;config/environment.rb&lt;/tt&gt; in your Rails app:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;libxml-ruby&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:lib&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;xml&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;and then run:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;sudo rake gems:install
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;or if you wish to install manually:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;sudo gem install libxml-ruby
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The only dependency that might not be found in a standard *nix setup is the libxml development files, so you may need to install a package called &lt;code&gt;libxml2-dev&lt;/code&gt; (on Ubuntu) or &lt;code&gt;libxml-devel&lt;/code&gt; (on CentOS).&lt;/p&gt;
&lt;h2&gt;2. Create a Model For Your Feed&lt;/h2&gt;
&lt;p&gt;You need to create a model to store your feeds in the database, so use the Rails generator script:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;script/generate model Tweet &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  guid:string url:string body:text published_at:datetime
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;and then add this method to the skeleton ActiveRecord model:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;update_from_feed&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# fetch XML document&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;uri&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;URI&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;http://twitter.com/...&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Net&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;HTTP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uri&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uri&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uri&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;# quit if non-2xx HTTP response&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;2&amp;quot;&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;# parse and save&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;doc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;XML&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;doc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;/rss/channel/item&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;guid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find_first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;guid&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exists?&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:guid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;guid&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;create!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;:body&lt;/span&gt;         &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find_first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;description&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;:url&lt;/span&gt;          &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find_first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;link&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;:published_at&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find_first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;pubDate&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;:guid&lt;/span&gt;         &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;guid&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2&gt;3. Try it out&lt;/h2&gt;
&lt;p&gt;Make sure to run the migration to create the &lt;tt&gt;tweets&lt;/tt&gt; table:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;rake db:migrate
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;then start a console session:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;script/console
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;and fetch/parse/save your tweets:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;Tweet.count             &lt;span class=&quot;c&quot;&gt;# should return 0&lt;/span&gt;
Tweet.update_from_feed  &lt;span class=&quot;c&quot;&gt;# fetches tweets&lt;/span&gt;
Tweet.count             &lt;span class=&quot;c&quot;&gt;# should return n &amp;gt; 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Your &lt;tt&gt;tweets&lt;/tt&gt; table should now be populated with the latest data.&lt;/p&gt;
&lt;p&gt;Note that although libxml-ruby is fast, you should be aware of the payload you&amp;#8217;re receiving on each update and think about how often you can afford to fetch and parse a multi-megabyte feed.&lt;/p&gt;</description>
    </item>

    <item>
      <title>Form Builders in Rails</title>
      <author>Alex Reisner</author>
      <pubDate>2008-11-06T00:00:00-08:00</pubDate>
      <link>http://code.alexreisner.com/articles/form-builders-in-rails.html</link>
      <guid>http://code.alexreisner.com/articles/form-builders-in-rails.html</guid>
      <description>&lt;p&gt;&lt;em&gt;Update 26 July 2009: for some ready-made form builders that may suit your needs please see my &lt;a href=&quot;/code/informant.html&quot;&gt;Informant&lt;/a&gt; plugin.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;There is no question that metaprogramming techniques bring enormous power to Ruby on Rails, but in some places that power comes at the cost of code readability. One place in which a maze of hook methods and dynamically-defined methods can at first obscure the behavior of the code is in ActionView&amp;#8217;s FormBuilder. Because custom FormBuilders have been invaluable in my work I&amp;#8217;d like to give you a guided tour of the source code so you can understand it and be prepared to harness the power of custom FormBuilders in your applications. At the end I&amp;#8217;ll also offer some practical tips (feel free to &lt;a href=&quot;#tips&quot;&gt;skip to the bottom&lt;/a&gt; if you&amp;#8217;re in a rush).&lt;/p&gt;
&lt;h2&gt;A Tour of the Code&lt;/h2&gt;
&lt;p&gt;Reading the source code is a great way to learn how Rails works, and I recommend keeping the relevant files open in your text editor alongside this article, though it&amp;#8217;s not necessary. All the code I discuss is located in &lt;code&gt;actionpack/lib/action_view/helpers/form_helper.rb&lt;/code&gt;. I will provide schematic views of the source code where helpful (line numbers taken from Rails 2.1.2). You don&amp;#8217;t need to be a metaprogramming expert to read this article, but I do assume that you understand blocks, bindings, and the &lt;code&gt;yield&lt;/code&gt; statement.&lt;/p&gt;
&lt;h2&gt;A FormBuilder&amp;#8217;s Life&lt;/h2&gt;
&lt;p&gt;The first thing to understand is what a FormBuilder is, and really it&amp;#8217;s just a proxy for calling methods of the Form*Helper* module. What methods are those? They should look familiar to you:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# File: actionpack/lib/action_view/helpers/form_helper.rb&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Line: 75, in module ActionView::Helpers&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;FormHelper&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;form_for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;      &lt;span class=&quot;n&quot;&gt;record_or_name_or_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fields_for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;record_or_name_or_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;         &lt;span class=&quot;n&quot;&gt;object_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;text_field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;object_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;password_field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;object_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;hidden_field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;object_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;file_field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;object_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;text_area&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;object_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;check_box&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;object_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{},&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;radio_button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;object_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tag_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;These are probably some of the first Rails helper methods we all learn. All the field-generating methods (not the two field &lt;em&gt;group&lt;/em&gt; generators at the top) take an &lt;code&gt;object_name&lt;/code&gt; as the first parameter. When we are building a form for a single object (or &amp;#8220;model&amp;#8221;), this parameter is likely to be the same for every field, and the most obvious thing FormBuilder does for you is remember this parameter so you only have to specify it once, on initialization.&lt;/p&gt;
&lt;p&gt;How is a FormBuilder initialized? Most often it happens by a call to the &lt;code&gt;form_for&lt;/code&gt; method, for example, in a view:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;erb&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;form_for&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@car&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text_field&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;  ...&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;That little &lt;code&gt;f&lt;/code&gt; is the FormBuilder object which you use to conveniently generate form fields without specifying the &lt;code&gt;object_name&lt;/code&gt; every time. But what exactly happens in this call to &lt;code&gt;form_for&lt;/code&gt;? Basically, the code in between &lt;code&gt;&amp;lt;% form_for ... %&amp;gt;&lt;/code&gt; and the &lt;code&gt;&amp;lt;% end %&amp;gt;&lt;/code&gt; is a block (i.e., anonymous method) that takes one parameter (&lt;code&gt;f&lt;/code&gt;) and gets evaluated within &lt;code&gt;form_for&lt;/code&gt; but retains its binding. Let&amp;#8217;s follow our block into &lt;code&gt;form_for&lt;/code&gt; and see what happens to it:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# File: actionpack/lib/action_view/helpers/form_helper.rb&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Line: 232, in module ActionView::Helpers&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;form_for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;record_or_name_or_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;form_tag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{},&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;binding&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;fields_for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;object_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;lt;/form&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;binding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;We see the opening &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; &lt;code&gt;form&lt;/code&gt; tag rendered via the &lt;code&gt;concat&lt;/code&gt; method (note too the binding from our template being preserved). Our block (&lt;code&gt;proc&lt;/code&gt;) is then passed to &lt;code&gt;fields_for&lt;/code&gt; where the FormBuilder part of this operation occurs:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# File: actionpack/lib/action_view/helpers/form_helper.rb&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Line: 299, in module ActionView::Helpers::FormHelper&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fields_for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;record_or_name_or_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;builder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActionView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default_form_builder&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;object_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The first of these two lines is where the class of our FormBuilder is determined. First the options array is consulted to see if &lt;code&gt;:builder&lt;/code&gt; is specified, and if it&amp;#8217;s not, a default class is used. (Yes, you &lt;em&gt;can&lt;/em&gt; change this default to avoid specifying the &lt;code&gt;:builder&lt;/code&gt; option on every form&amp;#8212;see how in the tips &lt;a href=&quot;#tips&quot;&gt;below&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;The second line is the workhorse. It does two main things: it creates a new instance of the chosen FormBuilder class, and it yields to the block. In other words, it passes a new FormBuilder object to the anonymous method we wrote in our view (you know, the one that takes the &lt;code&gt;f&lt;/code&gt; parameter and prints some form fields).&lt;/p&gt;
&lt;h2&gt;Anatomy of a FormBuilder&lt;/h2&gt;
&lt;p&gt;Now that we know how and where a FormBuilder is created we can look at what it does (or, if we&amp;#8217;re writing a custom one, we&amp;#8217;re probably interested in what it &lt;em&gt;needs&lt;/em&gt; to do). Let&amp;#8217;s add some fields to our view:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;erb&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;form_for&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@car&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text_field&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:model&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text_field&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:cylinders&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;It should be clear now that these fields are rendered by invoking the &lt;code&gt;text_field&lt;/code&gt; method of our FormBuilder object. So a custom FormBuilder has to provide a &lt;code&gt;text_field&lt;/code&gt; method, and probably some others like &lt;code&gt;check_box&lt;/code&gt;, &lt;code&gt;select&lt;/code&gt;, and &lt;code&gt;submit&lt;/code&gt;. Here&amp;#8217;s what the default FormBuilder defines:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# File: actionpack/lib/action_view/helpers/form_helper.rb&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Line: 694, in module ActionView::Helpers&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FormBuilder&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;object_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fields_for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;record_or_name_or_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;            &lt;span class=&quot;nb&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;submit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;           &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Save changes&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;error_message_on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prepend_text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;error_messages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;text_field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;       &lt;span class=&quot;nb&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;password_field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;   &lt;span class=&quot;nb&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;hidden_field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;file_field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;       &lt;span class=&quot;nb&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;text_area&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;        &lt;span class=&quot;nb&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;check_box&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;        &lt;span class=&quot;nb&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{},&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;radio_button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tag_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;

  &lt;span class=&quot;kp&quot;&gt;private&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;objectify_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;As you would expect, the seven field-generating methods are the same ones defined in the FormHelper module (above), minus the initial &lt;code&gt;object_name&lt;/code&gt; parameter. (If you look at the actual source code you will see that five of these methods&amp;#8212;&lt;code&gt;text_field&lt;/code&gt;, &lt;code&gt;password_field&lt;/code&gt;, &lt;code&gt;hidden_field&lt;/code&gt;, &lt;code&gt;file_field&lt;/code&gt;, and &lt;code&gt;text_area&lt;/code&gt;&amp;#8212;are defined dynamically by &lt;code&gt;define_method&lt;/code&gt;.) We&amp;#8217;ll get to the details of these methods, but first let&amp;#8217;s look at perhaps the most useful part of the FormBuilder object: the instance variables it carries. Here&amp;#8217;s the default FormBuidler&amp;#8217;s &lt;code&gt;initialize&lt;/code&gt; method:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# File: actionpack/lib/action_view/helpers/form_helper.rb&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Line: 701, in class ActionView::Helpers::FormBuilder&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;object_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;vi&quot;&gt;@object_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@proc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 
    &lt;span class=&quot;n&quot;&gt;object_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;proc&lt;/span&gt;
  &lt;span class=&quot;vi&quot;&gt;@default_options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@options&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@options&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The FormBuilder stores each of its five parameters and stores them. They are:&lt;/p&gt;
&lt;dl&gt;
  &lt;dt&gt;@object_name&lt;/dt&gt;
  &lt;dd&gt;This is the old, familiar &lt;code&gt;object_name&lt;/code&gt; you used to have to pass to every field generator before you used FormBuilders.&lt;/dd&gt;
  &lt;dt&gt;@object&lt;/dt&gt;
  &lt;dd&gt;This is the object you are building a form for (in our example it&amp;#8217;s the first argument to &lt;code&gt;form_for&lt;/code&gt;).&lt;/dd&gt;
  &lt;dt&gt;@options&lt;/dt&gt;
  &lt;dd&gt;The options passed to &lt;code&gt;form_for&lt;/code&gt;, more or less.&lt;/dd&gt;
  &lt;dt&gt;@proc&lt;/dt&gt;
  &lt;dd&gt;The block provided to &lt;code&gt;form_for&lt;/code&gt; (remember him?).&lt;/dd&gt;
  &lt;dt&gt;@template&lt;/dt&gt;
  &lt;dd&gt;The current view (an instance of ActionView::Base). This object provides all methods available in your view. Coupled with &lt;code&gt;concat&lt;/code&gt; (for output) and &lt;code&gt;@proc&lt;/code&gt; (which provides the binding from your view) you can call any of these methods &lt;strong&gt;as if you were writing code in your ERb template&lt;/strong&gt;.&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Let&amp;#8217;s take a quick look at how the Rails-supplied FormBuilder uses these variables to implement a field-rendering method:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# File: actionpack/lib/action_view/helpers/form_helper.rb&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Line: 740, in class ActionView::Helpers::FormBuilder&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;radio_button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tag_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
  &lt;span class=&quot;vi&quot;&gt;@template&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;radio_button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@object_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tag_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;objectify_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This method invokes the &lt;code&gt;radio_button&lt;/code&gt; method of the template&amp;#8212;the exact same &lt;code&gt;radio_button&lt;/code&gt; method you call when you&amp;#8217;re creating a form without a FormBuilder. The first argument is the &lt;code&gt;@object_name&lt;/code&gt; which is stored in the FormBuilder object, followed by the &lt;code&gt;method&lt;/code&gt;, &lt;code&gt;tag_value&lt;/code&gt;, and &lt;code&gt;options&lt;/code&gt;. The options are first passed through &lt;code&gt;objectify_options&lt;/code&gt; which simply merges in some defaults stored in the FormBuilder.&lt;/p&gt;
&lt;p&gt;One final thing to note is the last four lines of the &lt;code&gt;form_helper.rb&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# File: actionpack/lib/action_view/helpers/form_helper.rb&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Line: 764, in module ActionView&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;cattr_accessor&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:default_form_builder&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default_form_builder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ActionView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Helpers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;FormBuilder&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;These lines re-open the ActionView::Base class to allow access to and set a default value for the &lt;code&gt;default_form_builder&lt;/code&gt; attribute. I mentioned above that we can call this method to set an application-wide default FormBuilder class, but it&amp;#8217;s important to notice that the default is set here, when Helper modules are included, &lt;strong&gt;not&lt;/strong&gt; at boot time. You may be tempted to call ActionView::Base.default_form_builder in your &lt;code&gt;config/environment.rb&lt;/code&gt; file, but this won&amp;#8217;t work. Instead, call it in one of your helpers, after the included Rails helpers are loaded.&lt;/p&gt;
&lt;p&gt;&lt;!-- write something about error messages methods --&gt;&lt;/p&gt;
&lt;h2 id=&quot;tips&quot;&gt;Some Practical Tips&lt;/h2&gt;
&lt;p&gt;So far this article has been a discussion of how Rails&amp;#8217; FormBuilder-related code works. If you want to do anything creative with FormBuilders, an understanding of how they work will help you greatly. However, you may just need to get something done, so in this section I will give you some quick pointers, sans explanation, for writing and using custom FormBuilders.&lt;/p&gt;
&lt;h3&gt;1. Inherit From the Included FormBuilder&lt;/h3&gt;
&lt;p&gt;You usually want to define your custom builder in &lt;code&gt;app/helpers/application_helper.rb&lt;/code&gt;. When you do so, you should make sure it inherits from the Rails-included base class, which will give you a good starting place:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;YourFormBuilder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActionView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Helpers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;FormBuilder&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Note that you should &lt;strong&gt;not&lt;/strong&gt; place your class inside the ApplicationHelper module but at the end of the file.&lt;/p&gt;
&lt;h3&gt;2. Set an Application-Wide Default FormBuilder&lt;/h3&gt;
&lt;p&gt;In &lt;code&gt;app/helpers/application_helper.rb&lt;/code&gt; call:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;ActionView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default_form_builder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;YourFormBuilder&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This saves you from having to pass &lt;code&gt;:builder =&amp;gt; YourCustomFormBuilder&lt;/code&gt; in the &lt;code&gt;options&lt;/code&gt; hash on every call to &lt;code&gt;form_for&lt;/code&gt;. You can still override this (with the &lt;code&gt;:builder&lt;/code&gt; option) where necessary.&lt;/p&gt;
&lt;h3&gt;3. Define Methods Dynamically in Bulk&lt;/h3&gt;
&lt;p&gt;You can get an array of all standard field helper methods by calling &lt;code&gt;field_helpers&lt;/code&gt;. You can add to/remove from this list:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;helpers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field_helpers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; 
  &lt;span class=&quot;sx&quot;&gt;%w(time_zone_select date_select)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; 
  &lt;span class=&quot;sx&quot;&gt;%w(hidden_field fields_for label)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;and then loop through all methods (field types) you want to customize, re-defining each dynamically by using &lt;code&gt;define_method&lt;/code&gt;, like so:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;helpers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;helper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;define_method&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;helper&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;detect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_a?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# decorate your fields here&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;4. Call Helper Methods (Just As You Would In An ERb Template)&lt;/h3&gt;
&lt;p&gt;If you can use a helper in a view, you can use it in your FormBuilder. This includes your custom helpers. Let&amp;#8217;s say you define a &lt;code&gt;small_caps&lt;/code&gt; method in your &lt;code&gt;ApplicationHelper&lt;/code&gt;. To call it in your FormBuilder, just do something like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;vi&quot;&gt;@template&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;small_caps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;some_word&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;5. Specify Field Layout In Partials&lt;/h3&gt;
&lt;p&gt;Just as you can do something like this in your ERb template:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;erb&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:partial&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;text_field&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
           &lt;span class=&quot;ss&quot;&gt;:locals&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:label&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Name&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;so too can you do it in your FormBuilder by using the &lt;code&gt;@template&lt;/code&gt; object:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;vi&quot;&gt;@template&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:partial&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;text_field&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                 &lt;span class=&quot;ss&quot;&gt;:locals&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:label&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Name&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This allows you to specify the appearance of forms (along with their labels, error messages, and various decorations) in ERb templates, which many people prefer to plain Ruby code.&lt;/p&gt;
&lt;h2&gt;Now, Go and Build Them&lt;/h2&gt;
&lt;p&gt;I hope I&amp;#8217;ve given you enough information to get started writing your own FormBuilder class. I really believe that FormBuilders are one of the keys to writing clean, reliable web applications and I&amp;#8217;m sure they aren&amp;#8217;t used as frequently as they should be due to lack of documentation.&lt;/p&gt;
&lt;p&gt;Thanks for reading, and good luck.&lt;/p&gt;</description>
    </item>


  </channel>
</rss>
