<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title>MetaSkills.net - Home</title>
  <id>tag:metaskills.net,2008:mephisto/</id>
  <generator version="0.8.0" uri="http://mephistoblog.com">Mephisto Drax</generator>
  <link href="http://metaskills.net/feed/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="http://metaskills.net/" rel="alternate" type="text/html"/>
  <updated>2008-10-13T20:33:23Z</updated>
  <entry xml:base="http://metaskills.net/">
    <author>
      <name>kencollins</name>
    </author>
    <id>tag:metaskills.net,2008-10-13:214</id>
    <published>2008-10-13T19:52:00Z</published>
    <updated>2008-10-13T20:33:23Z</updated>
    <category term="Apple/OSX"/>
    <category term="Heuristics"/>
    <category term="Ruby/Rails"/>
    <category term="code"/>
    <category term="javascript"/>
    <category term="lanterns"/>
    <category term="php"/>
    <category term="rails"/>
    <link href="http://metaskills.net/2008/10/13/code-o-lanterns-what-scares-you" rel="alternate" type="text/html"/>
    <title>Code-O-Lanterns: What Scares You?</title>
<summary type="html">&lt;img class=&quot;floatr&quot; src=&quot;/assets/2008/10/13/php_lantern.png&quot; height=&quot;228&quot; width=&quot;253&quot; /&gt;

&lt;p&gt;
  While reading the &lt;a href=&quot;http://tuaw.com/&quot; class=&quot;external-link&quot;&gt;The Unofficial Apple Weblog&lt;/a&gt; today I noticed this sweet little 
  &lt;a href=&quot;http://www.killerrobots.com/screensavers/&quot; class=&quot;external link&quot;&gt;Jack-O-Lantern screensaver&lt;/a&gt; for OS X. After some feedback on 
  the &lt;a href=&quot;http://757rb.org/&quot; class=&quot;external-link&quot;&gt;757.rb&lt;/a&gt; group, I decided to make some Code-O-Lanterns.
&lt;/p&gt;

&lt;p&gt;
  Follow the instructions for the &lt;a href=&quot;http://www.killerrobots.com/screensavers/&quot; class=&quot;external link&quot;&gt;Jack-O-Lantern screensaver&lt;/a&gt; 
  on where to put the carving files. If you are not on a Mac, I have taken some screen shots that you can use for desktop pictures. If you 
  would like to see a code o lantern that is not up... just ask for one, providing it has a logo!
&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
  &lt;img class=&quot;floatr&quot; src=&quot;/assets/2008/10/13/code_o_lanterns.png&quot; height=&quot;185&quot; width=&quot;554&quot; /&gt;
&lt;/div&gt;</summary><content type="html">
            &lt;img class=&quot;floatr&quot; src=&quot;/assets/2008/10/13/php_lantern.png&quot; height=&quot;228&quot; width=&quot;253&quot; /&gt;

&lt;p&gt;
  While reading the &lt;a href=&quot;http://tuaw.com/&quot; class=&quot;external-link&quot;&gt;The Unofficial Apple Weblog&lt;/a&gt; today I noticed this sweet little 
  &lt;a href=&quot;http://www.killerrobots.com/screensavers/&quot; class=&quot;external link&quot;&gt;Jack-O-Lantern screensaver&lt;/a&gt; for OS X. After some feedback on 
  the &lt;a href=&quot;http://757rb.org/&quot; class=&quot;external-link&quot;&gt;757.rb&lt;/a&gt; group, I decided to make some Code-O-Lanterns.
&lt;/p&gt;

&lt;p&gt;
  Follow the instructions for the &lt;a href=&quot;http://www.killerrobots.com/screensavers/&quot; class=&quot;external link&quot;&gt;Jack-O-Lantern screensaver&lt;/a&gt; 
  on where to put the carving files. If you are not on a Mac, I have taken some screen shots that you can use for desktop pictures. If you 
  would like to see a code o lantern that is not up... just ask for one, providing it has a logo!
&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
  &lt;img class=&quot;floatr&quot; src=&quot;/assets/2008/10/13/code_o_lanterns.png&quot; height=&quot;185&quot; width=&quot;554&quot; /&gt;
&lt;/div&gt;

&lt;img class=&quot;floatr&quot; src=&quot;/assets/2008/10/13/php_lantern.png&quot; height=&quot;228&quot; width=&quot;253&quot; /&gt;

&lt;p&gt;
  While reading the &lt;a href=&quot;http://tuaw.com/&quot; class=&quot;external-link&quot;&gt;The Unofficial Apple Weblog&lt;/a&gt; today I noticed this sweet little 
  &lt;a href=&quot;http://www.killerrobots.com/screensavers/&quot; class=&quot;external link&quot;&gt;Jack-O-Lantern screensaver&lt;/a&gt; for OS X. After some feedback on 
  the &lt;a href=&quot;http://757rb.org/&quot; class=&quot;external-link&quot;&gt;757.rb&lt;/a&gt; group, I decided to make some Code-O-Lanterns.
&lt;/p&gt;

&lt;p&gt;
  Follow the instructions for the &lt;a href=&quot;http://www.killerrobots.com/screensavers/&quot; class=&quot;external link&quot;&gt;Jack-O-Lantern screensaver&lt;/a&gt; 
  on where to put the carving files. If you are not on a Mac, I have taken some screen shots that you can use for desktop pictures. If you 
  would like to see a code o lantern that is not up... just ask for one, providing it has a logo!
&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
  &lt;img class=&quot;floatr&quot; src=&quot;/assets/2008/10/13/code_o_lanterns.png&quot; height=&quot;185&quot; width=&quot;554&quot; /&gt;
&lt;/div&gt;



&lt;h2&gt;Code-O-Lanterns Files&lt;/h2&gt;

&lt;ul class=&quot;mt10 mb10&quot;&gt;
  &lt;li&gt;757rb &lt;a href=&quot;/files/code_o_lanterns/carvings/757rb.png&quot;&gt;[Carving]&lt;/a&gt; &lt;a href=&quot;/files/code_o_lanterns/desktops/757rb.png&quot;&gt;[Desktop]&lt;/a&gt; &lt;/li&gt;
  &lt;li&gt;AJAX &lt;a href=&quot;/files/code_o_lanterns/carvings/ajax.png&quot;&gt;[Carving]&lt;/a&gt; &lt;a href=&quot;/files/code_o_lanterns/desktops/ajax.png&quot;&gt;[Desktop]&lt;/a&gt; &lt;/li&gt;
  &lt;li&gt;GIT &lt;a href=&quot;/files/code_o_lanterns/carvings/git.png&quot;&gt;[Carving]&lt;/a&gt; &lt;a href=&quot;/files/code_o_lanterns/desktops/git.png&quot;&gt;[Desktop]&lt;/a&gt; &lt;/li&gt;
  &lt;li&gt;Java &lt;a href=&quot;/files/code_o_lanterns/carvings/java.png&quot;&gt;[Carving]&lt;/a&gt; &lt;a href=&quot;/files/code_o_lanterns/desktops/java.png&quot;&gt;[Desktop]&lt;/a&gt; &lt;/li&gt;
  &lt;li&gt;JavaScript &lt;a href=&quot;/files/code_o_lanterns/carvings/javascript.png&quot;&gt;[Carving]&lt;/a&gt; &lt;a href=&quot;/files/code_o_lanterns/desktops/javascript.png&quot;&gt;[Desktop]&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Perl &lt;a href=&quot;/files/code_o_lanterns/carvings/perl.png&quot;&gt;[Carving]&lt;/a&gt; &lt;a href=&quot;/files/code_o_lanterns/desktops/perl.png&quot;&gt;[Desktop]&lt;/a&gt; &lt;/li&gt;
  &lt;li&gt;PHP &lt;a href=&quot;/files/code_o_lanterns/carvings/php.png&quot;&gt;[Carving]&lt;/a&gt; &lt;a href=&quot;/files/code_o_lanterns/desktops/php.png&quot;&gt;[Desktop]&lt;/a&gt; &lt;/li&gt;
  &lt;li&gt;Python &lt;a href=&quot;/files/code_o_lanterns/carvings/python.png&quot;&gt;[Carving]&lt;/a&gt; &lt;a href=&quot;/files/code_o_lanterns/desktops/python.png&quot;&gt;[Desktop]&lt;/a&gt; &lt;/li&gt;
  &lt;li&gt;Rails &lt;a href=&quot;/files/code_o_lanterns/carvings/rails.png&quot;&gt;[Carving]&lt;/a&gt; &lt;a href=&quot;/files/code_o_lanterns/desktops/rails.png&quot;&gt;[Desktop]&lt;/a&gt; &lt;/li&gt;
  &lt;li&gt;SVN &lt;a href=&quot;/files/code_o_lanterns/carvings/svn.png&quot;&gt;[Carving]&lt;/a&gt; &lt;a href=&quot;/files/code_o_lanterns/desktops/svn.png&quot;&gt;[Desktop]&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;
          </content>  </entry>
  <entry xml:base="http://metaskills.net/">
    <author>
      <name>kencollins</name>
    </author>
    <id>tag:metaskills.net,2008-10-11:213</id>
    <published>2008-10-11T01:52:00Z</published>
    <updated>2008-10-11T01:55:18Z</updated>
    <category term="Database"/>
    <category term="Heuristics"/>
    <category term="Ruby/Rails"/>
    <category term="plugin"/>
    <category term="rails"/>
    <link href="http://metaskills.net/2008/10/11/plug-it-in-plug-it-in" rel="alternate" type="text/html"/>
    <title>Plug It In Plug It In</title>
<content type="html">
            &lt;p&gt;
  &lt;img class=&quot;floatr&quot; src=&quot;http://www.metaskills.net/assets/2008/10/11/plugitin.png&quot; height=&quot;403&quot; alt=&quot;Jack Has Many Things&quot; width=&quot;285&quot; /&gt;
  I've been busy putting together some plugins form misc work. If you did not catch my latest article &lt;em&gt;&lt;a href=&quot;http://www.metaskills.net/2008/9/28/jack-has_many-things&quot;&gt;Jack has_many :things&lt;/a&gt;&lt;/em&gt; where I covered GroupeScope, by all means check it out. I've also just finished up a pretty solid backport of NamedScope that can be found on my Github page. It bills itself as a well tested complete back port for rails 1.2.6 and 2.0.4.
&lt;/p&gt;

&lt;p&gt;One thing that has been a real help while I've been developing these plugins is this autotest class I put together specifically for developing rails plugins. I even got mention on rubyonrails.org. Sweet! More to come.
&lt;/p&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul class=&quot;mt20&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/metaskills/named_scope/tree/master&quot; class=&quot;external-link&quot;&gt;The NamedScope plugin.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/metaskills/grouped_scope/tree/master&quot; class=&quot;external-link&quot;&gt;The GroupedScope plugin.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/metaskills/autotest_railsplugin/tree/master&quot; class=&quot;external-link&quot;&gt;The RailsPlugin class for Autotest.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.artlebedev.com/everything/vilcus/&quot; class=&quot;external-link&quot;&gt;Vilcus plug dactyloadapter&lt;/a&gt;. Developed specially for people who enjoy closing electrical circuits with their own fingers.&lt;/li&gt;
&lt;/ul&gt;
          </content>  </entry>
  <entry xml:base="http://metaskills.net/">
    <author>
      <name>kencollins</name>
    </author>
    <id>tag:metaskills.net,2008-09-28:212</id>
    <published>2008-09-28T19:34:00Z</published>
    <updated>2008-09-29T02:41:03Z</updated>
    <category term="Database"/>
    <category term="Heuristics"/>
    <category term="Ruby/Rails"/>
    <category term="activerecord"/>
    <category term="grouped_scope"/>
    <category term="plugin"/>
    <category term="rails"/>
    <link href="http://metaskills.net/2008/9/28/jack-has_many-things" rel="alternate" type="text/html"/>
    <title>Jack has_many :things</title>
