<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Kernow Soul Blog</title>
    <description>The blog of Jamie Dyer</description>
    <link>http://kernowsoul.com/blog</link>
    <item>
      <title>Introducing Scupper, the JavaScript library for easily dealing with HTML snippets in test suites</title>
      <description>&lt;p&gt;I came across a problem today while writing tests in JavaScript. The code I was testing required a snippet of &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; to work with. A user list needed to be reordered depending on their status. No problem I thought, I&amp;#8217;ll create div to store an &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; snippet, then before my test I&amp;#8217;ll duplicate and copy it into a test div.&lt;/p&gt;


&lt;pre&gt;&lt;code class='html'&gt;&amp;lt;div id=&quot;snippets&quot; style=&quot;display:none&quot;&amp;gt;
  &amp;lt;ul id=&quot;user-list-snippet&quot;&amp;gt;
    &amp;lt;li id=&quot;user-0&quot;&amp;gt;Shaun White&amp;lt;span class='user-0-status'&amp;gt;busy&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;
    &amp;lt;li id=&quot;user-1&quot;&amp;gt;Jeremy Jones&amp;lt;span class='user-1-status'&amp;gt;online&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;
    &amp;lt;li id=&quot;user-2&quot;&amp;gt;Jake Burton&amp;lt;span class='user-2-status'&amp;gt;offline&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;
    &amp;lt;li id=&quot;user-3&quot;&amp;gt;Tara Dakides&amp;lt;span class='user-3-status'&amp;gt;online&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;
  &amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;And the JavaScript to copy the element:&lt;/p&gt;


&lt;pre&gt;&lt;code class='javascript'&gt;$(&quot;#user-list-snippet&quot;).clone().removeAttr(&quot;id&quot;).attr(&quot;id&quot;, &quot;user-list&quot;).appendTo($('#dom_test'));&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Of course when working with id&amp;#8217;s in &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; they have to be unique so the technique caused some of the other tests in the suite to fail, I needed to find another way to do this. One thing I hate is using &lt;a href=&quot;http://jquery.com&quot;&gt;jQuery&lt;/a&gt; to create more than a few dom elements as it gets complex very quickly and it&amp;#8217;s not easy to see if the code is producing the desired &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; at a glance.&lt;/p&gt;


	&lt;p&gt;After taking a break I came up with a simple solution, the Scupper library was about to be written. I wanted to write snippets in &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; so I kept the snippet used in the first attempt. I then created a library that collected all of the snippets from the dom, storing them internally, before deleting them from the dom. This allowed the dom to be free from conflicting id&amp;#8217;s and general pollution. The &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; snippet became:&lt;/p&gt;


&lt;pre&gt;&lt;code class='html'&gt;&amp;lt;div id=&quot;snippets&quot; style=&quot;display:none&quot;&amp;gt;
  &amp;lt;div id=&quot;user-list-snippet&quot;&amp;gt;
    &amp;lt;ul id=&quot;user-list&quot;&amp;gt;
      &amp;lt;li id=&quot;user-0&quot;&amp;gt;Shaun White&amp;lt;span class='user-0-status'&amp;gt;busy&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;
      &amp;lt;li id=&quot;user-1&quot;&amp;gt;Jeremy Jones&amp;lt;span class='user-1-status'&amp;gt;online&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;
      &amp;lt;li id=&quot;user-2&quot;&amp;gt;Jake Burton&amp;lt;span class='user-2-status'&amp;gt;offline&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;
      &amp;lt;li id=&quot;user-3&quot;&amp;gt;Tara Dakides&amp;lt;span class='user-3-status'&amp;gt;online&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;
    &amp;lt;/ul&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The containing div #user-list-snippet give an element to latch onto in order to grab whats inside. I created a method that sucks up all snippets inside a dom element and stores them:&lt;/p&gt;


&lt;pre&gt;&lt;code class='javascript'&gt;init: function(element_id){
  var element = $('#' + element_id);
  element.children().each(function(i, elm){
    elm = $(elm);
    Scupper.items[elm.attr('id')] = elm.html();
  });
  element.empty();
}&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The all that was needed is an easy way to pull them out an inset them into the dom:&lt;/p&gt;


&lt;pre&gt;&lt;code class='javascript'&gt;insert_into: function(source_id, destination_id){
  return $('#' + destination_id).append(Scupper.retrieve(source_id));
},

retrieve: function(id){
  if(Scupper.items[id] !== undefined){
    return Scupper.items[id];
  }else{
    throw &quot;Requested Scupper element not found with id: &quot; + id;
  }
}&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Calling insert_into() grabs the snippet &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; and inserts it into the specified dom element ready for the test to use it.&lt;/p&gt;


	&lt;p&gt;If you want to use Scupper the source is &lt;a href=&quot;http://github.com/kernow/Scupper/&quot;&gt;freely available on github&lt;/a&gt;.&lt;/p&gt;</description>
      <pubDate>Wed, 06 Jan 2010 17:34:25 +0000</pubDate>
      <link>http://kernowsoul.com/blog/2010/01/06/introducing-scupper-the-javascript-library-for-easily-dealing-with-html-snippets-in-test-suites</link>
      <guid>http://kernowsoul.com/blog/2010/01/06/introducing-scupper-the-javascript-library-for-easily-dealing-with-html-snippets-in-test-suites</guid>
    </item>
    <item>
      <title>Shoulda macro should_render_a_form_to</title>
      <description>&lt;p&gt;I&amp;#8217;ve been writing a fair number of functional tests recently, one thing that kept cropping up was the need to check if a form had been rendered and that it was going to perform a particular action. Shoulda has a should_render_a_form macro, unfortunately it&amp;#8217;s been depreciated and doesn&amp;#8217;t do anything other than check a form element has been rendered in the view.&lt;/p&gt;


	&lt;p&gt;I decided to come up with my own macro that checks the specifics of a form element, enter should_render_a_form_to. This takes tree arguments, a description, an options hash and a block that contains the expected url. You would use the macro as follows&amp;#8230;&lt;/p&gt;


Check there is a form posting to the new_user_post_path:
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;should_render_a_form_to(&quot;create a new post&quot;, {:method =&amp;gt; &quot;post&quot;}) { new_user_post_path(@user.id) }&lt;/code&gt;&lt;/pre&gt;

Check there is a form putting to the user_post_path and that the form has the id of &amp;#8216;post_edit_form&amp;#8217;:
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;should_render_a_form_to(&quot;update a post&quot;, {:method =&amp;gt; &quot;put&quot;, :id =&amp;gt; &quot;post_edit_form&quot;}) { user_post_path( :user_id =&amp;gt; @user.id, :id =&amp;gt; 1) }&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The macro code is available on &lt;a href=&quot;http://github.com/kernow/shoulda/tree/form_macro&quot;&gt;github&lt;/a&gt; with test coverage. If you just want to cut and paste into your own macro&amp;#8217;s file:&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;def should_render_a_form_to(description, options = {}, &amp;#38;block)
  should &quot;render a form to #{description}&quot; do
    expected_url  = instance_eval(&amp;#38;block)
    form_method   = case options[:method]
      when &quot;post&quot;, &quot;put&quot;, &quot;delete&quot; : &quot;post&quot; 
      else &quot;get&quot; 
      end
    assert_select &quot;form[action=?][method=?]&quot;,
                  expected_url,
                  form_method,
                  true,
                  &quot;The template doesn't contain a &amp;lt;form&amp;gt; element with the action #{expected_url}&quot; do |elms|

      if options[:id]
        elms.each do |elm|
          assert_select elm,
                        &quot;##{options[:id]}&quot;,
                        true,
                        &quot;The template doesn't contain a &amp;lt;form&amp;gt; element with the id #{options[:id]}&quot; 
        end
      end

      unless %w{get post}.include? options[:method]
        assert_select &quot;input[name=_method][value=?]&quot;,
                      options[:method],
                      true,
                      &quot;The template doesn't contain a &amp;lt;form&amp;gt; for #{expected_url} using the method #{options[:method]}&quot; 
      end
    end
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The macro checks for both the forms action attribute as well as the hidden input rails uses to specify the method where necessary. I&amp;#8217;ve also been playing with creating a macro to check for a form with specific fields such as should_render_a_form_with_fields. This is proving to be slightly more difficult than I originally anticipated and defining a nice interface to the method has been rather tricky.&lt;/p&gt;</description>
      <pubDate>Wed, 07 Oct 2009 17:21:39 +0000</pubDate>
      <link>http://kernowsoul.com/blog/2009/10/07/shoulda-macro-shouldrenderaformto</link>
      <guid>http://kernowsoul.com/blog/2009/10/07/shoulda-macro-shouldrenderaformto</guid>
    </item>
    <item>
      <title>Vlad the Deployer Hoptoad Integration</title>
      <description>&lt;p&gt;I&amp;#8217;ve just had to setup &lt;a href=&quot;http://hoptoadapp.com&quot;&gt;Hoptoad&lt;/a&gt; for one of our apps that uses &lt;a href=&quot;http://rubyhitsquad.com/Vlad_the_Deployer.html&quot;&gt;Vlad&lt;/a&gt; for deployment, the integration isn&amp;#8217;t quite as easy as with &lt;a href=&quot;http://www.capify.org&quot;&gt;Capistrano&lt;/a&gt;. I couldn&amp;#8217;t find much information on how to integrate the two so I thought I&amp;#8217;d share my solution.&lt;/p&gt;


	&lt;p&gt;The original Hoptaod task for use with Capistrano needed a little modification.&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;task :notify_hoptoad do
  rails_env = fetch(:rails_env, &quot;production&quot;)
  local_user = ENV['USER'] || ENV['USERNAME']
  notify_command = &quot;rake hoptoad:deploy TO=#{rails_env} REVISION=#{current_revision} REPO=#{repository} USER=#{local_user}&quot; 
  puts &quot;Notifying Hoptoad of Deploy (#{notify_command})&quot; 
  `#{notify_command}`
  puts &quot;Hoptoad Notification Complete.&quot; 
end
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;fetch is a Capistrano method so needed to be removed, we can use the &lt;a href=&quot;http://hitsquad.rubyforge.org/vlad/doco/getting_started_txt.html&quot;&gt;Vlad environment pattern&lt;/a&gt; for this. I also wanted to use the git information for the user instead of the system user, finally as far as I can tell the git commit &lt;span class=&quot;caps&quot;&gt;SHA&lt;/span&gt; being deployed is not available in Vlad.&lt;/p&gt;


	&lt;p&gt;In the Vlad deployment script I added a Hoptoad task to replace the default Capistrano task provided by Hoptoad.&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;task :notify_hoptoad =&amp;gt; [:git_user, :git_revision] do
  notify_command = &quot;rake hoptoad:deploy TO=#{rails_env} REVISION=#{current_sha} REPO=#{repository} USER='#{current_user}'&quot; 
  puts &quot;Notifying Hoptoad of Deploy (#{notify_command})&quot; 
  `#{notify_command}`
  puts &quot;Hoptoad Notification Complete.&quot; 
end
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Then added it as a dependency for the deploy task&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;task :deploy =&amp;gt; [:update, :migrate, :start_app, :notify_hoptoad]
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;There are a couple of helper tasks I&amp;#8217;ve added to get the git user and the &lt;span class=&quot;caps&quot;&gt;SHA&lt;/span&gt; of the commit being deployed&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;remote_task :git_revision do
  set :current_sha, run(&quot;cd #{File.join(scm_path, 'repo')}; git rev-parse origin/master&quot;).strip
end

task :git_user do
  set :current_user, `git config --get user.name`.strip
end
&lt;/code&gt;&lt;/pre&gt;</description>
      <pubDate>Fri, 04 Sep 2009 11:46:47 +0000</pubDate>
      <link>http://kernowsoul.com/blog/2009/09/04/vlad-the-deployer-hoptoad-integration</link>
      <guid>http://kernowsoul.com/blog/2009/09/04/vlad-the-deployer-hoptoad-integration</guid>
    </item>
    <item>
      <title>For the love of table football, why I stayed up for 48 hours</title>
      <description>&lt;p&gt;What a weekend, it all started on Friday night, a feverish last minute planning session began on how we would implement &lt;a href=&quot;http://wuzlr.com&quot;&gt;wuzlr.com&lt;/a&gt;. We&amp;#8217;d bounced around some ideas earlier in the week and had a pretty good idea of what we wanted, whittling that down into a set of features we could implement in 48 hours was no easy task, there was so many good ideas we didn&amp;#8217;t have time to implement them all. The at 1am it all began&amp;#8230;&lt;/p&gt;

&lt;h3&gt;The Pitch&lt;/h3&gt;

&lt;p&gt;If your office is anything like ours things get pretty serious whenever a game of table football breaks out (especially when &lt;a href=&quot;http://twitter.com/theozaurus&quot;&gt;@theozaurus&lt;/a&gt; is playing). We&amp;#8217;ve wanted a way to track who&amp;#8217;s the best in the office for quite some time, finally we have just the thing, and so do you. Wuzlr is a table football league tracking application that lets you see performance over time with all sorts of fun and interesting facts and figures displayed.&lt;/p&gt;

&lt;p&gt;Wuzlr (or wuzler if you use the correct non web 2.0 spelling) is the Austrian word for table football and just so happened to be the first domain we came across that&amp;#8217;s still available. We also liked the hat tip to the &amp;#8216;e&amp;#8217; dropping crowd, no not you party people, I&amp;#8217;m talking about flickr and the like.&lt;/p&gt;

&lt;object width=&quot;425&quot; height=&quot;344&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://www.youtube.com/v/gGYnFlC7i7E&amp;#38;hl=en&amp;#38;fs=1&amp;#38;&quot;&gt;&lt;/param&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;&gt;&lt;/param&gt;&lt;param name=&quot;allowscriptaccess&quot; value=&quot;always&quot;&gt;&lt;/param&gt;&lt;embed src=&quot;http://www.youtube.com/v/gGYnFlC7i7E&amp;#38;hl=en&amp;#38;fs=1&amp;#38;&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;344&quot;&gt;&lt;/embed&gt;&lt;/object&gt;

&lt;h3&gt;Application Features&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Create leagues and record all your games,
Check out the &lt;a href=&quot;http://wuzlr.com/leagues/4&quot;&gt;Jiva office league&lt;/a&gt;&lt;/li&gt;

  &lt;li&gt;Compare yourself to other players,
Me Vs. Theo &lt;br /&gt;&lt;img src=&quot;/uploaded/images/wuzlr-compare.jpg&quot; style=&quot;margin-top: 20px;margin-bottom: 20px;&quot; /&gt;&lt;/li&gt;

  &lt;li&gt;View your nemesis, best team mate, worst team mate and more, &lt;a href=&quot;http://wuzlr.com/users/60&quot;&gt;my player page&lt;/a&gt;&lt;/li&gt;

  &lt;li&gt;League standings, games played per day, table bias, most dedicated players (who&amp;#8217;s put the most time in) &lt;br /&gt;&lt;img src=&quot;/uploaded/images/wuzlr-graphs.jpg&quot; style=&quot;margin-top: 20px;margin-bottom: 20px;&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Our Team&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Jamie Dyer &lt;a href=&quot;http://twitter.com/kernowsoul&quot;&gt;@kernowsoul&lt;/a&gt; Developer for &lt;a href=&quot;http://jivatechnology.com/&quot;&gt;Jiva&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Theo Coushion &lt;a href=&quot;http://twitter.com/theozaurus&quot;&gt;@theozaurus&lt;/a&gt; Developer for &lt;a href=&quot;http://jivatechnology.com/&quot;&gt;Jiva&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;Peter Coles &lt;a href=&quot;http://twitter.com/fatelvis&quot;&gt;@fatelvis&lt;/a&gt; Designer for &lt;a href=&quot;http://www.existem.com/&quot;&gt;Existem&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yes we know the site looks terrible in IE, who uses IE anyway?&lt;/p&gt;</description>
      <pubDate>Mon, 24 Aug 2009 01:05:43 +0000</pubDate>
      <link>http://kernowsoul.com/blog/2009/08/24/for-the-love-of-table-football-why-i-stayed-up-for-48-hours</link>
      <guid>http://kernowsoul.com/blog/2009/08/24/for-the-love-of-table-football-why-i-stayed-up-for-48-hours</guid>
    </item>
    <item>
      <title>My computer loves autotest-fsevent</title>
      <description>&lt;p&gt;I&amp;#8217;m a big fan of &lt;a href=&quot;http://www.zenspider.com/ZSS/Products/ZenTest/&quot;&gt;autotest&lt;/a&gt; for testing, unfortunately it does stress my poor MacBook Pro and makes the fan go berserk if running anything other than the most simple of test suites. This is due to autotest having to check each file in your project for changes.&lt;/p&gt;


	&lt;p&gt;No more will autotest stress out my mac, &lt;a href=&quot;http://www.bitcetera.com/en/products/autotest-fsevent&quot;&gt;autotest-fsevent&lt;/a&gt; is a great gem that uses &lt;span class=&quot;caps&quot;&gt;OS X&lt;/span&gt;&amp;#8217;s FSEvent system to be notified when files have changed rather than having to poll each file. You need mac &lt;span class=&quot;caps&quot;&gt;OS X 10&lt;/span&gt;.5 or later to take advantage of FSEvent.&lt;/p&gt;


	&lt;p&gt;The other nice thing autotest-fsevent does is take care of all the .autotest config options, I managed to delete my entire config file which I&amp;#8217;ve been tweaking for as long as I can remember trying to get the perfect setup.&lt;/p&gt;


	&lt;p&gt;I can now run even the most demanding of test suites and my computer barely breaks a sweat. Thanks &lt;a href=&quot;http://www.bitcetera.com&quot;&gt;bitcetera&lt;/a&gt;, my computer &amp;hearts;&amp;#8217;s you.&lt;/p&gt;</description>
      <pubDate>Thu, 04 Jun 2009 13:10:30 +0000</pubDate>
      <link>http://kernowsoul.com/blog/2009/06/04/my-computer-loves-autotest-fsevent</link>
      <guid>http://kernowsoul.com/blog/2009/06/04/my-computer-loves-autotest-fsevent</guid>
    </item>
    <item>
      <title>DRYing up multiple user contexts with shoulda macros</title>
      <description>&lt;p&gt;Today I&amp;#8217;ve been writing tests for a legacy Rails application I inherited recently. The application has several user roles, each role having varying permissions. To deal with this nicely I setup &lt;a href=&quot;http://thoughtbot.com/projects/shoulda&quot;&gt;shoulda&lt;/a&gt; macro&amp;#8217;s to create contexts for each of the user roles, public user, standard user, admin user etc. then in my tests I could write&amp;#8230;&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;public_context do

  context &quot;on GET to :index&quot; do
    setup do
      get :index
    end

    should_redirect_to(&quot;root url&quot;) { root_url }
  end
end

signed_in_user_context do

  context &quot;on GET to :index&quot; do
    setup do
      get :index
    end

    should_redirect_to(&quot;user url&quot;) { user_url }
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This is pretty standard practice now and something I picked up from looking at the code produced by the guys at &lt;a href=&quot;http://thoughtbot.com&quot;&gt;Thought Bot&lt;/a&gt;. While working on the test suite it became apparent many of the methods behaved in the same way for multiple user roles. I wanted to come up with a way to run a group of tests under multiple user roles without having to duplicate any code. Shoulda macros to the rescue again! After creating another macro to deal with multiple contexts I can write my tests like this&amp;#8230;&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;multiple_contexts 'public_context', 'signed_in_user_context' do

  context &quot;on GET to :show&quot; do
    setup do
      @advert = Factory(:advert)
      get :show, :id =&amp;gt; @advert.to_param
    end

    should_render_with_layout :application
    should_render_template :show
    should_not_set_the_flash
    should_assign_to( :advert ) { @advert }  
    should_respond_with :success
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;And the shoulda macro code itself&amp;#8230;&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;def multiple_contexts(*contexts, &amp;#38;blk)
  contexts.each { |context|
    send(context, &amp;#38;blk) if respond_to?(context)
  }
end

def public_context(&amp;#38;blk)
  context &quot;The public&quot; do
    setup { sign_out }
    merge_block(&amp;#38;blk)
  end
end

def signed_in_user_context(&amp;#38;blk)
  context &quot;A signed in user&quot; do
    setup do
      @user = Factory(:user)
      sign_in_as @user
    end
    merge_block(&amp;#38;blk)
  end
end&lt;/code&gt;&lt;/pre&gt;</description>
      <pubDate>Fri, 22 May 2009 00:14:26 +0000</pubDate>
      <link>http://kernowsoul.com/blog/2009/05/22/drying-up-multiple-user-contexts-with-shoulda-macros</link>
      <guid>http://kernowsoul.com/blog/2009/05/22/drying-up-multiple-user-contexts-with-shoulda-macros</guid>
    </item>
    <item>
      <title>Running JSLint through textmate</title>
      <description>&lt;p&gt;I&amp;#8217;ve been developing with JavaScript a lot recently and found &lt;a href=&quot;http://www.jslint.com/&quot;&gt;JSLint&lt;/a&gt; to be a rather useful tool for picking up syntax errors. Being primarily a &lt;a href=&quot;http://www.ruby-lang.org/en/&quot;&gt;ruby&lt;/a&gt; developer I have a nasty habit of omitting semicolons from the end of lines.&lt;/p&gt;


	&lt;p&gt;I found an article on &lt;a href=&quot;http://www.phpied.com/jslint-on-mac-textmate/&quot;&gt;running JSLint through a textmate command&lt;/a&gt; but found &lt;a href=&quot;http://wonko.com/post/pretty-jslint-output-for-textmate&quot;&gt;Ryan&amp;#8217;s script&lt;/a&gt; didn&amp;#8217;t quite work with the output from the version of JSLint I&amp;#8217;m using so I thought I&amp;#8217;d share my modifications.&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;#!/usr/bin/env ruby
require 'cgi'

lint = `/usr/bin/java -jar ~/Library/JSLint/js.jar ~/Library/JSLint/jslint.js &quot;$TM_FILEPATH&quot;`

lint.gsub!(/(line \d+ character \d+:) ([^\n]+)\n([^\n]+)/m) do
  &quot;&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;#{CGI.escapeHTML($1)}&amp;lt;/strong&amp;gt; #{CGI.escapeHTML($2)}&amp;lt;/p&amp;gt;&quot; &amp;lt;&amp;lt;
    ($3 ? &quot;&amp;lt;pre&amp;gt;#{CGI.escapeHTML($3)}&amp;lt;/pre&amp;gt;&quot; : '')
end

lint.gsub!(/^(jslint:.*at )/, '')

print &amp;lt;&amp;lt;HTML
&amp;lt;!doctype&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;style type=&quot;text/css&quot;&amp;gt;
    p { margin-bottom: 0; }
    pre {
      background: #f5f5f5;
      border: 1px solid #cfcfcf;
      font-size: 12px;
      margin-top: 2px;
      padding: 2px 4px;
    }
  &amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  #{lint}
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
HTML&lt;/code&gt;&lt;/pre&gt;</description>
      <pubDate>Mon, 27 Apr 2009 17:41:42 +0000</pubDate>
      <link>http://kernowsoul.com/blog/2009/04/27/running-jslint-through-textmate</link>
      <guid>http://kernowsoul.com/blog/2009/04/27/running-jslint-through-textmate</guid>
    </item>
    <item>
      <title>New bars and rubber for the steed</title>
      <description>&lt;p&gt;&lt;img src=&quot;/uploaded/images/bike-iphone.jpg&quot; alt=&quot;Lemond Fillmore with bull horn bars and orange rubber&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;A couple of weeks ago I had to replace the old tires on my Fillmore as I&amp;#8217;d worn through the green ones that came with teh bike. Took a bit of getting used to the orange but it&amp;#8217;s definitely growing on me.&lt;/p&gt;


	&lt;p&gt;This last weekend I managed a puncture the inner tube while pulling the pump off which required a trip to &lt;a href=&quot;http://www.stradacycles.co.uk/&quot;/&gt;Strada Cycles&lt;/a&gt;. I ended up replacing the bars and break callipers so it turned out to be a much more expensive trip than I was expecting. Just shy of &#163;100 got me a new inner tube and I was back on the road again.&lt;/p&gt;</description>
      <pubDate>Mon, 22 Dec 2008 20:17:51 +0000</pubDate>
      <link>http://kernowsoul.com/blog/2008/12/22/new-bars-and-rubber-for-the-steed</link>
      <guid>http://kernowsoul.com/blog/2008/12/22/new-bars-and-rubber-for-the-steed</guid>
    </item>
    <item>
      <title>javascript_auto_include plugin updated</title>
      <description>&lt;p&gt;I&amp;#8217;ve updated the &lt;a href=&quot;http://kernowsoul.com/page/javascript_auto_include&quot;&gt;javascript_auto_include plugin&lt;/a&gt; to include changes from &lt;a href=&quot;http://github.com/abradburne&quot;&gt;abradburne&lt;/a&gt; and &lt;a href=&quot;http://github.com/jimp79&quot;&gt;jimp79&lt;/a&gt;. Thanks to these guys the plugin now supports nested controllers so you can add javascript to a paths like admin/users and admin/users/show/1 etc.&lt;/p&gt;</description>
      <pubDate>Tue, 02 Dec 2008 16:03:38 +0000</pubDate>
      <link>http://kernowsoul.com/blog/2008/12/02/javascriptautoinclude-plugin-updated</link>
      <guid>http://kernowsoul.com/blog/2008/12/02/javascriptautoinclude-plugin-updated</guid>
    </item>
    <item>
      <title>MySQL order by rand on large data sets</title>
      <description>&lt;p&gt;More of a note to self than a real post. &lt;a href=&quot;http://www.paperplanes.de/archives/2008/4/24/mysql_nonos_order_by_rand/&quot;&gt;Great solution to extremely slow order by rand() queries&lt;/a&gt; when using large data sets by &lt;a href=&quot;http://www.paperplanes.de&quot;&gt;Paperplanes&lt;/a&gt;. Using this technique a query previously taking nearly 0.2 seconds was reduced to around 0.01 seconds.&lt;/p&gt;</description>
      <pubDate>Mon, 01 Dec 2008 17:49:45 +0000</pubDate>
      <link>http://kernowsoul.com/blog/2008/12/01/mysql-order-by-rand-on-large-data-sets</link>
      <guid>http://kernowsoul.com/blog/2008/12/01/mysql-order-by-rand-on-large-data-sets</guid>
    </item>
  </channel>
</rss>