<summary type="html">&lt;div class=&quot;photobounding floatl mr20&quot;&gt;
  &lt;div class=&quot;tl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;tr&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;bl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;br&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;photoborder&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;phototime&quot;&gt;
    &lt;img src=&quot;http://www.metaskills.net/assets/2008/9/28/jack.jpg&quot; height=&quot;214&quot; alt=&quot;Jack Has Many Things&quot; width=&quot;320&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
  I am Jack's sofa, stereo and wardrobe... I make Jack's life complete. I reside in a ActiveRecord table called &quot;things&quot; and Jack is the only one that has the key. This is Jack's life, and it's ending one minute at a time.
&lt;/p&gt;
  
&lt;p&gt;
  As rails developers, we have done this simple relationship over and over again. I'm sure the has_many association is by far the most common in app/db design. It gives a single resource quick and easy access to others, but as your application grows, and depression sets in...
&lt;/p&gt;</summary><content type="html">
            &lt;div class=&quot;photobounding floatl mr20&quot;&gt;
  &lt;div class=&quot;tl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;tr&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;bl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;br&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;photoborder&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;phototime&quot;&gt;
    &lt;img src=&quot;http://www.metaskills.net/assets/2008/9/28/jack.jpg&quot; height=&quot;214&quot; alt=&quot;Jack Has Many Things&quot; width=&quot;320&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
  I am Jack's sofa, stereo and wardrobe... I make Jack's life complete. I reside in a ActiveRecord table called &quot;things&quot; and Jack is the only one that has the key. This is Jack's life, and it's ending one minute at a time.
&lt;/p&gt;
  
&lt;p&gt;
  As rails developers, we have done this simple relationship over and over again. I'm sure the has_many association is by far the most common in app/db design. It gives a single resource quick and easy access to others, but as your application grows, and depression sets in...
&lt;/p&gt;
&lt;div class=&quot;photobounding floatl mr20&quot;&gt;
  &lt;div class=&quot;tl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;tr&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;bl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;br&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;photoborder&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;phototime&quot;&gt;
    &lt;img src=&quot;http://www.metaskills.net/assets/2008/9/28/jack.jpg&quot; height=&quot;214&quot; alt=&quot;Jack Has Many Things&quot; width=&quot;320&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
  I am Jack's sofa, stereo and wardrobe... I make Jack's life complete. I reside in a ActiveRecord table called &quot;things&quot; and Jack is the only one that has the key. This is Jack's life, and it's ending one minute at a time.
&lt;/p&gt;
  
&lt;p&gt;
  As rails developers, we have done this simple relationship over and over again. I'm sure the has_many association is by far the most common in app/db design. It gives a single resource quick and easy access to others, but as your application grows, and depression sets in, we have to open up.
&lt;/p&gt;




&lt;h2&gt;It's cheaper than a movie, and there's free coffee.&lt;/h2&gt;

&lt;div class=&quot;photobounding floatr ml10&quot;&gt;
  &lt;div class=&quot;tl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;tr&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;bl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;br&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;photoborder&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;phototime&quot;&gt;
    &lt;img src=&quot;http://www.metaskills.net/assets/2008/9/28/bob.jpg&quot; height=&quot;174&quot; alt=&quot;Jack With Bob&quot; width=&quot;148&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
  I am talking about groups. Not the underground ones that carve us out of wood, but ones where we share with those around us. This is healing. The time has come to for our objects to do the same, but how?
&lt;/p&gt;

&lt;p&gt;
  The problem is that the ActiveRecord has_many association is scoped to an individual. No matter what conditions are tacked on, they are always &lt;a href=&quot;http://en.wikipedia.org/wiki/Pwn&quot; class=&quot;external-link&quot;&gt;pwned&lt;/a&gt; by the proxy owner. The things they own have ended up owning you! Sure we could model some groupable schema and go through it, ActiveRecord is beautiful that way. But what about our hard work in all those existing has_many associations and named_scopes? 
&lt;/p&gt;





&lt;h2&gt;I felt like destroying something beautiful.&lt;/h2&gt;

&lt;p&gt;
  The solution is on everyone's face, it is on the tip of everyone's tongue. I just gave it a name. It is called &lt;a href=&quot;http://github.com/metaskills/grouped_scope/tree/master&quot; class=&quot;external-link&quot;&gt;GroupedScope&lt;/a&gt; and it will fundamentally change the constructed SQL for the has_many associations you want to share. The best part is that it will leave those associations untouched for continued use. GroupedScope even works with your existing association extensions and any named scopes. Let's have a session.
&lt;/p&gt; 

&lt;p&gt;First we need to install the plugin.&lt;/p&gt;

&lt;pre class=&quot;command&quot;&gt;
./script/plugin install git://github.com/metaskills/grouped_scope.git
&lt;/pre&gt;

&lt;p&gt;Now let's open up our Person model and schema, so Jack can share.&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;PeopleCanChooseAGroup&lt;/span&gt; &amp;lt; &lt;span class=&quot;co&quot;&gt;ActiveRecord&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Migration&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.up&lt;tt&gt;
&lt;/tt&gt;    add_column &lt;span class=&quot;sy&quot;&gt;:people&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:group_id&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:integer&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.down&lt;tt&gt;
&lt;/tt&gt;    remove_column &lt;span class=&quot;sy&quot;&gt;:people&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:group_id&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Person&lt;/span&gt; &amp;lt; &lt;span class=&quot;co&quot;&gt;ActiveRecord&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  has_many &lt;span class=&quot;sy&quot;&gt;:things&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  has_many &lt;span class=&quot;sy&quot;&gt;:acquaintances&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  has_many &lt;span class=&quot;sy&quot;&gt;:problems&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  grouped_scope &lt;span class=&quot;sy&quot;&gt;:things&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:problems&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;iv&quot;&gt;@jack&lt;/span&gt; = &lt;span class=&quot;co&quot;&gt;Person&lt;/span&gt;.find_by_name(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Jack&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;iv&quot;&gt;@bob&lt;/span&gt;  = &lt;span class=&quot;co&quot;&gt;Person&lt;/span&gt;.find_by_name(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bob&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;iv&quot;&gt;@jack&lt;/span&gt;.update_attribute &lt;span class=&quot;sy&quot;&gt;:group_id&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;iv&quot;&gt;@bob&lt;/span&gt;.update_attribute &lt;span class=&quot;sy&quot;&gt;:group_id&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;p&gt;
  Every Person object in our app is now ready to share their :things and their :problems. I have also just arbitrarily put Jack and Bob into the same group. Declaring &lt;code&gt;grouped_scope&lt;/code&gt; in the model generates a new &lt;code&gt;group&lt;/code&gt; instance method that will allow us to iterate over its members.
&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;iv&quot;&gt;@jack&lt;/span&gt;.group   &lt;span class=&quot;c&quot;&gt;# =&amp;gt; [#&amp;lt;Person id: 1, name: &amp;quot;Jack&amp;quot;, group_id: 1&amp;gt;, #&amp;lt;Person id: 2, name: &amp;quot;Bob&amp;quot;, group_id: 1&amp;gt;]&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;






&lt;h2&gt;We all started seeing things differently.&lt;/h2&gt;

&lt;p&gt;
  The object returned by the group method, an instance of GroupedScope::SelfGrouping, is far cooler than you think. It looks and acts as an enumerable array, but in reality it is a proxy object that can delegate to generated grouped association reflections which mimic their originals. Essentially giving the group access to all associated objects of its members, in this case their :things and :problems. Did I loose you? 
&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;iv&quot;&gt;@jack&lt;/span&gt;.problems.size   &lt;span class=&quot;c&quot;&gt;# =&amp;gt; 6&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;iv&quot;&gt;@bob&lt;/span&gt;.problems.size    &lt;span class=&quot;c&quot;&gt;# =&amp;gt; 2&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;iv&quot;&gt;@bob&lt;/span&gt;.group.problems        &lt;span class=&quot;c&quot;&gt;# =&amp;gt; [#&amp;lt;Problem...&amp;gt;,#&amp;lt;Problem...&amp;gt;,#&amp;lt;Problem...&amp;gt;,#&amp;lt;Problem...&amp;gt;,....]&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;iv&quot;&gt;@bob&lt;/span&gt;.group.problems.size   &lt;span class=&quot;c&quot;&gt;# =&amp;gt; 8&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;iv&quot;&gt;@jack&lt;/span&gt;.group.problems.size  &lt;span class=&quot;c&quot;&gt;# =&amp;gt; 8&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;p&gt;
  Without going into the detail of Jack's and Bob's problems, we can see that within the group, they are all shared. This is what the GroupedScope plugin is really all about. It allows existing has_many associations to be called on the group which changes the SQL generated to be owned by the group, essentially from &lt;code&gt;id = 1&lt;/code&gt; to &lt;code&gt;id IN (1,2)&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
  The way it accomplishes this is pretty sweet. GroupedScope creates an association reflection and accessor that will proxy all critical reflection calls back to the original association reflection. This means that it can be really smart and maintain all the logic in the existing association which could include custom options like :class_name, :foreign_key, :though, and :extend, very handy for legacy/custom associations. It also lets you chain named scopes on the grouped scope. Here is very contrived example:
&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Person&lt;/span&gt; &amp;lt; &lt;span class=&quot;co&quot;&gt;ActiveRecord&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  has_many &lt;span class=&quot;sy&quot;&gt;:mental_issues&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:class_name&lt;/span&gt; =&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;MentalState&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:foreign_key&lt;/span&gt; =&amp;gt; &lt;span class=&quot;sy&quot;&gt;:name&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;dangerous&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      find &lt;span class=&quot;sy&quot;&gt;:all&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:conditions&lt;/span&gt; =&amp;gt; {&lt;span class=&quot;sy&quot;&gt;:snap_tolerance&lt;/span&gt; =&amp;gt; &lt;span class=&quot;i&quot;&gt;10&lt;/span&gt;}&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  grouped_scope &lt;span class=&quot;sy&quot;&gt;:mental_issues&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;MentalState&lt;/span&gt; &amp;lt; &lt;span class=&quot;co&quot;&gt;ActiveRecord&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  named_scope &lt;span class=&quot;sy&quot;&gt;:treatable_by&lt;/span&gt;, lambda { |doctor| &lt;tt&gt;
&lt;/tt&gt;    {&lt;span class=&quot;sy&quot;&gt;:conditions&lt;/span&gt; =&amp;gt; {&lt;span class=&quot;sy&quot;&gt;:doctor_id&lt;/span&gt; =&amp;gt; doctor.id}}&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;iv&quot;&gt;@jack&lt;/span&gt;.group.mental_issues.dangerous.treatable_by(&lt;span class=&quot;iv&quot;&gt;@doctor&lt;/span&gt;) &lt;span class=&quot;c&quot;&gt;# =&amp;gt; [#&amp;lt;MentalState...&amp;gt;,#&amp;lt;MentalState...&amp;gt;]&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;




&lt;h2&gt;This is probably one of those &quot;cry for help&quot; things.&lt;/h2&gt;

&lt;div class=&quot;photobounding floatr ml10&quot;&gt;
  &lt;div class=&quot;tl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;tr&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;bl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;br&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;photoborder&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;phototime&quot;&gt;
    &lt;img src=&quot;http://www.metaskills.net/assets/2008/9/28/marla.jpg&quot; height=&quot;214&quot; alt=&quot;Marla&quot; width=&quot;320&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
  The GroupedScope plugin is not done. It is however well tested and can do what I have outlined in both rails 1.2.6 and 2.1.1. I have marked some TODO's in the project README but I thought I would cover a few here in detail.
&lt;/p&gt;

&lt;p&gt;
  First, every model that declares &lt;code&gt;grouped_scope&lt;/code&gt; also generates a &lt;code&gt;belongs_to :grouping&lt;/code&gt; association that can be used to get to the GroupedScope::Grouping object. This object has no underlying schema and is not being used right now. Eventually this will be the place where you write your own &lt;a href=&quot;http://errtheblog.com/posts/67-evil-twin-plugin&quot; class=&quot;external-link&quot;&gt;evil twin plugin&lt;/a&gt; that defines your business logic to what a group (not the selfgrouping proxy) can do. For now, it would be a good idea to generate a &quot;groupings&quot; table and create rows and use those IDs when assigning group_ids.
&lt;/p&gt;

&lt;p&gt;
  Also, you may have noticed that GroupedScope focuses on a single group and that no single owner can essentially have many groups. I think at some point I might like to see this and work like all the examples above. Have other ideas? Send me an email. I'm ken at this domain dot com.
&lt;/p&gt;



&lt;h2&gt;I'd like to thank the Academy.&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/metaskills/grouped_scope/tree/master&quot; class=&quot;external-link&quot;&gt;The GroupedScope plugin on my Github account.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Fight_Club&quot; class=&quot;external-link&quot;&gt;About the movie Fight Club.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
          </content>  </entry>
  <entry xml:base="http://metaskills.net/">
    <author>
      <name>kencollins</name>
    </author>
    <id>tag:metaskills.net,2008-09-19:194</id>
    <published>2008-09-19T17:46:00Z</published>
    <updated>2008-09-19T17:58:41Z</updated>
    <category term="Heuristics"/>
    <category term="Ruby/Rails"/>
    <category term="Workflow"/>
    <category term="autotest"/>
    <category term="plugin"/>
    <category term="rails"/>
    <category term="tdd"/>
    <link href="http://metaskills.net/2008/9/19/using-autotest-for-rails-plugin-development" rel="alternate" type="text/html"/>
    <title>Using Autotest For Rails Plugin Development</title>
<summary type="html">&lt;p&gt;
  I love &lt;a href=&quot;http://www.zenspider.com/ZSS/Products/ZenTest/&quot; class=&quot;external-link&quot;&gt;autotest&lt;/a&gt;. I have event posted before how to 
  extend the idea of &lt;a href=&quot;/2008/4/6/autotest-playlist-for-red-green-feedback&quot;&gt;autotest sounds to a red/green playlist&lt;/a&gt; but now that 
  I am taking more time to extract some of my work to plugins, I really wanted autotest to come with me. The problem is that the default 
  autotest mappings do not play with rails conventions, the biggest being that test files for a lib match the name of the lib with 
  &lt;code&gt;_test.rb&lt;/code&gt; at the END of the...
&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;
  I love &lt;a href=&quot;http://www.zenspider.com/ZSS/Products/ZenTest/&quot; class=&quot;external-link&quot;&gt;autotest&lt;/a&gt;. I have event posted before how to 
  extend the idea of &lt;a href=&quot;/2008/4/6/autotest-playlist-for-red-green-feedback&quot;&gt;autotest sounds to a red/green playlist&lt;/a&gt; but now that 
  I am taking more time to extract some of my work to plugins, I really wanted autotest to come with me. The problem is that the default 
  autotest mappings do not play with rails conventions, the biggest being that test files for a lib match the name of the lib with 
  &lt;code&gt;_test.rb&lt;/code&gt; at the END of the...
&lt;/p&gt;
&lt;p&gt;
  I love &lt;a href=&quot;http://www.zenspider.com/ZSS/Products/ZenTest/&quot; class=&quot;external-link&quot;&gt;autotest&lt;/a&gt;. I have event posted before how to 
  extend the idea of &lt;a href=&quot;/2008/4/6/autotest-playlist-for-red-green-feedback&quot;&gt;autotest sounds to a red/green playlist&lt;/a&gt; but now that 
  I am taking more time to extract some of my work to plugins, I really wanted autotest to come with me. The problem is that the default 
  autotest mappings do not play with rails conventions, the biggest being that test files for a lib match the name of the lib with 
  &lt;code&gt;_test.rb&lt;/code&gt; at the END of the filename.
&lt;/p&gt;

&lt;p&gt;
  Today I posted a new project to my Github account, called 
  &lt;a href=&quot;http://github.com/metaskills/autotest_railsplugin/tree/master&quot; class=&quot;external-link&quot;&gt;Autotest::Railsplugin&lt;/a&gt;. This project 
  should be a great start for fleshing out all the typical mappings, ignore, libs, etc. that autotest needs to know about when developing 
  a rails plugin. I invite you to download it and give it a try and provide feedback on missing details.
&lt;/p&gt;


&lt;h2&gt;To Install&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/metaskills/autotest_railsplugin/tree/master&quot; class=&quot;external-link&quot;&gt;Download&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Rename the directory to &quot;autotest&quot;&lt;/li&gt;
  &lt;li&gt;Place inside of your plugin’s root directory.&lt;/li&gt;
  &lt;li&gt;From your plugin root, you can now use autotest.&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class=&quot;command&quot;&gt;
$ autotest
  loading autotest/railsplugin
&lt;/pre&gt;

&lt;p&gt;
  By default, autotest will scan your present working directory for an autotest folder that has a discover.rb in it. So it should find and 
  display the &lt;code&gt;loading autotest/railsplugin&lt;/code&gt; which means it found the plugin class just fine. If this is not the case make sure 
  you have the directory named correctly. If you have a conflicting autotest directory for some reason you can always force the plugin class, 
  again assuming you have it in the right, place using:
&lt;/p&gt;

&lt;pre class=&quot;command&quot;&gt;
$ autotest -railsplugin
&lt;/pre&gt;


&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/metaskills/autotest_railsplugin/tree/master&quot; class=&quot;external-link&quot;&gt;The New Autotest::Railsplugin on Github&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.zenspider.com/ZSS/Products/ZenTest/&quot;&gt;The Official ZenTest/AutoTest Site&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2008/4/6/autotest-playlist-for-red-green-feedback&quot;&gt;Autotest Playlist For Red/Green Feedback&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.fozworks.com/2007/7/28/autotest-sound-effects/&quot; class=&quot;external-link&quot;&gt;Autotest Sound Idea from Jeremy Seitz @ FozWorks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
          </content>  </entry>
  <entry xml:base="http://metaskills.net/">
    <author>
      <name>kencollins</name>
    </author>
    <id>tag:metaskills.net,2008-09-14:190</id>
    <published>2008-09-14T18:31:00Z</published>
    <updated>2008-09-14T18:42:22Z</updated>
    <category term="Lifestyle"/>
    <category term="lifestyle"/>
    <category term="multicade"/>
    <link href="http://metaskills.net/2008/9/14/going-horizontal-on-the-multicade" rel="alternate" type="text/html"/>
    <title>Going Horizontal On The Multicade</title>
<summary type="html">&lt;p&gt;
&lt;div class=&quot;photobounding floatl mr20&quot;&gt;
  &lt;div class=&quot;tl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;tr&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;bl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;br&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;photoborder&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;phototime&quot;&gt;
    &lt;img src=&quot;/assets/2008/9/14/multicade.jpg&quot; height=&quot;333&quot; alt=&quot;New multicade front view.&quot; width=&quot;276&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;


  A few months ago I &quot;invested&quot; in a upright Galaga multicade. This is no costly refurb/restoration unit, but rather a customized new build 
  from a great company called &lt;a href=&quot;http://www.arcadeshop.com/&quot; class=&quot;external-link&quot;&gt;Arcadeshop Amusement&lt;/a&gt;. This place does two great 
  things. First they will manufacturer/build you a new cabinet of your liking with all the parts professionally installed. This includes 
  the display, &lt;a href=&quot;http://en.wikipedia.org/wiki/Jamma&quot; class=&quot;external-link&quot;&gt;JAMMA&lt;/a&gt; harness, coin door assembly, control panel, and 
  all artwork. I chose a classic Galaga/Ms.Pacman/Midway cabinet with a 19&quot; CRT display. My only deviation from the Galaga theme was a 
  multicade control panel that had a 4-way joystick and two buttons for the left or right handed.
&lt;/p&gt;

&lt;p&gt;
  The second thing about this great company is that sell one of the coolest &lt;a href=&quot;http://www.arcadeshop.com/multi-pcb/multi-pcb.htm&quot; class=&quot;external-link&quot;&gt;Multicade JAMMA PCBs&lt;/a&gt; I have seen. This board is programmable with a standard serial cable to run game ROM's in their 
  approved list and that included such greats that I wanted like Galaga, Donkey Kong, Ms.Pacman, and Phoenix. For the record... I am not going 
  after &lt;a href=&quot;http://en.wikipedia.org/wiki/Billy_Mitchell_(gamer)&quot; class=&quot;external-link&quot;&gt;Billy Mitchell's&lt;/a&gt; record. I just wanted a nice...
&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;
&lt;div class=&quot;photobounding floatl mr20&quot;&gt;
  &lt;div class=&quot;tl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;tr&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;bl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;br&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;photoborder&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;phototime&quot;&gt;
    &lt;img src=&quot;/assets/2008/9/14/multicade.jpg&quot; height=&quot;333&quot; alt=&quot;New multicade front view.&quot; width=&quot;276&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;


  A few months ago I &quot;invested&quot; in a upright Galaga multicade. This is no costly refurb/restoration unit, but rather a customized new build 
  from a great company called &lt;a href=&quot;http://www.arcadeshop.com/&quot; class=&quot;external-link&quot;&gt;Arcadeshop Amusement&lt;/a&gt;. This place does two great 
  things. First they will manufacturer/build you a new cabinet of your liking with all the parts professionally installed. This includes 
  the display, &lt;a href=&quot;http://en.wikipedia.org/wiki/Jamma&quot; class=&quot;external-link&quot;&gt;JAMMA&lt;/a&gt; harness, coin door assembly, control panel, and 
  all artwork. I chose a classic Galaga/Ms.Pacman/Midway cabinet with a 19&quot; CRT display. My only deviation from the Galaga theme was a 
  multicade control panel that had a 4-way joystick and two buttons for the left or right handed.
&lt;/p&gt;

&lt;p&gt;
  The second thing about this great company is that sell one of the coolest &lt;a href=&quot;http://www.arcadeshop.com/multi-pcb/multi-pcb.htm&quot; class=&quot;external-link&quot;&gt;Multicade JAMMA PCBs&lt;/a&gt; I have seen. This board is programmable with a standard serial cable to run game ROM's in their 
  approved list and that included such greats that I wanted like Galaga, Donkey Kong, Ms.Pacman, and Phoenix. For the record... I am not going 
  after &lt;a href=&quot;http://en.wikipedia.org/wiki/Billy_Mitchell_(gamer)&quot; class=&quot;external-link&quot;&gt;Billy Mitchell's&lt;/a&gt; record. I just wanted a nice...
&lt;/p&gt;
&lt;p&gt;

&lt;div class=&quot;photobounding floatl mr20&quot;&gt;
  &lt;div class=&quot;tl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;tr&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;bl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;br&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;photoborder&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;phototime&quot;&gt;
    &lt;img src=&quot;/assets/2008/9/14/multicade.jpg&quot; height=&quot;333&quot; alt=&quot;New multicade front view.&quot; width=&quot;276&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

  A few months ago I &quot;invested&quot; in a upright Galaga multicade. This is no costly refurb/restoration unit, but rather a customized new build 
  from a great company called &lt;a href=&quot;http://www.arcadeshop.com/&quot; class=&quot;external-link&quot;&gt;Arcadeshop Amusement&lt;/a&gt;. This place does two great 
  things. First they will manufacturer/build you a new cabinet of your liking with all the parts professionally installed. This includes 
  the display, &lt;a href=&quot;http://en.wikipedia.org/wiki/Jamma&quot; class=&quot;external-link&quot;&gt;JAMMA&lt;/a&gt; harness, coin door assembly, control panel, and 
  all artwork. I chose a classic Galaga/Ms.Pacman/Midway cabinet with a 19&quot; CRT display. My only deviation from the Galaga theme was a 
  multicade control panel that had a 4-way joystick and two buttons for the left or right handed.
&lt;/p&gt;

&lt;p&gt;
  The second thing about this great company is that sell one of the coolest &lt;a href=&quot;http://www.arcadeshop.com/multi-pcb/multi-pcb.htm&quot; class=&quot;external-link&quot;&gt;Multicade JAMMA PCBs&lt;/a&gt; I have seen. This board is programmable with a standard serial cable to run game ROM's in their 
  approved list and that included such greats that I wanted like Galaga, Donkey Kong, Ms.Pacman, and Phoenix. For the record... I am not going 
  after &lt;a href=&quot;http://en.wikipedia.org/wiki/Billy_Mitchell_(gamer)&quot; class=&quot;external-link&quot;&gt;Billy Mitchell's&lt;/a&gt; record. I just wanted a nice 
  low-tech diversion :)
&lt;/p&gt;

&lt;p&gt;
  So these games held me over for a time, but I really wanted to be a bit more flexible with the option to play some horizontal games. 
  To that end, I invited my friend and fellow 757.rb'er Geoff Parsons over to help me rotate my CRT. Before we got to that jun part, I had to 
  manufacture my own horizontal cross members to hold the display. Thankfully a trip to LOWES steel part section and a new hack saw yielded a 
  very decent support system, see here. The icing on the cake after we remounted the CRT was to replace the 4-way joystick with a new 
  &lt;a href=&quot;http://www.happcontrols.com/joysticks/super_joy.htm&quot; class=&quot;external-link&quot;&gt;4/8-way super stick from HAPP Controls&lt;/a&gt;, a new 
  &lt;a href=&quot;http://www.lizardlickamusements.com/pages/boards.shtml&quot; class=&quot;external-link&quot;&gt;19-in-one JAMMA PCB&lt;/a&gt; from Lizard Lick, and a 
  new monitor bezel for the horizontal display. Now with this PCB, I am enjoying games like Super Mario Bros, Gradius, and Defender.
&lt;/p&gt;

&lt;div class=&quot;photobounding floatr ml20&quot;&gt;
  &lt;div class=&quot;tl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;tr&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;bl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;br&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;photoborder&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;phototime&quot;&gt;
    &lt;img src=&quot;/assets/2008/9/14/multicade_horiz.jpg&quot; height=&quot;298&quot; alt=&quot;New horizontal mounts for the multicade.&quot; width=&quot;385&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
  For those that may ask, why did I not go with some sort of MAME system. Sometimes options are good... but too many are distracting. 
  I really like the idea of having as much as my multicade mimic the old arcade cabinet as possible, and hacking on another computer to 
  do that was not in the cards. I love just slapping in a JAMMA board and having the set of games I like. Low-tech fun!
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://metaskills.net/">
    <author>
      <name>kencollins</name>
    </author>
    <id>tag:metaskills.net,2008-08-18:172</id>
    <published>2008-08-18T01:22:00Z</published>
    <updated>2008-10-06T13:14:50Z</updated>
    <category term="Heuristics"/>
    <category term="Ruby/Rails"/>
    <category term="class"/>
    <category term="javascript"/>
    <category term="object"/>
    <category term="oriented"/>
    <category term="rails"/>
    <category term="ruby"/>
    <link href="http://metaskills.net/2008/8/18/in-hell-oo-for-homemarks" rel="alternate" type="text/html"/>
    <title>Hell'OO HomeMarks</title>
<summary type="html">&lt;p&gt;
  Well HomeMarks v2.0 is done and ready for the public. You can download it from my 
  &lt;a href=&quot;http://github.com/metaskills/homemarks/tree/master&quot; class=&quot;external-link&quot;&gt;Github project&lt;/a&gt; page. It has a real simple &lt;code&gt;rake app:bootstrap&lt;/code&gt; 
  task that I came up with over the weekend will have you running a local copy in only a few seconds, give it a try. Sometime 
  over the next few days, I'll move over the live site to this code base too. If you have not yet kept up on the implementation 
  mantra I set down for the HomeMarks v2 project, you might want to &lt;a href=&quot;/2008/5/24/the-ajax-head-br-design-pattern&quot;&gt;read an older post&lt;/a&gt; 
  as well as this excerpt from the project README.
&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;
  Well HomeMarks v2.0 is done and ready for the public. You can download it from my 
  &lt;a href=&quot;http://github.com/metaskills/homemarks/tree/master&quot; class=&quot;external-link&quot;&gt;Github project&lt;/a&gt; page. It has a real simple &lt;code&gt;rake app:bootstrap&lt;/code&gt; 
  task that I came up with over the weekend will have you running a local copy in only a few seconds, give it a try. Sometime 
  over the next few days, I'll move over the live site to this code base too. If you have not yet kept up on the implementation 
  mantra I set down for the HomeMarks v2 project, you might want to &lt;a href=&quot;/2008/5/24/the-ajax-head-br-design-pattern&quot;&gt;read an older post&lt;/a&gt; 
  as well as this excerpt from the project README.
&lt;/p&gt;
&lt;p&gt;
  Well HomeMarks v2.0 is done and ready for the public. You can download it from my 
  &lt;a href=&quot;http://github.com/metaskills/homemarks/tree/master&quot; class=&quot;external-link&quot;&gt;Github project&lt;/a&gt; page. It has a real simple &lt;code&gt;rake app:bootstrap&lt;/code&gt; 
  task that I came up with over the weekend will have you running a local copy in only a few seconds, give it a try. Sometime 
  over the next few days, I'll move over the live site to this code base too. If you have not yet kept up on the implementation 
  mantra I set down for the HomeMarks v2 project, you might want to &lt;a href=&quot;/2008/5/24/the-ajax-head-br-design-pattern&quot;&gt;read an older post&lt;/a&gt; 
  as well as this excerpt from the project README.
&lt;/p&gt;

&lt;blockquote&gt;
  &lt;div&gt;
    HomeMarks was built using the Ruby on Rails framework with a heavy emphasis on object 
    oriented JavaScript to make AJAX requests to a RESTful back-end. Unlike most Rails 
    applications it does not use any inline JavaScript helpers nor does it rely on RJS 
    (Remote JavaScript) for dynamic page updates. Instead it is nearly 100% unobtrusive 
    JavaScript which uses simple HEAD or JSON responses to communicate to the objects on 
    the page. This has yielded very slim controller code which is decoupled from the 
    views and easily testable in isolation at a functional level.
  &lt;/div&gt;
&lt;/blockquote&gt;

&lt;p&gt;
  So what do I think of this implementation and writing all this object oriented JavaScript? Well – its been real hard, I've been in 
  JS Hell-OO for the better part of a few weeks as I came closer to finishing the project. Coming from a self inflicted addiction
  to unit/functional testing in rails, it is very hard to get into the habit of opening the browser to test view code. A big part of 
  me hates writing all this JS without one bit of unit testing. I've heard that Prototype v2 will have unit testing, that would be awesome! 
&lt;/p&gt;

&lt;div class=&quot;photobounding floatl mr20&quot;&gt;
  &lt;div class=&quot;tl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;tr&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;bl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;br&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;photoborder&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;phototime&quot;&gt;
    &lt;img src=&quot;/assets/2008/8/18/oojs.gif&quot; height=&quot;237&quot; alt=&quot;Hell'oo for HomeMarks&quot; width=&quot;384&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
  So, bitching aside, I am very happy that my JS-fu is stronger. The end result besides all those buckets of water up the hill is that 
  I can now really appreciate the ruby object model and how prototype strives to make JS class construction follow its example. Kudos 
  really goes to Sam Stephenson for bridging the two object models. As I learned more about how prototype's classes work, I actually 
  learned quite a bit about ruby too. Using that knowledge I gave a talk at the 
  &lt;a href=&quot;http://757rb.org/&quot; class=&quot;external-link&quot;&gt;Hampton Roads Ruby Users Group (757rb)&lt;/a&gt; on the topic. You can download the PDF 
  version of the slides &lt;a href=&quot;http://groups.google.com/group/757rb/files&quot;&gt; from the files section of the Google group&lt;/a&gt; page. 
  Look for the file titled &lt;em&gt;OO JavaScript Class Construction&lt;/em&gt;
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://metaskills.net/">
    <author>
      <name>kencollins</name>
    </author>
    <id>tag:metaskills.net,2008-07-06:163</id>
    <published>2008-07-06T19:14:00Z</published>
    <updated>2008-07-07T01:28:47Z</updated>
    <category term="Heuristics"/>
    <category term="Ruby/Rails"/>
    <category term="exceptions"/>
    <category term="rails"/>
    <category term="shotgun"/>
    <category term="zombie"/>
    <link href="http://metaskills.net/2008/7/6/stop-exception-notifications-with-the-zombieshotgun" rel="alternate" type="text/html"/>
    <title>Stop Exception Notifications With The ZombieShotgun</title>
<summary type="html">&lt;div class=&quot;photobounding floatl mr20&quot;&gt;
  &lt;div class=&quot;tl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;tr&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;bl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;br&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;photoborder&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;phototime&quot;&gt;
    &lt;img src=&quot;/assets/2008/7/6/zombie_shotgun.jpg&quot; height=&quot;213&quot; alt=&quot;Resident Evil Zombie Shotgun&quot; width=&quot;320&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p class=&quot;clearfix&quot;&gt;
  I am all about knowing how to survive a zombie invasion – as much as I am a firm believer of using the right tool for the a given job. It can not be argued that killing zombies with a shotgun to the head is as natural a fit as peanut butter to chocolate. They simply just go together. 
&lt;/p&gt;</summary><content type="html">
            &lt;div class=&quot;photobounding floatl mr20&quot;&gt;
  &lt;div class=&quot;tl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;tr&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;bl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;br&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;photoborder&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;phototime&quot;&gt;
    &lt;img src=&quot;/assets/2008/7/6/zombie_shotgun.jpg&quot; height=&quot;213&quot; alt=&quot;Resident Evil Zombie Shotgun&quot; width=&quot;320&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p class=&quot;clearfix&quot;&gt;
  I am all about knowing how to survive a zombie invasion – as much as I am a firm believer of using the right tool for the a given job. It can not be argued that killing zombies with a shotgun to the head is as natural a fit as peanut butter to chocolate. They simply just go together. 
&lt;/p&gt;
&lt;div class=&quot;photobounding floatl mr20&quot;&gt;
  &lt;div class=&quot;tl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;tr&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;bl&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;br&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;photoborder&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;phototime&quot;&gt;
    &lt;img src=&quot;/assets/2008/7/6/zombie_shotgun.jpg&quot; height=&quot;213&quot; alt=&quot;Resident Evil Zombie Shotgun&quot; width=&quot;320&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
  I am all about knowing how to survive a zombie invasion – as much as I am a firm believer of using the right tool for a given job. It can not be argued that killing zombies with a shotgun to the head is as natural a fit as peanut butter to chocolate. They simply just go together. 
&lt;/p&gt;

&lt;p&gt;
  Now real zombies may not be a daily nuisance, but 
  &lt;a href=&quot;http://en.wikipedia.org/wiki/Zombie_computer&quot; class=&quot;external-link&quot;&gt;computer zombies&lt;/a&gt; 
  are a daily pain in the butt to network administrators as well as software engineers alike. If you have 
  ever deployed a rails application into production that used some sort of exception notification, 
  then you may at some time seen some zombie attacks throw a bunch of exceptions. My solution a few 
  years back was to build my own ZombieShotgun module, see below.
&lt;/p&gt;

&lt;p&gt;
  The idea is simple, include the module and add this line to the very top of your filter chain 
  &lt;code&gt;before_filter :shoot_zombies&lt;/code&gt;. Just like in real life, if rails detects a zombie attack, 
  it will issue a 404 not found error in the beautiful rails syntax &lt;code&gt;head :not_found&lt;/code&gt;.
  I love it when code models the real world! Please note that there are a ton of better ways to 
  accomplish user agent filtering, most notably, in your web server config... but that does not mean 
  this is not a fun module to use.
&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;ZombieShotgun&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;co&quot;&gt;ZOMBIE_AGENTS&lt;/span&gt;       = [&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Microsoft Office Protocol Discovery&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;,&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Microsoft Data Access Internet Publishing Provider Protocol Discovery&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;,&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;FrontPage&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;co&quot;&gt;ZOMBIE_ATTACK_DIRS&lt;/span&gt;  = [&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;_vti_bin&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;,&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;MSOffice&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;,&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;verify-VCNstrict&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;,&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;notified-VCNstrict&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  protected&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;shoot_zombies&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    head &lt;span class=&quot;sy&quot;&gt;:not_found&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; zombie_attack?&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;zombie_attack?&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    zombie_attack_on_directory? || zombie_agent_attack?&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;zombie_attack_on_directory?&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    attack = request.path.from(&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    attack_dir = attack.index(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;).nil? ? attack : attack.to(attack.index(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;span class=&quot;i&quot;&gt;-1&lt;/span&gt;)    &lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;co&quot;&gt;ZOMBIE_ATTACK_DIRS&lt;/span&gt;.include?(attack_dir)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;zombie_agent_attack?&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    ua = request.env[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;HTTP_USER_AGENT&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;    !ua.blank? &amp;amp;&amp;amp; &lt;span class=&quot;co&quot;&gt;ZOMBIE_AGENTS&lt;/span&gt;.any? { |za| za =~ &lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;ua&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
          </content>  </entry>
  <entry xml:base="http://metaskills.net/">
    <author>
      <name>kencollins</name>
    </author>
    <id>tag:metaskills.net,2008-06-18:156</id>
    <published>2008-06-18T02:41:00Z</published>
    <updated>2008-06-18T15:50:02Z</updated>
    <category term="Heuristics"/>
    <category term="Ruby/Rails"/>
    <category term="ajax"/>
    <category term="csrf"/>
    <category term="javascript"/>
    <category term="rails"/>
    <category term="rest"/>
    <link href="http://metaskills.net/2008/6/18/restful-ajax-with-forgery-protection" rel="alternate" type="text/html"/>
    <title>RESTful AJAX with Forgery Protection</title>
<summary type="html">&lt;p&gt;
  Writing the new &lt;a href=&quot;http://www.homemarks.com/&quot; class=&quot;external-link&quot;&gt;HomeMarks&lt;/a&gt; has been a great exercise. I've learned that the &lt;a href=&quot;/2008/5/24/the-ajax-head-br-design-pattern&quot;&gt;&lt;em&gt;AJAX Head &amp;lt;strike&gt;Design Pattern&amp;lt;/strike&gt; Implementation&lt;/em&gt;&lt;/a&gt; is more akin to developing a service-oriented application (SOA) since I have moved all client-side coupling from the controllers, like RJS, and only respond with HEAD or JSON data. Today I learned...&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;
  Writing the new &lt;a href=&quot;http://www.homemarks.com/&quot; class=&quot;external-link&quot;&gt;HomeMarks&lt;/a&gt; has been a great exercise. I've learned that the &lt;a href=&quot;/2008/5/24/the-ajax-head-br-design-pattern&quot;&gt;&lt;em&gt;AJAX Head &amp;lt;strike&gt;Design Pattern&amp;lt;/strike&gt; Implementation&lt;/em&gt;&lt;/a&gt; is more akin to developing a service-oriented application (SOA) since I have moved all client-side coupling from the controllers, like RJS, and only respond with HEAD or JSON data. Today I learned...&lt;/p&gt;
&lt;p&gt;
  Writing the new &lt;a href=&quot;http://www.homemarks.com/&quot; class=&quot;external-link&quot;&gt;HomeMarks&lt;/a&gt; has been a great exercise. I've learned that the &lt;a href=&quot;/2008/5/24/the-ajax-head-br-design-pattern&quot;&gt;&lt;em&gt;AJAX Head &amp;lt;strike&gt;Design Pattern&amp;lt;/strike&gt; Implementation&lt;/em&gt;&lt;/a&gt; is more akin to developing a service-oriented application (SOA) since I have moved all client-side coupling from the controllers, like RJS, and only respond with HEAD or JSON data. Today I learned about &lt;a href=&quot;http://halcyon.rubyforge.org/&quot; class=&quot;external-link&quot;&gt;Halcyon&lt;/a&gt; which is self described as a JSON web application framework built on Rack. If you take a look at their example, it looks a lot like HomeMarks v2, pretty cool!
&lt;/p&gt;

&lt;h3&gt;Getting To The Point&lt;/h3&gt;

&lt;p&gt;
  Last week I finally got around to doing the controller CRUD for the user's column objects. The core &lt;code&gt;homemarks/app.js&lt;/code&gt; JavaScript class contains the one (and only one) AJAX dispatcher/handler for the entire application. One problem that I ran into was how to continue to use forgery protection in rails to protect from CSRF attacks while relying solely on ad-hoc JavaScript requests to a RESTful back-end. I could have turned off &lt;a href=&quot;http://api.rubyonrails.com/classes/ActionController/RequestForgeryProtection/ClassMethods.html#M000300&quot; class=&quot;external-link&quot;&gt;&lt;code&gt;protect_from_forgery&lt;/code&gt;&lt;/a&gt; but that did not feel right. I wanted RESTful AJAX with forgery protection.
&lt;/p&gt;

&lt;h3&gt;My Solution&lt;/h3&gt;

&lt;p&gt;
  Since the HomeMarks v2 app has one AJAX dispatcher/handler for the entire app, all I had to do was to get the authenticity token into each and every request. It took a bit of digging in the rails source to find the methods I wanted but here both the ERB snippet I am using in my layout and the helper method found in my &lt;code&gt;application_helper.rb&lt;/code&gt; file.
&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;script&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;type&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;text/javascript&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;&amp;lt;%= auth_params_js_var %&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;auth_params_js_var&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;co&quot;&gt;RAILS_ENV&lt;/span&gt; == &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;%|&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;var authParams = $H({&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;request_forgery_protection_token&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;form_authenticity_token.inspect&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;});&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;|&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;p&gt;
  What does this do? It creates a JS variable called &lt;code&gt;authParams&lt;/code&gt; at the window level (right term?) that all other functions can use. That variable returns a JavaScript hash that will have a single key/value pair for the rails authenticity token, see below. Basically at this point all you have to do is merge this hash with your &lt;code&gt;parameters&lt;/code&gt; option for your AJAX object. You can reference the HomeMarks app.js file in the resources section if you want to see how I did this on my app, code snippet below too.
&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;  doAjaxRequest: &lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;(elmnt,finishMethod) {&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;c&quot;&gt;// ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; method = elmnt.method || &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;    new Ajax.Request(elmnt.action,{&lt;tt&gt;
&lt;/tt&gt;      onComplete: &lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;(request){&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.completeAjaxRequest(request);&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; (finishMethod) { finishMethod.&lt;span class=&quot;fu&quot;&gt;call&lt;/span&gt;(&lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;,request) };&lt;tt&gt;
&lt;/tt&gt;      }.bind(&lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;),&lt;tt&gt;
&lt;/tt&gt;      parameters: parameters.merge(authParams),&lt;tt&gt;
&lt;/tt&gt;      method: method&lt;tt&gt;
&lt;/tt&gt;    });&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;




&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul class=&quot;mt20&quot;&gt;
  &lt;li&gt;The Latest HomeMarks &lt;a href=&quot;http://github.com/metaskills/homemarks/tree/master/public/javascripts/homemarks/app.js&quot; class=&quot;external-link&quot;&gt;app.js&lt;/a&gt; Class. See doAjaxRequest() function.&lt;/li&gt;
&lt;/ul&gt;
          </content>  </entry>
  <entry xml:base="http://metaskills.net/">
    <author>
      <name>kencollins</name>
    </author>
    <id>tag:metaskills.net,2008-05-30:147</id>
    <published>2008-05-30T03:21:00Z</published>
    <updated>2008-05-30T12:44:55Z</updated>
    <category term="Heuristics"/>
    <category term="Ruby/Rails"/>
    <category term="Workflow"/>
    <category term="bdd"/>
    <category term="rails"/>
    <category term="shoulda"/>
    <category term="tdd"/>
    <category term="testing"/>
    <link href="http://metaskills.net/2008/5/30/coulda-shoulda-woulda" rel="alternate" type="text/html"/>
    <title>Coulda Shoulda Woulda</title>
<summary type="html">&lt;p&gt;
  It has been about 6 months now since I started using the &lt;a href=&quot;http://www.thoughtbot.com/projects/shoulda&quot; class=&quot;external-link&quot;&gt;Shoulda&lt;/a&gt; testing plugin as my BDD/TDD tool of choice. Unlike a lot of other people, I did not flock to the RSpec bandwaggon. Personally I think RSpec is horribly bloated a sledgehammer for a simple issue, the need to have test code organized with nested setups and context blocks.
&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;
  It has been about 6 months now since I started using the &lt;a href=&quot;http://www.thoughtbot.com/projects/shoulda&quot; class=&quot;external-link&quot;&gt;Shoulda&lt;/a&gt; testing plugin as my BDD/TDD tool of choice. Unlike a lot of other people, I did not flock to the RSpec bandwaggon. Personally I think RSpec is horribly bloated a sledgehammer for a simple issue, the need to have test code organized with nested setups and context blocks.
&lt;/p&gt;
&lt;p&gt;
  It has been about 6 months now since I started using the &lt;a href=&quot;http://www.thoughtbot.com/projects/shoulda&quot; class=&quot;external-link&quot;&gt;Shoulda&lt;/a&gt; testing plugin as my BDD/TDD tool of choice. Unlike a lot of other people, I did not flock to the RSpec bandwaggon. Personally I think RSpec is horribly bloated a sledgehammer for a simple issue, the need to have test code organized with nested setups and context blocks.
&lt;/p&gt;

&lt;p&gt;
  If you are new to Shoulda, I highly urge you to take a look at the &lt;a href=&quot;http://www.thoughtbot.com/projects/shoulda&quot; class=&quot;external-link&quot;&gt;Thoughbot project page&lt;/a&gt; for it. If you have the time take a look at some of their other projects, like Paperclip. These guys are really smart. If you really want to see how shoulda can sing, check out &lt;a href=&quot;http://mwrc2008.confreaks.com/12saleh.html&quot; class=&quot;external-link&quot;&gt;Tammer Saleh's presentation of it at the MountainWest RubyConf 2008&lt;/a&gt;. In that presentation he covers how you can extend Shoulda and write your own macros that generate additional tests. This is what my blog post is about.
&lt;/p&gt;


&lt;h2&gt;Sample Shoulda Macro For Functional Require Login&lt;/h2&gt;

&lt;p&gt;
  Here is a simple module that you might find for any restful authentication system. This would be included in your main &lt;code&gt;test_helper.rb&lt;/code&gt; file where it would add the normal login_as(user) method. The good part I want to point out is the &lt;code&gt;should_require_login(*actions)&lt;/code&gt; macro method that shows off a neat example of how you could use Shoulda in your functional tests at the class level.
&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;31&lt;tt&gt;
&lt;/tt&gt;32&lt;tt&gt;
&lt;/tt&gt;33&lt;tt&gt;
&lt;/tt&gt;34&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;AuthSystem&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;TestHelper&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.included(receiver)&lt;tt&gt;
&lt;/tt&gt;      receiver.extend &lt;span class=&quot;co&quot;&gt;ClassMethods&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      receiver.send &lt;span class=&quot;sy&quot;&gt;:include&lt;/span&gt;, &lt;span class=&quot;co&quot;&gt;InstanceMethods&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;ClassMethods&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;should_require_login&lt;/span&gt;(*actions)&lt;tt&gt;
&lt;/tt&gt;        actions.each &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |action|&lt;tt&gt;
&lt;/tt&gt;          should &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Require login for '&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;action&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;' action&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;            get(action)&lt;tt&gt;
&lt;/tt&gt;            assert_redirected_to(login_url)&lt;tt&gt;
&lt;/tt&gt;          &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;InstanceMethods&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;login_as&lt;/span&gt;(user)&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; u = users(user)&lt;tt&gt;
&lt;/tt&gt;          &lt;span class=&quot;iv&quot;&gt;@request&lt;/span&gt;.session[&lt;span class=&quot;sy&quot;&gt;:user_id&lt;/span&gt;] = u.id&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;p&gt;
  Here is how it would look in the controller functional test. These are all contrived examples, but I think it illustrates how Shoulda can be used and in general how you can make your own macros that test at a higher level.
&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;UsersControllerTest&lt;/span&gt; &amp;lt; &lt;span class=&quot;co&quot;&gt;ActionController&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;TestCase&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  should_require_login &lt;span class=&quot;sy&quot;&gt;:edit&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:update&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:etc&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
          </content>  </entry>
  <entry xml:base="http://metaskills.net/">
    <author>
      <name>kencollins</name>
    </author>
    <id>tag:metaskills.net,2008-05-24:136</id>
    <published>2008-05-24T20:00:00Z</published>
    <updated>2008-05-30T12:48:44Z</updated>
    <category term="Heuristics"/>
    <category term="Ruby/Rails"/>
    <category term="ajax"/>
    <category term="design"/>
    <category term="javascript"/>
    <category term="pattern"/>
    <category term="unobtrusive"/>
    <link href="http://metaskills.net/2008/5/24/the-ajax-head-br-design-pattern" rel="alternate" type="text/html"/>
    <title>The "AJAX Head" Design Pattern</title>
<summary type="html">&lt;p&gt;
  This is the first of a few articles covering the total rewrite of the &lt;a href=&quot;http://homemarks.com/&quot; class=&quot;external-link&quot;&gt;HomeMarks.com&lt;/a&gt; code base as I upgrade it to Rails 2.1. The &quot;AJAX Head&quot; pattern is the moniker I have assigned to methodology that has come about during said rewrite and the design decisions I choose early on. The rules were simple...
&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;
  This is the first of a few articles covering the total rewrite of the &lt;a href=&quot;http://homemarks.com/&quot; class=&quot;external-link&quot;&gt;HomeMarks.com&lt;/a&gt; code base as I upgrade it to Rails 2.1. The &quot;AJAX Head&quot; pattern is the moniker I have assigned to methodology that has come about during said rewrite and the design decisions I choose early on. The rules were simple...
&lt;/p&gt;


&lt;p&gt;
  This is the first of a few articles covering the total rewrite of the &lt;a href=&quot;http://homemarks.com/&quot; class=&quot;external-link&quot;&gt;HomeMarks.com&lt;/a&gt; code base as I upgrade it to Rails 2.1. The &quot;AJAX Head&quot; pattern is the moniker I have assigned to methodology that has come about during said rewrite and the design decisions I choose early on. The rules were simple.
&lt;/p&gt;

&lt;ul class=&quot;mt20&quot;&gt;
  &lt;li&gt;Total Unobtrusive JavaScript (&lt;a href=&quot;http://en.wikipedia.org/wiki/Tag_soup&quot; class=&quot;external-link&quot;&gt;No Tag Soup&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;No RJS Controller Responses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  Rails makes it very easy to generate JavaScript with Ruby. The generator methods are extensive and cover both the Prototype and Scriptaculous libraries. The first version of HomeMarks used the generators exclusively to augment both the views and controller responses. In fact, I used a technique that is covered in the latest &lt;a href=&quot;http://www.pragprog.com/titles/fr_arr/advanced-rails-recipes&quot; class=&quot;external-link&quot;&gt;&lt;em&gt;Advanced Rails Recipes&lt;/em&gt;&lt;/a&gt; (way before it came out) under the &quot;Replace In-View Raw JavaScript&quot; chapter. Basically I created helper methods that generated JavaScript shared by both the views and controllers. It was a great technique but things &lt;a href=&quot;http://github.com/metaskills/homemarks/tree/d33dab1405537db2d2dab86d79db415d9e7f56e5/app/helpers/application_helper.rb&quot; class=&quot;external-link&quot;&gt;got messy quick&lt;/a&gt;. So life was good back then, I had a lot of Ruby code and a very dynamic site, but something did not seem right...
&lt;/p&gt;

&lt;h2&gt;What Is The AJAX Head Pattern?&lt;/h2&gt;

&lt;p&gt;
  It is an experiment into a vision to see what happens when you make the decision to totally go unobtrusive. Not just in your views but the controllers too! Imagine it this way &amp;mdash; your controllers are &lt;strong&gt;slim APIs&lt;/strong&gt;. They should do nothing but render a page on a GET request and when it comes to a POST/PUT/DELETE they should do nothing more than just say YES or NO (with errors).
&lt;/p&gt;

&lt;p&gt;
  Now lets think about that. What does that mean for an application that uses exclusive AJAX calls for dynamic page updates? It means that your visual client (the browser) will need to know ALOT less from the controller about what to do. It's great, the browser knows what is on the page, from the GET request, and what it needs to do with it. The client only needs to tell the remote resource store what it did. In this pattern the controller is relegated to nothing more than acting on model data and letting the client know if it succeeded or failed. So in short.
&lt;/p&gt;

&lt;blockquote&gt;
  &lt;div&gt;
    The AJAX head design pattern forces the view and controller to work in isolation with the most minimal coupling possible. Kind of like a web service.
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;h2&gt;Tools and Code Needed&lt;/h2&gt;

&lt;ul class=&quot;mt20&quot;&gt;
  &lt;li&gt;A application that does just about everything with AJAX.&lt;/li&gt;
  &lt;li&gt;Fluency with ActionController::Base#head method and HTTP status codes.&lt;/li&gt;
  &lt;li&gt;Site-wide exception rescues for ActiveRecord::RecordInvalid.&lt;/li&gt;
  &lt;li&gt;Global client-side AJAX request and response handlers.&lt;/li&gt;
  &lt;li&gt;Global client-side error handlers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  This may seem like a daunting list, but its pretty simple when you break it down. Let's do each one at at time with some of the current code from HomeMarks. The HomeMarks app is my first check on the list. When I did this app just about EVERYTHING was done via an AJAX call to update the page. Now on to the others.
&lt;/p&gt;


&lt;h2&gt;2) Head And Status Codes&lt;/h2&gt;

&lt;p&gt;
  The &lt;a href=&quot;http://api.rubyonrails.com/classes/ActionController/Base.html#M000454&quot; class=&quot;external-link&quot;&gt;ActionController::Base#head&lt;/a&gt; method and &lt;a href=&quot;http://dev.rubyonrails.org/browser/trunk/actionpack/lib/action_controller/status_codes.rb&quot; class=&quot;external-link&quot;&gt;HTTP status codes&lt;/a&gt; are the second item on the list. The head method is very useful when you just want to respond with HTTP headers and no body content. This is typical behavior when an app responds to external web services requests. This is important to note, I chose to rely on head responses as a way to meet my design decision of not using any RJS responses from the controller.
&lt;/p&gt;
  
  
&lt;p&gt;
  The basic usage of the head method is simple, you just pass a symbol to the head method that is the lowercase underscore equivalent to an HTTP status code. For instance, if you wanted to respond with success, choose a status code from the 200 range, the easiest being 'OK', which would look like &lt;code&gt;head(:ok)&lt;/code&gt;. If you wanted to respond to bad authentication, you might use the 401 code like so, &lt;code&gt;head(:unauthorized)&lt;/code&gt;. Here is an example from HomeMarks restful user signup action.
&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;UsersController&lt;/span&gt; &amp;lt; &lt;span class=&quot;co&quot;&gt;ApplicationController&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;create&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;co&quot;&gt;User&lt;/span&gt;.create!(params[&lt;span class=&quot;sy&quot;&gt;:user&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;    head &lt;span class=&quot;sy&quot;&gt;:ok&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;p&gt;
  There is actually a number of things going on in those 2 lines of code above. If the user is created, the AJAX request will get a simple 'OK' message via the head method. Obviously the client will need to know what to do on its own. But if errors happen what to do? This brings us to...
&lt;/p&gt;


&lt;h2&gt;3) Invalid Object Handling&lt;/h2&gt;

&lt;p&gt;
  When Rails 2 came out, it gave us a very useful tool for our controllers, the &lt;a href=&quot;http://api.rubyonrails.com/classes/ActionController/Rescue/ClassMethods.html&quot; class=&quot;external-link&quot;&gt;ActionController#rescue_from&lt;/a&gt; method. It allows you to delegate exception handling to a method either per controller or site wide for a specific exception class. So enter the &lt;a href=&quot;http://github.com/metaskills/homemarks/tree/master/lib/render_invalid_record.rb&quot; class=&quot;external-link&quot;&gt;RenderInvalidRecord&lt;/a&gt; module, show below.
&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;RenderInvalidRecord&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.included(base)&lt;tt&gt;
&lt;/tt&gt;    base.rescue_from(&lt;span class=&quot;co&quot;&gt;ActiveRecord&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;RecordInvalid&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:with&lt;/span&gt; =&amp;gt; &lt;span class=&quot;sy&quot;&gt;:render_invalid_record&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  protected&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;render_invalid_record&lt;/span&gt;(exception)&lt;tt&gt;
&lt;/tt&gt;    record = exception.record&lt;tt&gt;
&lt;/tt&gt;    respond_to &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |format|&lt;tt&gt;
&lt;/tt&gt;      format.html { render &lt;span class=&quot;sy&quot;&gt;:action&lt;/span&gt; =&amp;gt; (record.new_record? ? &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt; : &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;edit&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;) }&lt;tt&gt;
&lt;/tt&gt;      format.js   { render &lt;span class=&quot;sy&quot;&gt;:json&lt;/span&gt; =&amp;gt; record.errors.full_messages, &lt;span class=&quot;sy&quot;&gt;:status&lt;/span&gt; =&amp;gt; &lt;span class=&quot;sy&quot;&gt;:unprocessable_entity&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:content_type&lt;/span&gt; =&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;application/json&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;      format.xml  { render &lt;span class=&quot;sy&quot;&gt;:xml&lt;/span&gt; =&amp;gt; record.errors.full_messages,  &lt;span class=&quot;sy&quot;&gt;:status&lt;/span&gt; =&amp;gt; &lt;span class=&quot;sy&quot;&gt;:unprocessable_entity&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;      format.json { render &lt;span class=&quot;sy&quot;&gt;:json&lt;/span&gt; =&amp;gt; record.errors.full_messages, &lt;span class=&quot;sy&quot;&gt;:status&lt;/span&gt; =&amp;gt; &lt;span class=&quot;sy&quot;&gt;:unprocessable_entity&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;p&gt;
  Once included in your application.rb file, every ActiveRecord::RecordInvalid exception will be handled by the render_invalid_record method. I use this pattern often and it is the primary reason I always use the &lt;strong&gt;bang methods&lt;/strong&gt; that end with an exclamation point, such as &lt;code&gt;create!&lt;/code&gt; or &lt;code&gt;save!&lt;/code&gt;. This module above was inspired by &lt;a href=&quot;http://github.com/josh/&quot; class=&quot;external-link&quot;&gt;Joshua Peek's&lt;/a&gt; own module of the same name but has been edited here to fit my needs. Both the &quot;xml&quot; and &quot;html&quot; response formats are not used by HomeMarks but are included here to show how this module can work for any request type.
&lt;/p&gt;

&lt;p&gt;
  Now, how this fits into the AJAX Head pattern. The design decision of not having RJS responses means one of two things needs to come from the response. First, if the response is a success, meaning in the 200 range, then it is assumed that the client only needs to know that all is 'OK'. Second, if the request has errors, then the response needs to communicate them. I choose JSON for the format of these errors since all AJAX request objects from Prototype automatically include a &lt;code&gt;application/json&lt;/code&gt; accept header. So that is why I changed both the &quot;js&quot; and the &quot;json&quot; response type in the RenderInvalidRecord module to both serialize the objects full error messages into a JSON array with an HTTP status code of 422 &quot;Unprocessable Entity&quot; which seemed to make the most sense to me. This pretty much wraps up the server side part of the pattern. Now onto the client side. Everything from here on is personal taste on how your client will react to an &quot;good&quot; or &quot;bad&quot; response object.
&lt;/p&gt;


&lt;h2&gt;4) Client-Side AJAX Handlers&lt;/h2&gt;

&lt;p&gt;
  I can not stress enough how much you have to bake your own functions to handle the client side reaction to both good and bad AJAX responses. The client's ability to know what to do with errors will be tightly coupled to AJAX handlers and the design choices of your site. In the examples below I have broken up methods in the same JavaScript classes to show you the parts for a specific behavior in a more concise manner. Also please note that I am using Prototype module and class organization heavily in HomeMarks. This allows me to build a Base JavaScript module and classes that mimic Rails models which inherit/mixin Base methods. I also use the Scriptaculous Builder class for creating DOM fragments too. Now back to business.
&lt;/p&gt;

&lt;p&gt;
  &lt;a href=&quot;http://metaskills.net/files/homemarksv2/signup.html&quot; title=&quot;HomeMarks v2 Signup&quot;&gt;&lt;img class=&quot;floatr&quot; src=&quot;http://metaskills.net/files/homemarksv2/preview_signup2.png&quot; height=&quot;251&quot; width=&quot;246&quot;&gt;&lt;/a&gt;The first part of the AJAX head pattern was to use unobtrusive JavaScript. Because of this design choice, there are no &lt;code&gt;remote_form_for&lt;/code&gt; methods in the HomeMarks view code. All forms are simple &lt;code&gt;form_for&lt;/code&gt; methods. Below is a sample of the HomeMarksSite JavaScript class that creates AJAX handlers for all site forms. The below example is slimmed down to only show the initialization of this behavior for the signup form. But no matter which form is given this behavior the process is the same.
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The form's submit event is handled by &lt;code&gt;startAjaxForm()&lt;/code&gt;. It does the following:&lt;/li&gt;
    &lt;ul&gt;
      &lt;li&gt;Stops the normal submit behavior.&lt;/li&gt;
      &lt;li&gt;Adds a loading spinner in the #form_loading span.&lt;/li&gt;
      &lt;li&gt;Creates a new AJAX.Request using the forms own action. It also binds a function to delegate the logic of completing the form when the request is finished. More on that later in #2 below.&lt;/li&gt;
      &lt;li&gt;Finally it disables the form.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;li&gt;Once a response comes back from the server, the &lt;code&gt;delegateCompleteAjaxForm()&lt;/code&gt; function will be called with both the form object and the AJAX request object. The logic of this function includes:&lt;/li&gt;
  &lt;ul&gt;
    &lt;li&gt;Figuring out the &quot;mood&quot; of the request using getRequestMood() function which is part of my base module.&lt;/li&gt;
    &lt;li&gt;Sends the form and mood to the &lt;code&gt;completeAjaxForm()&lt;/code&gt; function. This function will replace the loading spinner with an image that reflects a good or bad response.&lt;/li&gt;
    &lt;li&gt;If the mood is good, meaning the response status code was within a 200 range, then the function will delegate to a function specific for that forms success using a simple case statement.&lt;/li&gt;
    &lt;li&gt;If this mood is bad, meaning the response status code not within a 200 range, the form will be enabled and the response JSON errors will be displayed. Currently I am using a modal class for this. Again more on that later. You may also note that my base module has a function called &lt;code&gt;messagesToList()&lt;/code&gt; that process the response into a DOM &amp;lt;ul&amp;gt; list.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/ul&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;31&lt;tt&gt;
&lt;/tt&gt;32&lt;tt&gt;
&lt;/tt&gt;33&lt;tt&gt;
&lt;/tt&gt;34&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;35&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;36&lt;tt&gt;
&lt;/tt&gt;37&lt;tt&gt;
&lt;/tt&gt;38&lt;tt&gt;
&lt;/tt&gt;39&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;40&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;41&lt;tt&gt;
&lt;/tt&gt;42&lt;tt&gt;
&lt;/tt&gt;43&lt;tt&gt;
&lt;/tt&gt;44&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;45&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;46&lt;tt&gt;
&lt;/tt&gt;47&lt;tt&gt;
&lt;/tt&gt;48&lt;tt&gt;
&lt;/tt&gt;49&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;50&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;51&lt;tt&gt;
&lt;/tt&gt;52&lt;tt&gt;
&lt;/tt&gt;53&lt;tt&gt;
&lt;/tt&gt;54&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;55&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;56&lt;tt&gt;
&lt;/tt&gt;57&lt;tt&gt;
&lt;/tt&gt;58&lt;tt&gt;
&lt;/tt&gt;59&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;60&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;61&lt;tt&gt;
&lt;/tt&gt;62&lt;tt&gt;
&lt;/tt&gt;63&lt;tt&gt;
&lt;/tt&gt;64&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;65&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;66&lt;tt&gt;
&lt;/tt&gt;67&lt;tt&gt;
&lt;/tt&gt;68&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; HomeMarksBase = {&lt;tt&gt;
&lt;/tt&gt;  getRequestMood: &lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;(request) {&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;return&lt;/span&gt; (request.status &amp;gt;= 200 &amp;amp;&amp;amp; request.status &amp;lt; 300) ? &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;good&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt; : &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;bad&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;  },&lt;tt&gt;
&lt;/tt&gt;  messagesToList: &lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;(request) {&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; messages = request.responseJSON;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; messageList = UL();&lt;tt&gt;
&lt;/tt&gt;    messages.each(&lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;(message){ &lt;tt&gt;
&lt;/tt&gt;      messageList.appendChild( LI(message.escapeHTML()) );&lt;tt&gt;
&lt;/tt&gt;    });&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;return&lt;/span&gt; messageList;&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;};&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; HomeMarksSite = Class.create(HomeMarksBase,{ &lt;tt&gt;
&lt;/tt&gt;  initialize: &lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;() {&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.signupForm = $(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;signup_form&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.initEvents();&lt;tt&gt;
&lt;/tt&gt;  },&lt;tt&gt;
&lt;/tt&gt;  startAjaxForm: &lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;(&lt;span class=&quot;pt&quot;&gt;event&lt;/span&gt;) {&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;pt&quot;&gt;event&lt;/span&gt;.&lt;span class=&quot;fu&quot;&gt;stop&lt;/span&gt;();&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; form = &lt;span class=&quot;pt&quot;&gt;event&lt;/span&gt;.findElement(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; options = &lt;span class=&quot;pt&quot;&gt;Object&lt;/span&gt;.extend({imgSrc:&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;loading_invert.gif&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;}, arguments[1] || {});&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; loadArea = form.down(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;#form_loading&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; imgTag = IMG({src:(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/images/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;+options.imgSrc)});&lt;tt&gt;
&lt;/tt&gt;    $(loadArea).update(imgTag);&lt;tt&gt;
&lt;/tt&gt;    new Ajax.Request(form.action,{&lt;tt&gt;
&lt;/tt&gt;      onComplete: &lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;(request){ &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.delegateCompleteAjaxForm(form,request) }.bind(&lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;),&lt;tt&gt;
&lt;/tt&gt;      parameters: form.serialize(&lt;span class=&quot;pc&quot;&gt;true&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    });&lt;tt&gt;
&lt;/tt&gt;    form.disable();&lt;tt&gt;
&lt;/tt&gt;  },&lt;tt&gt;
&lt;/tt&gt;  delegateCompleteAjaxForm: &lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;(form,request) {&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; mood = &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.getRequestMood(request);&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.completeAjaxForm(form,{mood:mood});&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; (mood == &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;good&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;) { &lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;switch&lt;/span&gt; (form) { &lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;r&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.supportForm : &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.completeSupportForm(request); &lt;span class=&quot;r&quot;&gt;break&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;      }&lt;tt&gt;
&lt;/tt&gt;    }&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;else&lt;/span&gt; { &lt;tt&gt;
&lt;/tt&gt;      form.enable();&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; (!request.responseText.blank()) {&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; flashHTML = DIV([H2(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Errors On Form!&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;),&lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.messagesToList(request)]);&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.flashModal(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;bad&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;,flashHTML);&lt;tt&gt;
&lt;/tt&gt;      };&lt;tt&gt;
&lt;/tt&gt;    };&lt;tt&gt;
&lt;/tt&gt;  },&lt;tt&gt;
&lt;/tt&gt;  completeAjaxForm: &lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;(form) {&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; options = &lt;span class=&quot;pt&quot;&gt;Object&lt;/span&gt;.extend({mood:&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;good&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;}, arguments[1] || {});&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; loadArea = form.down(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;#form_loading&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; completeId = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;complete_ajax_form_&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt; + form.id;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; imgSrc = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/images/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;+options.mood+&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;.png&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; moodHtml = SPAN({id:completeId,className:&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;m0 p0&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;}, [IMG({src:imgSrc})]);&lt;tt&gt;
&lt;/tt&gt;    $(loadArea).update(moodHtml);&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;fu&quot;&gt;setTimeout&lt;/span&gt;(&lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;() { $(completeId).fade(); },3000);&lt;tt&gt;
&lt;/tt&gt;  },&lt;tt&gt;
&lt;/tt&gt;  completeSignupForm: &lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;(request) {&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; message = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Thank your for signing up for your own HomeMarks page. An email has been sent to &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; +&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;your address along with a link to activate your account. If you have not done so already, please &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; +&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;take a moment to read the HomeMarks documentation.&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; flashHTML = DIV([H2(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Signup Complete:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;),P(message)]);&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.flash(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;good&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;,flashHTML);&lt;tt&gt;
&lt;/tt&gt;  },&lt;tt&gt;
&lt;/tt&gt;  initEvents: &lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;() {&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.signupForm) { &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.signupForm.observe(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;submit&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.startAjaxForm.bindAsEventListener(&lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;)); };&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;});&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;



&lt;h2&gt;5) Client-Side Error Handling&lt;/h2&gt;

&lt;p&gt;
  Currently I have 3 client-side options that I can use to present errors back to the user from the JSON array in AJAX response. The first I started out with was using the &lt;code&gt;alert()&lt;/code&gt; function. That got boring real quick, but I left my implementation below which is part of the base class, called &lt;code&gt;messagesToAlert()&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
  The second slightly more interesting way was to create a flash message that used the same XHTML/CSS already present in my layout file. This was real easy to implement. Basically using the ERB fragment below in my layout, I guaranteed that I had 3 unique DOM elements for each of my flash message styles, good/bad/indif. Now all I had to do was to create an accessor in my HomeMarksSite class. I choose &lt;code&gt;this.flashes&lt;/code&gt;. I then created a &lt;code&gt;clearFlashes()&lt;/code&gt; function and then a &lt;code&gt;flash()&lt;/code&gt; function that would take the mood and the HTML to embed, viola – I can now call &lt;code&gt;this.flash.('good',someHTML)&lt;/code&gt; and I get the same type of flash one would have seen if I set it in the controller and rendered. Note, this is what I used on the the signup form success above.
&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;lt;% [&lt;span class=&quot;sy&quot;&gt;:good&lt;/span&gt;,&lt;span class=&quot;sy&quot;&gt;:bad&lt;/span&gt;,&lt;span class=&quot;sy&quot;&gt;:indif&lt;/span&gt;].each &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |key| &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&lt;tt&gt;
&lt;/tt&gt;  &amp;lt;div id=&amp;quot;flash_&amp;lt;%= key %&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; class=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;flash_message&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; style=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;display&lt;span class=&quot;sy&quot;&gt;:&amp;lt;&lt;/span&gt;%= flash[key].blank? ? &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt; : &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;;&amp;quot;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &amp;lt;span&amp;gt;&amp;lt;%= flash[key] &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;lt;/span&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &amp;lt;&lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;div&amp;gt;&lt;tt&gt;
&lt;/tt&gt;&amp;lt;% end %&amp;gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;br /&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;31&lt;tt&gt;
&lt;/tt&gt;32&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; HomeMarksBase = {&lt;tt&gt;
&lt;/tt&gt;  messagesToAlert: &lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;(request) {&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; messages = request.responseJSON;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; alertText = messages.&lt;span class=&quot;fu&quot;&gt;join&lt;/span&gt;(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;.\n&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; (alertText.endsWith(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)) { &lt;span class=&quot;fu&quot;&gt;alert&lt;/span&gt;(alertText); } &lt;span class=&quot;r&quot;&gt;else&lt;/span&gt; { &lt;span class=&quot;fu&quot;&gt;alert&lt;/span&gt;(alertText+&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;); };&lt;tt&gt;
&lt;/tt&gt;  },&lt;tt&gt;
&lt;/tt&gt;  messagesToList: &lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;(request) {&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; messages = request.responseJSON;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; messageList = UL();&lt;tt&gt;
&lt;/tt&gt;    messages.each(&lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;(message){ &lt;tt&gt;
&lt;/tt&gt;      messageList.appendChild( LI(message.escapeHTML()) );&lt;tt&gt;
&lt;/tt&gt;    });&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;return&lt;/span&gt; messageList;&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;};&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; HomeMarksSite = Class.create(HomeMarksBase,{ &lt;tt&gt;
&lt;/tt&gt;  initialize: &lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;() {&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.flashes = $$(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;div.flash_message&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;  },&lt;tt&gt;
&lt;/tt&gt;  clearFlashes: &lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;() {&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.flashes.invoke(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;hide&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.flashes.invoke(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;,&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;  },&lt;tt&gt;
&lt;/tt&gt;  flash: &lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;(mood,html) {&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.clearFlashes();&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; moodFlash = &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.flashes.&lt;span class=&quot;fu&quot;&gt;find&lt;/span&gt;(&lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;(e){ &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; (e.id == &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;flash_&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;+mood) {&lt;span class=&quot;r&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;pc&quot;&gt;true&lt;/span&gt;}; });&lt;tt&gt;
&lt;/tt&gt;    moodFlash.update(html);&lt;tt&gt;
&lt;/tt&gt;    moodFlash.show();&lt;tt&gt;
&lt;/tt&gt;    $(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;site_wrapper&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;).&lt;span class=&quot;fu&quot;&gt;scrollTo&lt;/span&gt;();&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;});&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;p&gt;
  &lt;a href=&quot;http://metaskills.net/files/homemarksv2/login.html&quot; title=&quot;HomeMarks v2 Login&quot;&gt;&lt;img class=&quot;floatr&quot; src=&quot;http://metaskills.net/files/homemarksv2/preview_login2.png&quot; height=&quot;251&quot; width=&quot;246&quot;&gt;&lt;/a&gt;Lastly, and probably the coolest, is the HomeMarksModal JavaScript class I created. This is my new default way of errors to a user. It can be seen in all my video examples on this page. To the right is another example of the login form that uses the same handlers described above. The HomeMarksModal JavaScript class is a bit large to paste inline in this article, but if you want to see the latest version, you can always get it &lt;a href=&quot;http://github.com/metaskills/homemarks/tree/master/public/javascripts/homemarks/modal.js&quot; class=&quot;external-link&quot;&gt;from the master branch of the homemarks_core project&lt;/a&gt; on Github.com. When you bind an instance of this object to the window/document, it will automatically crate the modal HTML using Builder. If you want to use it, make sure to get the CSS and images the project too. Below is a function that I put in my site class that allows me to call &lt;code&gt;this.flashModal('good',someHTML))&lt;/code&gt;.
&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; HomeMarksSite = Class.create(HomeMarksBase,{ &lt;tt&gt;
&lt;/tt&gt;  flashModal: &lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;(mood,html) {&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; moodColor = &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.flashMoodColors.get(mood);&lt;tt&gt;
&lt;/tt&gt;    HmModal.show(html,{color:moodColor});&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;});&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;



&lt;h2&gt;Wrapping It Up&lt;/h2&gt;

&lt;p&gt;
  This article turned out a lot longer than I had wanted. The AJAX head pattern is pretty simple and it is really fun to see a two line user signup action yield such interactive results. Something also feels good about not putting view code in the controller, yes you can look at inline RJS as view code. Sure it requires that you do a lot more JS work, but there are benefits.
&lt;/p&gt;

&lt;p&gt;
  Image you have team of programmers, one person can stay in model/controller land while the other stays on the view/javascript. The model/controller person would write their own tests (PLEASE TAKE A LOOK AT MINE), while the view/javascript person might even take the initiative to use selenium to test the JavaScript. At the time of this writing, I have not done any selenium tests since the plugin for rails is not compatible for 2.0. That last benefit I could think of for this design pattern is that you could easily update view code without restarting your rails app. Just update the JavaScripts and your good to go.
&lt;/p&gt;

&lt;p&gt;
  In closing, please let me know what you think. Perhaps you have a better name for the design pattern? Perhaps someone else has a name for it already?
&lt;/p&gt;



&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul class=&quot;mt20&quot;&gt;
  &lt;li&gt;Original &lt;a href=&quot;http://github.com/metaskills/homemarks/tree/d33dab1405537db2d2dab86d79db415d9e7f56e5/app/helpers/application_helper.rb&quot; class=&quot;external-link&quot;&gt;application_helper.rb&lt;/a&gt; from HomeMarks v1. An overboard example of shared view/controller tagsoup/rjs.&lt;/li&gt;
  &lt;li&gt;The latest &lt;a href=&quot;http://www.pragprog.com/titles/fr_arr/advanced-rails-recipes&quot; class=&quot;external-link&quot;&gt;&lt;em&gt;Advanced Rails Recipes&lt;/em&gt;&lt;/a&gt; book. See the chapter on &quot;Replace In-View Raw JavaScript&quot;. I discourage this technique used in mass.&lt;/li&gt;
  &lt;li&gt;Rails API for the &lt;a href=&quot;http://api.rubyonrails.com/classes/ActionController/Base.html#M000454&quot; class=&quot;external-link&quot;&gt;ActionController::Base#head&lt;/a&gt; method.&lt;/li&gt;
  &lt;li&gt;Rails API for the &lt;a href=&quot;http://dev.rubyonrails.org/browser/trunk/actionpack/lib/action_controller/status_codes.rb&quot; class=&quot;external-link&quot;&gt;HTTP status codes&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Rails API for the &lt;a href=&quot;http://api.rubyonrails.com/classes/ActionController/Rescue/ClassMethods.html&quot; class=&quot;external-link&quot;&gt;ActionController#rescue_from&lt;/a&gt; method.&lt;/li&gt;
  &lt;li&gt;The latest &lt;a href=&quot;http://github.com/metaskills/homemarks/tree/master/lib/render_invalid_record.rb&quot; class=&quot;external-link&quot;&gt;RenderInvalidRecord&lt;/a&gt; module from the HomeMarks core.&lt;/li&gt;
  &lt;li&gt;The latest  &lt;a href=&quot;http://github.com/metaskills/homemarks/tree/master/public/javascripts/homemarks/modal.js&quot; class=&quot;external-link&quot;&gt;HomeMarksModal&lt;/a&gt; JavaScript class from the HomeMarks core.&lt;/li&gt;
&lt;/ul&gt;
          </content>  </entry>
  <entry xml:base="http://metaskills.net/">
    <author>
      <name>kencollins</name>
    </author>
    <id>tag:metaskills.net,2008-04-25:132</id>
    <published>2008-04-25T14:34:00Z</published>
    <updated>2008-05-24T01:46:13Z</updated>
    <category term="Apple/OSX"/>
    <category term="Heuristics"/>
    <category term="Ruby/Rails"/>
    <category term="TextMate"/>
    <category term="apple"/>
    <category term="environment"/>
    <category term="path"/>
    <category term="ruby"/>
    <category term="rubyamp"/>
    <category term="textmate"/>
    <link href="http://metaskills.net/2008/4/25/using-rubyamp-textmate-bundle-with-opt-ruby" rel="alternate" type="text/html"/>
    <title>Using RubyAMP TextMate Bundle With /opt Ruby</title>
<summary type="html">&lt;p&gt;I've been a TextMate user for a long time now and I'm still finding new things to do with it. Here recently I wanted to use the &lt;a href=&quot;http://code.leadmediapartners.com/tools/rubyamp&quot; class=&quot;external-link&quot;&gt;RubyAMP TextMate Bundle&lt;/a&gt; and was a little miffed to find that it was pointing to my OS X system ruby. The error message looked something like this when it went looking for my ruby/gems.&lt;/p&gt;

&lt;pre&gt;
No such file to load -- appscript (LoadError) from 
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require’
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:27:in `require’
...
&lt;/pre&gt;</summary><content type="html">
            &lt;p&gt;I've been a TextMate user for a long time now and I'm still finding new things to do with it. Here recently I wanted to use the &lt;a href=&quot;http://code.leadmediapartners.com/tools/rubyamp&quot; class=&quot;external-link&quot;&gt;RubyAMP TextMate Bundle&lt;/a&gt; and was a little miffed to find that it was pointing to my OS X system ruby. The error message looked something like this when it went looking for my ruby/gems.&lt;/p&gt;

&lt;pre&gt;
No such file to load -- appscript (LoadError) from 
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require’
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:27:in `require’
...
&lt;/pre&gt;
&lt;p&gt;I've been a TextMate user for a long time now and I'm still finding new things to do with it. Here recently I wanted to use the &lt;a href=&quot;http://code.leadmediapartners.com/tools/rubyamp&quot; class=&quot;external-link&quot;&gt;RubyAMP TextMate Bundle&lt;/a&gt; and was a little miffed to find that it was pointing to my OS X system ruby. The error message looked something like this when it went looking for my ruby/gems.&lt;/p&gt;

&lt;pre&gt;
No such file to load -- appscript (LoadError) from 
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require’
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:27:in `require’
...
&lt;/pre&gt;

&lt;p&gt;My problem is that I use ruby installed from MacPorts (yes I have Leopard). I do this because I put a lot of crap and extra dependencies into my opt direcotry and I do not trust Apple to NOT blow away the crazy dependencey hell I would have ended up creating in the standard bin directories if I chose not to use MacPorts. I would have thought that my &lt;code&gt;TM_RUBY&lt;/code&gt; environment variable being set correctly to &lt;code&gt;/opt/local/bin/ruby&lt;/code&gt; in my TextMate preferences would have given RubyAMP enough info to find my correct gem environment. Obviously not... and it took me quite a bit of digging around to learn what else I needed to do. For starters, here is more than you ever wanted to know about &lt;a href=&quot;http://macromates.com/textmate/manual/shell_commands#search_path&quot; class=&quot;external-link&quot;&gt;how TextMate gets the $PATH information&lt;/a&gt;. You can skip reading that and do these simple steps.&lt;/p&gt;

&lt;ul class=&quot;mt10&quot;&gt;
&lt;li&gt;Open /Developer/Applications/Utilities/Property List Editor.app&lt;/li&gt;
&lt;li&gt;Click on &quot;New Root&quot;, now expand that node in the list view below.&lt;/li&gt;
&lt;li&gt;Click on &quot;New Child&quot;, name it PATH&lt;/li&gt;
&lt;li&gt;The child row for PATH should be a String type&lt;/li&gt;
&lt;li&gt;Enter your PATH info here, should mimic your .bash_profile, without $PATH&lt;/li&gt;
&lt;li&gt;Save this file to your Desktop as environment.plist&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now do this in the console, we need to move that file to an invisible &lt;code&gt;.MacOSX&lt;/code&gt; folder in your home directory. In all likelyhood this folder does not exists, nor does the environment.plist file inside of it, if so, please do your own work to make sure that you do not overwrite existing information. Now:&lt;/p&gt;

&lt;pre class=&quot;command&quot;&gt;
mkdir ~/.MacOSX
mv ~/Desktop/environment.plist ~/.MacOSX
&lt;/pre&gt;

&lt;p&gt;With the file in place, you now have to log out and back in. To be on the safe side, just reboot. Now your OSX apps, including TextMate and it's bundles will have the correct PATH information to get to your binaries. See below for an example of what my environment.plist file looks like. Note too that my full PATH info in that file is this string &lt;code&gt;/opt/local/bin:/opt/local/sbin:/opt/local/lib/mysql5/bin:/opt/local/apache2/bin&lt;/code&gt;. Notice that path info after the apache2 path? This is where you should add the default path info for a Mac. Unlike the .bash_profile, you can not specify &lt;code&gt;$PATH&lt;/code&gt; and have it expanded from within a plist file. So to be on the safe side, when I added this, I put the standard mac path info at the end of my own additions. That standard path info is &lt;code&gt;/usr/local/bin:/bin:/sbin:/usr/bin:/usr/sbin&lt;/code&gt;&lt;/p&gt;



&lt;div class=&quot;iecenter&quot;&gt;
  &lt;img src=&quot;http://www.metaskills.net/assets/2008/4/25/envplist.png&quot; height=&quot;302&quot; width=&quot;496&quot; /&gt;
&lt;/div&gt;
          </content> 