<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-UK" xmlns="http://www.w3.org/2005/Atom">
  <title>Beanlogic - Our blog</title>
  <id>tag:www.beanlogic.co.uk,2008:mephisto/our-blog</id>
  <generator version="0.8.0" uri="http://mephistoblog.com">Mephisto Drax</generator>
  <link href="http://www.beanlogic.co.uk/feed/our-blog/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="http://www.beanlogic.co.uk/our-blog" rel="alternate" type="text/html"/>
  <updated>2008-10-28T13:53:58Z</updated>
  <entry xml:base="http://www.beanlogic.co.uk/">
    <author>
      <name>Elwyn Malethan</name>
    </author>
    <id>tag:www.beanlogic.co.uk,2008-10-01:31</id>
    <published>2008-10-01T11:16:00Z</published>
    <updated>2008-10-28T13:53:58Z</updated>
    <category term="Our blog"/>
    <link href="http://www.beanlogic.co.uk/2008/10/1/beanlogic-sale-now-on" rel="alternate" type="text/html"/>
    <title>Beanlogic sale now on!</title>
<summary type="html">&lt;p&gt;&lt;img src=&quot;/assets/2008/10/1/30pc-off.png&quot; alt=&quot;&quot; /&gt; &lt;em&gt;Cheesy title eh! :-)&lt;/em&gt;&lt;/p&gt;


	&lt;p class=&quot;clear&quot;&gt;Many of our customers are worried about the current economic slow down. They&#8217;re tightening their belts, thinking much harder about their planned investments, especially in the realms of software and the web. We at Beanlogic appreciate the pressures on business in these times. Well, Beanlogic is tightening its belt as well. We are happy to announce a &lt;strong&gt;30% cut in our rates&lt;/strong&gt; effective for work commissioned in October &#8216;08.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;&lt;img src=&quot;/assets/2008/10/1/30pc-off.png&quot; alt=&quot;&quot; /&gt; &lt;em&gt;Cheesy title eh! :-)&lt;/em&gt;&lt;/p&gt;


	&lt;p class=&quot;clear&quot;&gt;Many of our customers are worried about the current economic slow down. They&#8217;re tightening their belts, thinking much harder about their planned investments, especially in the realms of software and the web. We at Beanlogic appreciate the pressures on business in these times. Well, Beanlogic is tightening its belt as well. We are happy to announce a &lt;strong&gt;30% cut in our rates&lt;/strong&gt; effective for work commissioned in October &#8216;08.&lt;/p&gt;
&lt;h3&gt;Squeeze on promotional budgets&lt;/h3&gt;


	&lt;p&gt;Website development usually sits under budgetary responsibility of &lt;em&gt;marketing&lt;/em&gt;, which is often the area to see the biggest slowdown in times of economic uncertainty. This is ironic since it is exactly the time that advertising and promotional activities are most valuable.&lt;/p&gt;


	&lt;p&gt;It is particularly important to maintain a marketing spend in such times. Precisely because of the slowdown more value for money can be obtained due to the increasing competitiveness of the market. Something which Beanlogic&#8217;s lower prices reflect.&lt;/p&gt;


	&lt;h3&gt;Efficiency is the order of the day&lt;/h3&gt;


	&lt;p&gt;When the market becomes an increasingly competitive place to do business, organisations large and small need to look at where economies can be made. This shouldn&#8217;t come at the cost of productivity however. With great software to automate processes and improve efficiency in your business it is possible to counter the pressure put on your margin by the current turmoil.&lt;/p&gt;


	&lt;p&gt;Again, because of the the competitive rates Beanlogic is offering, it is possible to get &lt;strong&gt;great value for money&lt;/strong&gt; and get the &lt;strong&gt;maximum return on investment&lt;/strong&gt;. The efficiencies organisations put in place today will help them weather the storm and will make them extra competitive when the economy recovers. As a result companies that invest at times like this will prosper more as economic growth returns and they&#8217;ll recover quicker.&lt;/p&gt;


	&lt;h3&gt;Don&#8217;t hesitate&lt;/h3&gt;


	&lt;p&gt;If you or your organisation are interested in investing in a new website or additions to an existing website or great, reliable software to improve efficiency, Beanlogic is here to help. Our already highly-competitive rates are slashed for work commissioned in October &#8216;08.&lt;/p&gt;


	&lt;p&gt;Even if you have an existing supplier, why not get a competing quote from Beanlogic. You can be assured of the quality of our output, &lt;a href=&quot;/our-work&quot;&gt;our work speaks for itelf&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Call now on 029 2000 6404 for a free telephone consultation.&lt;/strong&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.beanlogic.co.uk/">
    <author>
      <name>Elwyn Malethan</name>
    </author>
    <id>tag:www.beanlogic.co.uk,2008-09-25:26</id>
    <published>2008-09-25T08:43:00Z</published>
    <updated>2008-10-30T14:27:45Z</updated>
    <category term="Our blog"/>
    <link href="http://www.beanlogic.co.uk/2008/9/25/pifa-launched" rel="alternate" type="text/html"/>
    <title>PIFA Launched</title>
<summary type="html">&lt;p&gt;We are happy to announce the launch of another successful Beanlogic project. This time for the &lt;a href=&quot;http://www.grcc.org.uk/&quot; title=&quot;Gloucestershire Rural Community Council&quot;&gt;&lt;span class=&quot;caps&quot;&gt;GRCC&lt;/span&gt;&lt;/a&gt; in the form of &lt;a href=&quot;http://www.performanceimprovementforall.co.uk/&quot; title=&quot;Performance Improvement For All&quot;&gt;&lt;span class=&quot;caps&quot;&gt;PIFA&lt;/span&gt;&lt;/a&gt; (Performance Improvement For All).&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;We are happy to announce the launch of another successful Beanlogic project. This time for the &lt;a href=&quot;http://www.grcc.org.uk/&quot; title=&quot;Gloucestershire Rural Community Council&quot;&gt;&lt;span class=&quot;caps&quot;&gt;GRCC&lt;/span&gt;&lt;/a&gt; in the form of &lt;a href=&quot;http://www.performanceimprovementforall.co.uk/&quot; title=&quot;Performance Improvement For All&quot;&gt;&lt;span class=&quot;caps&quot;&gt;PIFA&lt;/span&gt;&lt;/a&gt; (Performance Improvement For All).&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;caps&quot;&gt;PIFA&lt;/span&gt; is &lt;span class=&quot;caps&quot;&gt;GRCC&lt;/span&gt; initiative to help voluntary organisations add value to their offering by providing services and support in many areas. The website was a technically far simpler affair in comparison to the average Beanlogic project. Sometimes it&#8217;s nice to have a small-scale, pure design project.&lt;/p&gt;


	&lt;p class=&quot;clear&quot;&gt;&lt;a href=&quot;http://www.performanceimprovementforall.co.uk/&quot;&gt;&lt;img src=&quot;/assets/2008/9/25/pifa-screenshot.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.beanlogic.co.uk/">
    <author>
      <name>Elwyn Malethan</name>
    </author>
    <id>tag:www.beanlogic.co.uk,2008-09-18:22</id>
    <published>2008-09-18T10:10:00Z</published>
    <updated>2008-09-18T10:16:34Z</updated>
    <category term="Our blog"/>
    <category term="cms"/>
    <category term="horan"/>
    <category term="website"/>
    <link href="http://www.beanlogic.co.uk/2008/9/18/radiant-layouts" rel="alternate" type="text/html"/>
    <title>Radiant file-based layouts</title>
<summary type="html">&lt;p&gt;A few weeks ago I went over to see Tim O&#8217;Donovan at Horan Construction (no website yet, we&#8217;re working on it). They are a successful civil engineering company based in South Wales that undertake a variety of projects, varying from road surfacing to the design and construction of household-waste disposal centers. Despite being successful and respected in their industry they currently have no web presence.&lt;/p&gt;


	&lt;p&gt;Beanlogic are developing a new content-managed website for them. This kind of small-scale project is a common occurrence and we have a streamlined process and a collection of the tools and frameworks that we have become proficient with to implement just this kind of project. One of the tools we use is &lt;a href=&quot;http://radiantcms.org/&quot;&gt;Radiant&lt;/a&gt; , an open-source &lt;a href=&quot;http://www.rubyonrails.org/&quot;&gt;Ruby on Rails&lt;/a&gt; based content management system (CMS).&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;A few weeks ago I went over to see Tim O&#8217;Donovan at Horan Construction (no website yet, we&#8217;re working on it). They are a successful civil engineering company based in South Wales that undertake a variety of projects, varying from road surfacing to the design and construction of household-waste disposal centers. Despite being successful and respected in their industry they currently have no web presence.&lt;/p&gt;


	&lt;p&gt;Beanlogic are developing a new content-managed website for them. This kind of small-scale project is a common occurrence and we have a streamlined process and a collection of the tools and frameworks that we have become proficient with to implement just this kind of project. One of the tools we use is &lt;a href=&quot;http://radiantcms.org/&quot;&gt;Radiant&lt;/a&gt; , an open-source &lt;a href=&quot;http://www.rubyonrails.org/&quot;&gt;Ruby on Rails&lt;/a&gt; based content management system (CMS).&lt;/p&gt;
&lt;h3&gt;Radiant&lt;/h3&gt;


	&lt;p&gt;We use Radiant for a number of our content-managed projects. &lt;em&gt;&#8220;A bespoke software company using off-the-shelf application?&#8221;&lt;/em&gt; I hear you ask. Well, yes we we do. We&#8217;re busy developing extensions to Radiant that solve our customers&#8217; business needs rather than re-inventing the content management wheel. Besides, Radiant has a strong and active community that is always improving the offering. Something we have been actively involved in.&lt;/p&gt;


	&lt;p&gt;Radiant covers the vast majority of the functionality one would need in terms of content-management. However, we have found it lacking in some specific areas. One is navigation ordering, which will be the subject of another article. Another is the fact that the layout &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; templates reside in the database.&lt;/p&gt;


	&lt;h4&gt;Database layouts&lt;/h4&gt;


	&lt;p&gt;Layouts or view templates are the ubiquitous wrapper for every view in a web-application or website. They provide an easy way to apply to each view in the application with a standard or uniform decoration. In the average web-application (implemented using Rails perhaps) the layouts are stored on the file system, in the source tree.&lt;/p&gt;


	&lt;p&gt;In Radiant, which by it&#8217;s very nature allows the user to create and modify pages, all the view information, including the layouts are stored in the database. This is generally fine if all we were dealing with is a solely content-driven website. In most cases however we are not. We&#8217;re dealing with a content-driven website that has software-based extensions. In our projects, these extensions vary from reservation systems found in &lt;a href=&quot;http://www.lamangadirect.co.uk/&quot;&gt;La Manga Direct&lt;/a&gt; and &lt;a href=&quot;http://www.parkluxurycottages.com/&quot;&gt;Park Cottages&lt;/a&gt; to an on-line shop extension we&#8217;re developing for a current project.&lt;/p&gt;


	&lt;p&gt;In a standard Radiant deployment the extensions are forced to use the same database-driven layouts that the content-managed views use. This means that we have source code that is part of extension software residing in the database. This is something I find unpalatable for two reasons.&lt;/p&gt;


	&lt;h4&gt;Source code belongs in version control&lt;/h4&gt;


	&lt;p&gt;I include &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; in the term &lt;em&gt;source code&lt;/em&gt;. We use a &lt;span class=&quot;caps&quot;&gt;VCS&lt;/span&gt; (Version Control System) &#8211; &lt;a href=&quot;http://subversion.tigris.org/&quot;&gt;Subversion&lt;/a&gt; to be precise &#8211; for all our projects here, it&#8217;s an essential component of developing software (any software developer that doesn&#8217;t employ some form of &lt;span class=&quot;caps&quot;&gt;VCS&lt;/span&gt; is not be trusted in my humble opinion). In any ordinary web application the views and layouts for those views usually reside in the source tree, and therefore in the &lt;span class=&quot;caps&quot;&gt;VCS&lt;/span&gt;. This means that they can be subjected to the usual view testing. It also means that changes made to layouts on a developer&#8217;s workstation are made available to every other developer and any staging machines by virtue of the fact they all get the source code from the &lt;span class=&quot;caps&quot;&gt;VCS&lt;/span&gt;. This cannot be achieved with database layouts unless we start storing all or part of the database content in the &lt;span class=&quot;caps&quot;&gt;VCS&lt;/span&gt;, which creates it&#8217;s own problems.&lt;/p&gt;


	&lt;p&gt;This leads me on to the second reason for being unhappy with storing layouts in the database, and that is concurrency issues.&lt;/p&gt;


	&lt;h4&gt;Which database is the authority?&lt;/h4&gt;


	&lt;p&gt;After the launch of a new website and especially in the final stages of the development of a project the customer &#8211; or someone acting on their behalf &#8211; is busy populating or modifying the content for their website. What is also usually happening during this period is final tweaks and bug fixes. Some of these changes sometimes involve changes to layouts. If the layouts reside in the database there is potential for there being multiple, conflicting versions of the database on multiple workstations or staging servers.&lt;/p&gt;


	&lt;p&gt;The short-sighted (non)answer is to prevent changes on other copies of the database whilst working on another. The correct solution is to solve the root-cause of the problem. That is the fact that there is software source code in the database, somewhere it has no business being.&lt;/p&gt;


	&lt;h4&gt;The right answer?&lt;/h4&gt;


	&lt;p&gt;The answer is to view it from a pure software point of view. That is to employ the same methodologies and principles to any Radiant project that we would apply to a pure software project, and to do this without compromise. These methodologies include test-driven development (TDD), behavior-driven development (BDD) and &#8211; more relevantly to this article &#8211; the compulsory use of source management using version control.&lt;/p&gt;


	&lt;h3&gt;File-based layouts&lt;/h3&gt;


	&lt;p&gt;Before we tried to solve this problem ourselves we had a look at what already available on the open-source shelf.&lt;/p&gt;


	&lt;h4&gt;file-system-extension&lt;/h4&gt;


	&lt;p&gt;One solution that first cropped up was the Radiant extension &lt;a href=&quot;http://github.com/nelstrom/radiant-file-system-extension/&quot;&gt;file-system-extension&lt;/a&gt; . This extension provides some handy rake tasks to extract the database content (including the layouts) and place it on the file-system and vice-versa. With some tweaking we could modify these tasks to act exclusively on the layout data. However this doesn&#8217;t solve our problem. Regardless of what we are editing to change the layouts, Radiant will still be looking for them in the database.&lt;/p&gt;


	&lt;p&gt;This extension does allow us to keep our layout in the &lt;span class=&quot;caps&quot;&gt;VCS&lt;/span&gt; but it doesn&#8217;t solve the problem of database concurrency.&lt;/p&gt;


	&lt;h4&gt;file_based_layout&lt;/h4&gt;


	&lt;p&gt;The next thing we tried is the &lt;a href=&quot;http://ext.radiantcms.org/extensions/14-file-based-layout&quot;&gt;file_based_layout&lt;/a&gt; extension . The name alone sounds promising if does what it says on the tin.&lt;/p&gt;


	&lt;p&gt;This extension allows us to define layouts in Radiant that us a file on the file system rather than database content. That means that the layouts can now reside in the &lt;span class=&quot;caps&quot;&gt;VCS&lt;/span&gt; and that all versions (developers&#8217; workstations and deployed servers) use layout from the file system. It satisfies the criteria I have set out above. This is what we are currently using for our Radiant-based projects and the respective extensions. If anyone has any other recommendations I&#8217;d be happy to hear about it.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.beanlogic.co.uk/">
    <author>
      <name>Elwyn Malethan</name>
    </author>
    <id>tag:www.beanlogic.co.uk,2008-08-13:19</id>
    <published>2008-08-13T17:49:00Z</published>
    <updated>2008-08-13T19:37:50Z</updated>
    <category term="Our blog"/>
    <category term="image manipulation"/>
    <category term="imagemagick"/>
    <category term="rmagick"/>
    <link href="http://www.beanlogic.co.uk/2008/8/13/installing-a-specific-verison-of-rmagick" rel="alternate" type="text/html"/>
    <title>Installing a specific version of rmagick</title>
<summary type="html">&lt;p&gt;Ever tried to install a specific version of &lt;a href=&quot;http://rmagick.rubyforge.org/&quot;&gt;rmagick&lt;/a&gt; ? That is a version that isn&#8217;t the latest. Most people that find this page on Google have probably noticed that it doesn&#8217;t always go smoothly. Other readers familiar with rubygems are probably thinking &#8220;It&#8217;s easy, you just do this&#8230;&#8221;&lt;/p&gt;


&lt;pre class=&quot;blackboard&quot;&gt;
$ sudo gem install rmagick --version X.X.X
&lt;/pre&gt;

	&lt;p&gt;That&#8217;s certainly what I thought, I then spent the next 1/2 hour trying to figure out why one of the most simple tasks wasn&#8217;t working out.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Ever tried to install a specific version of &lt;a href=&quot;http://rmagick.rubyforge.org/&quot;&gt;rmagick&lt;/a&gt; ? That is a version that isn&#8217;t the latest. Most people that find this page on Google have probably noticed that it doesn&#8217;t always go smoothly. Other readers familiar with rubygems are probably thinking &#8220;It&#8217;s easy, you just do this&#8230;&#8221;&lt;/p&gt;


&lt;pre class=&quot;blackboard&quot;&gt;
$ sudo gem install rmagick --version X.X.X
&lt;/pre&gt;

	&lt;p&gt;That&#8217;s certainly what I thought, I then spent the next 1/2 hour trying to figure out why one of the most simple tasks wasn&#8217;t working out.&lt;/p&gt;
&lt;p&gt;We run &lt;a href=&quot;http://www.debian.org/&quot;&gt;Debian&lt;/a&gt; and &lt;a href=&quot;http://www.ubuntu.com/&quot;&gt;Ubuntu&lt;/a&gt; servers here at Beanlogic, purely for the stability/reliability and ease of administration. Debian especially holds stability and reliability over the currency of the software included, which is good for the reliability of our hosting. It sometimes comes at the cost of easy access to the very latest versions of some software libraries however. &lt;a href=&quot;http://www.imagemagick.org/&quot;&gt;ImageMagick&lt;/a&gt; is one of those libraries.&lt;/p&gt;


	&lt;p&gt;Debian 4.0 (&lt;em&gt;Etch&lt;/em&gt;) has, as standard ImageMagick version 6.2.4 available in the package repositories. However, the latest version of &lt;code&gt;rmagick&lt;/code&gt; (2.52) at the time of writing requires ImageMagick &amp;gt;= 6.3.0. As illustrated by the following:&lt;/p&gt;


&lt;pre class=&quot;blackboard&quot;&gt;
$ sudo gem install --no-rdoc --no-ri --no-update-sources rmagick 
Building native extensions.  This could take a while...
ERROR:  Error installing rmagick:
    ERROR: Failed to build gem native extension.

/usr/bin/ruby1.8 extconf.rb install --no-rdoc --no-ri --no-update-sources rmagick
checking for Ruby version &amp;gt;= 1.8.2... yes
checking for gcc... yes
checking for Magick-config... yes
checking for ImageMagick version &amp;gt;= 6.3.0... no
Can't install RMagick 2.5.2. You must have ImageMagick 6.3.0 or later.

*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers.  Check the mkmf.log file for more
details.  You may need configuration options.

Provided configuration options:
    --with-opt-dir
    --without-opt-dir
    --with-opt-include
    --without-opt-include=${opt-dir}/include
    --with-opt-lib
    --without-opt-lib=${opt-dir}/lib
    --with-make-prog
    --without-make-prog
    --srcdir=.
    --curdir
    --ruby=/usr/bin/ruby1.8

Gem files will remain installed in /usr/lib/ruby/gems/1.8/gems/rmagick-2.5.2 for inspection.
Results logged to /usr/lib/ruby/gems/1.8/gems/rmagick-2.5.2/ext/RMagick/gem_make.out
&lt;/pre&gt;

	&lt;p&gt;Ok, so I need to install a specific version of &lt;code&gt;rmagick&lt;/code&gt;. Easy, you say. So I thought.&lt;/p&gt;


	&lt;p&gt;This is what happened on my first attempt.&lt;/p&gt;


&lt;pre class=&quot;blackboard&quot;&gt;
$ sudo gem install --no-rdoc --no-ri --no-update-sources rmagick --version 1.15.13
Building native extensions.  This could take a while...
ERROR:  While executing gem ... (Gem::Installer::ExtensionBuildError)
    ERROR: Failed to build gem native extension.

ruby gem_extconf.rb install --no-rdoc --no-ri rmagick --version 1.15.13

sh configure --disable-htmldoc --version

RMagick configure 1.15.13
generated by GNU Autoconf 2.61

Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
RMagick configuration completed successfully.

Gem files will remain installed in /var/lib/gems/1.8/gems/rmagick-1.15.13 for inspection.
Results logged to /var/lib/gems/1.8/gems/rmagick-1.15.13/gem_make.out
&lt;/pre&gt;

	&lt;p&gt;That didn&#8217;t work at all! What ensued was 30 minutes of confused, follicle-threatening investigating. The clue to the problem above is the reference to &lt;code&gt;sh configure&lt;/code&gt;. Rubygems is passing the &lt;code&gt;--version&lt;/code&gt; argument to the part of the installation that compiles C-based parts of the gem. This results in no compilation at all! It instead tells us what version of &lt;code&gt;rmagick&lt;/code&gt; we&#8217;re trying to install. Not helpful.&lt;/p&gt;


	&lt;p&gt;The solution is to be less verbose and do the following instead.&lt;/p&gt;


&lt;pre class=&quot;blackboard&quot;&gt;
sudo gem install --no-rdoc --no-ri --no-update-sources rmagick -v 1.15.13
Building native extensions.  This could take a while...
Successfully installed rmagick-1.15.13
&lt;/pre&gt;

	&lt;p&gt;&lt;em&gt;Note the use of &lt;code&gt;-v&lt;/code&gt; instead of &lt;code&gt;--version&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;It seems that the lesson of this experience for me is to be less verbose. Some people who know me might agree with that&#8230;&lt;/p&gt;


	&lt;p&gt;On a somewhat unrelated matter, maybe we should make more use of &lt;a href=&quot;http://seattlerb.rubyforge.org/ImageScience.html&quot;&gt;ImageScience&lt;/a&gt; instead. The claim that it &#8220;kicks the living crap out of RMagick&#8221; sounds good to me!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.beanlogic.co.uk/">
    <author>
      <name>Elwyn Malethan</name>
    </author>
    <id>tag:www.beanlogic.co.uk,2008-08-08:18</id>
    <published>2008-08-08T18:28:00Z</published>
    <updated>2008-08-08T20:26:35Z</updated>
    <category term="Our blog"/>
    <category term="combo box"/>
    <category term="css"/>
    <category term="dhtml"/>
    <category term="form design"/>
    <category term="html"/>
    <category term="user interface"/>
    <link href="http://www.beanlogic.co.uk/2008/8/8/combo-boxes-for-the-web" rel="alternate" type="text/html"/>
    <title>Combo boxes for the web</title>
<summary type="html">&lt;p&gt;Back in &#8216;99, when I took my client-side software blinkers off and moved from C/C++/Java rich-application development to developing for the web I noticed a few things. Not least was the different disciplines that had to be learnt and design patterns employed. The one thing that I could immediately relate to was constructing user interfaces, especially forms. There are familiar elements here, such as text boxes, text areas, radio buttons &#38; checkboxes, select boxes and combo boxes&#8230; oh hang on, that&#8217;s a lie. There are no combo boxes. In fact there has never been a standard browser implementation of a combo box (to my knowledge, please correct me if I&#8217;m wrong). &lt;strong&gt;Well, like blue Smarties, the combo box should come back and join the party.&lt;/strong&gt;&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Back in &#8216;99, when I took my client-side software blinkers off and moved from C/C++/Java rich-application development to developing for the web I noticed a few things. Not least was the different disciplines that had to be learnt and design patterns employed. The one thing that I could immediately relate to was constructing user interfaces, especially forms. There are familiar elements here, such as text boxes, text areas, radio buttons &#38; checkboxes, select boxes and combo boxes&#8230; oh hang on, that&#8217;s a lie. There are no combo boxes. In fact there has never been a standard browser implementation of a combo box (to my knowledge, please correct me if I&#8217;m wrong). &lt;strong&gt;Well, like blue Smarties, the combo box should come back and join the party.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The absence of the combo box in the web developers toolbox has always struck me as odd. Why implement all the other input elements and not a combo box? I suppose the line had to be drawn somewhere. In this article I&#8217;ll be exploring how the traditional web-based approach to simulating combo box functionality can be improved until it looks and feels like a combo box.&lt;/p&gt;


	&lt;h3&gt;The traditional solution&lt;/h3&gt;


&lt;pre class=&quot;blackboard&quot;&gt;
&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;How did you hear about us?&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;br&lt;/span&gt;/&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;select&lt;/span&gt; &lt;span class=&quot;MetaTag&quot;&gt;name&lt;/span&gt;=&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;referrer&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;option&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;From a friend&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;option&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;option&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Found on Google&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;option&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;option&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;From a magazine&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;option&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;option&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Other, please specify&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;option&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;br&lt;/span&gt;/&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;MetaTag&quot;&gt;name&lt;/span&gt;=&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;referrer_other&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;MetaTag&quot;&gt;value&lt;/span&gt;=&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; /&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;The traditional solution to providing combo box functionality has been the rather inelegant separate text box for the &lt;em&gt;other&lt;/em&gt; option. This approach has two main problems in my opinion. One is that it just reminds me of the old paper forms. The web is superseding paper forms as a means of collecting information from people. That means it&#8217;s meant to be better! Well it isn&#8217;t.&lt;/p&gt;


	&lt;p class=&quot;clear&quot;&gt;&lt;img src=&quot;/assets/2008/8/8/screengrab1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;The other problem with this traditional solution is that it&#8217;s always been an annoyance to validate or process. Some potentially very elegant code to iterate through the fields in your form to validate or process the information is confounded by the exception that in a certain condition we have to consult a different field of the form. That&#8217;s not major problem, I hear you say. True, problems like this are par for the course for web developers. We at Beanlogic like elegant, beautiful solutions however. Even if they are &lt;em&gt;under the bonnet&lt;/em&gt;, never to be seen by anyone.&lt;/p&gt;


	&lt;p&gt;I could go through all the half-hearted steps one could take to improve, by increment both the visual and technical aspects of the traditional solution. I&#8217;m not going to. Any interim, partial improvement would perhaps have been relevant a few years ago. These days, with most browsers in in ubiquitous use supporting a decent level of scripting and standards compliance (even &lt;span class=&quot;caps&quot;&gt;IE6&lt;/span&gt;, &lt;em&gt;gasp!&lt;/em&gt;) and lightweight JavaScript libraries like &lt;a href=&quot;http://www.prototypejs.org/&quot;&gt;Prototype&lt;/a&gt; standardising the programming interface, we can go straight to the optimal solution. Then I&#8217;ll show how it can be made scalable. Incidentally, if you&#8217;re interested in a &#8216;90s style solution look &lt;a href=&quot;http://www.cs.tut.fi/~jkorpela/forms/combo.html&quot;&gt;here&lt;/a&gt; ;-)&lt;/p&gt;


	&lt;h3&gt;The solution&lt;/h3&gt;


	&lt;p&gt;The first think I&#8217;m going to address is the visual shortcomings of the traditional approach. Let&#8217;s make it look like a combo box!&lt;/p&gt;


	&lt;p&gt;This bit is a fairly straight-forward use of &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt;. We&#8217;re simply going to reposition our text box over the select box, giving the impression they are one and the same thing.&lt;/p&gt;


	&lt;h4&gt;The &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; for repositioning our input elements&lt;/h4&gt;


&lt;pre class=&quot;blackboard&quot;&gt;

&lt;span class=&quot;Entity&quot;&gt;body&lt;/span&gt; {
  &lt;span class=&quot;Support&quot;&gt;font-family&lt;/span&gt;: &lt;span class=&quot;Support&quot;&gt;sans-serif&lt;/span&gt;; &lt;span class=&quot;Support&quot;&gt;font-size&lt;/span&gt;: &lt;span class=&quot;Constant&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;px&lt;/span&gt;; &lt;span class=&quot;Support&quot;&gt;padding&lt;/span&gt;: &lt;span class=&quot;Constant&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;px&lt;/span&gt;;  
}

&lt;span class=&quot;Entity&quot;&gt;p&lt;/span&gt; {
  &lt;span class=&quot;Support&quot;&gt;line-height&lt;/span&gt;: &lt;span class=&quot;Constant&quot;&gt;18&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;px&lt;/span&gt;;
  &lt;span class=&quot;Support&quot;&gt;position&lt;/span&gt;: &lt;span class=&quot;Support&quot;&gt;relative&lt;/span&gt;;
}

&lt;span class=&quot;Entity&quot;&gt;select&lt;/span&gt; {
  &lt;span class=&quot;Support&quot;&gt;width&lt;/span&gt;: &lt;span class=&quot;Constant&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;px&lt;/span&gt;;
}

&lt;span class=&quot;Entity&quot;&gt;input&lt;/span&gt; {
  &lt;span class=&quot;Support&quot;&gt;width&lt;/span&gt;: &lt;span class=&quot;Constant&quot;&gt;178&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;px&lt;/span&gt;;
  &lt;span class=&quot;Support&quot;&gt;height&lt;/span&gt;: &lt;span class=&quot;Constant&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;px&lt;/span&gt;;
  &lt;span class=&quot;Support&quot;&gt;position&lt;/span&gt;: &lt;span class=&quot;Support&quot;&gt;absolute&lt;/span&gt;;
  &lt;span class=&quot;Support&quot;&gt;top&lt;/span&gt;: &lt;span class=&quot;Constant&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;px&lt;/span&gt;;
  &lt;span class=&quot;Support&quot;&gt;left&lt;/span&gt;: &lt;span class=&quot;Constant&quot;&gt;2&lt;/span&gt;;
  &lt;span class=&quot;Support&quot;&gt;border&lt;/span&gt;: &lt;span class=&quot;Support&quot;&gt;none&lt;/span&gt;
}
&lt;/pre&gt;

	&lt;p&gt;The addition of this &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; makes our form look like this now.&lt;/p&gt;


	&lt;p class=&quot;clear&quot;&gt;&lt;img src=&quot;/assets/2008/8/8/screengrab1_1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;It may now look like a combo box (in &lt;a href=&quot;http://www.mozilla.com/firefox/&quot;&gt;Firefox 3&lt;/a&gt; on &lt;a href=&quot;http://www.ubuntu.com/&quot;&gt;Ubuntu Hardy&lt;/a&gt; at least) but what we&#8217;ve actually done has rendered both elements unusable, at the very least confusing. Let&#8217;s make it behave like a combo box. For this next bit you should download &lt;a href=&quot;http://www.prototypejs.org/&quot;&gt;Prototype&lt;/a&gt; , you&#8217;re going to need it. All of the things I&#8217;m going to be showing in this article and future articles on the subject can be done without Prototype but it&#8217;s &lt;em&gt;easier and quicker with Prototype&lt;/em&gt;.&lt;/p&gt;


&lt;pre class=&quot;blackboard&quot;&gt;
&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;script&lt;/span&gt; &lt;span class=&quot;MetaTag&quot;&gt;src&lt;/span&gt;=&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;prototype.js&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;MetaTag&quot;&gt;type&lt;/span&gt;=&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;text/javascript&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;/&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;&amp;lt;!--&lt;/span&gt; ... &lt;span class=&quot;Comment&quot;&gt;--&amp;gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;How did you hear about us?&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;br&lt;/span&gt;/&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;select&lt;/span&gt; &lt;span class=&quot;MetaTag&quot;&gt;name&lt;/span&gt;=&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;referrer_select&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;MetaTag&quot;&gt;onchange&lt;/span&gt;=&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;$('Referrer').value = this.value&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;option&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;From a friend&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;option&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;option&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Found on Google&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;option&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;option&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;From a magazine&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;option&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;

  &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;MetaTag&quot;&gt;name&lt;/span&gt;=&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;referrer&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;Referrer&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; /&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;I&#8217;ve made a few changes here. I&#8217;ll try to explain them&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;The selection box now populates the text box with the value from the options selected using a little bit of JavaScript.&lt;/li&gt;
		&lt;li&gt;We&#8217;ve dropped the &#8220;Other, please specify&#8221; because it is implied in the functionality of the combo box.&lt;/li&gt;
		&lt;li&gt;Swapped the emphasis around for the naming of the elements. We&#8217;re now only really interested in the value saved in the text box, since all the selection box is there for is to feed values to the  text box.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;That&#8217;s it for now. This obviously isn&#8217;t rocket science. It certainly isn&#8217;t when applied to a single, known browser for a single use. In future articles on the subject I&#8217;ll be showing you how this approach can be scaled up for multiple use across all the browsers in use today. I&#8217;ll also show how we might elegantly process the information in the form and how we can degrade the functionality gracefully to less compliant or functional browsers.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.beanlogic.co.uk/">
    <author>
      <name>Elwyn Malethan</name>
    </author>
    <id>tag:www.beanlogic.co.uk,2008-07-16:17</id>
    <published>2008-07-16T15:00:00Z</published>
    <updated>2008-07-16T16:10:54Z</updated>
    <category term="Our blog"/>
    <category term="restful_authentication"/>
    <link href="http://www.beanlogic.co.uk/2008/7/16/hacking-restful_authentication" rel="alternate" type="text/html"/>
    <title>hacking restful_authentication</title>
<summary type="html">&lt;p&gt;I had a peculiar requirement in a recent project recently, in which we used &lt;a href=&quot;http://agilewebdevelopment.com/plugins/restful_authentication&quot;&gt;restful_authentication&lt;/a&gt;, where we needed to protect every controller and action from access without authentication. However these same actions also responded to &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; requests for ActiveResource models in another app. The &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; needed to be available without authentication. This posed more difficulties than I thought it would.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;I had a peculiar requirement in a recent project recently, in which we used &lt;a href=&quot;http://agilewebdevelopment.com/plugins/restful_authentication&quot;&gt;restful_authentication&lt;/a&gt;, where we needed to protect every controller and action from access without authentication. However these same actions also responded to &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; requests for ActiveResource models in another app. The &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; needed to be available without authentication. This posed more difficulties than I thought it would.&lt;/p&gt;
&lt;h3&gt;Bypassing authentication for &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; requests&lt;/h3&gt;


	&lt;p&gt;I created a controller class to act as the parent class for all controllers that required authentication (the wisdom of the inheritance strategy here is yet to be established). It applies the &lt;code&gt;login_required&lt;/code&gt; filter to all actions, thus protecting all inherited controllers.&lt;/p&gt;


	&lt;p&gt;To filter out &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; requests I took my inspiration from the &lt;code&gt;respond_to&lt;/code&gt; method in Rails. This uses a Responder, which in turn uses some sort of mime-type lookup of the format requested by the client. I used this approach in an overridden version of &lt;code&gt;login_required&lt;/code&gt;.&lt;/p&gt;


&lt;pre class=&quot;blackboard&quot;&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; ...&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;Responder&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;initialize&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;controller&lt;/span&gt;)
      &lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;controller&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; controller
      &lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;request&lt;/span&gt;    &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; controller.&lt;span class=&quot;Entity&quot;&gt;request&lt;/span&gt;
      &lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;response&lt;/span&gt;   &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; controller.&lt;span class=&quot;Entity&quot;&gt;response&lt;/span&gt;

      &lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;mime_type_priority&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;Array&lt;/span&gt;(&lt;span class=&quot;Support&quot;&gt;Mime&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;Type&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;lookup_by_extension&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;request&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;parameters&lt;/span&gt;[&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;format&lt;/span&gt;]) &lt;span class=&quot;Keyword&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;request&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;accepts&lt;/span&gt;)

      &lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;order&lt;/span&gt;     &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; []
      &lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;responses&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; {}
    &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;    &lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; ...&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; ...&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;The one stumbling block I encountered was that I couldn&#8217;t get at the instance properties of &lt;code&gt;Mime::Type&lt;/code&gt; in order to decide whether we needed authentication or not. This was because there were no accessors for those properties. In order to get access to them I extended the instance of &lt;code&gt;Mime::Type&lt;/code&gt; with a new method to expose the &lt;code&gt;symbol&lt;/code&gt; instance property.&lt;/p&gt;


&lt;pre class=&quot;blackboard&quot;&gt;
&lt;span class=&quot;Keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;ApplicationAuthController&lt;span class=&quot;Superclass&quot;&gt; &lt;span class=&quot;Superclass&quot;&gt;&amp;lt;&lt;/span&gt; ApplicationController&lt;/span&gt;&lt;/span&gt;

  before_filter &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;login_required&lt;/span&gt;

  &lt;span class=&quot;Keyword&quot;&gt;protected&lt;/span&gt;

&lt;span class=&quot;Comment&quot;&gt;  &lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; Overidden login_required to allow XML requests through&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;login_required&lt;/span&gt;
    mime_type &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;Array&lt;/span&gt;(&lt;span class=&quot;Support&quot;&gt;Mime&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;Type&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;lookup_by_extension&lt;/span&gt;(request.&lt;span class=&quot;Entity&quot;&gt;parameters&lt;/span&gt;[&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;format&lt;/span&gt;]) &lt;span class=&quot;Keyword&quot;&gt;||&lt;/span&gt; request.&lt;span class=&quot;Entity&quot;&gt;accepts&lt;/span&gt;).&lt;span class=&quot;Entity&quot;&gt;first&lt;/span&gt;

&lt;span class=&quot;Comment&quot;&gt;    &lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; We need to get access to the @symbol property of this object. However it has no accessor.&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;    &lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; We extend this instance only to have a to_sym method&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; mime_type&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;Keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;to_sym&lt;/span&gt;
        &lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;symbol&lt;/span&gt;
      &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;

    logger.&lt;span class=&quot;Entity&quot;&gt;debug&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;Request format: &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;#{&lt;/span&gt;mime_type&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;Entity&quot;&gt;to_sym&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;

    &lt;span class=&quot;Keyword&quot;&gt;super&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;if&lt;/span&gt; mime_type.&lt;span class=&quot;Entity&quot;&gt;to_sym&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;xml&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;As you can see, &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; requests bypass authentication altogether.&lt;/p&gt;


	&lt;p&gt;There are dangers in this approach, especially when the assumption of the presence of a valid &lt;code&gt;current_user&lt;/code&gt; is made in actions that might deliver both normal application output as well as &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt;. Some suitably targeted &lt;em&gt;specs&lt;/em&gt; should limit the scope for broken actions here.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.beanlogic.co.uk/">
    <author>
      <name>Elwyn Malethan</name>
    </author>
    <id>tag:www.beanlogic.co.uk,2008-07-12:14</id>
    <published>2008-07-12T00:00:00Z</published>
    <updated>2008-07-16T16:10:47Z</updated>
    <category term="Our blog"/>
    <category term="bdd"/>
    <category term="gedit"/>
    <category term="plugin"/>
    <category term="rspec"/>
    <category term="textmate"/>
    <link href="http://www.beanlogic.co.uk/2008/7/12/gedit-on-rails" rel="alternate" type="text/html"/>
    <title>Gedit on Rails?</title>
<summary type="html">&lt;p&gt;You watch any screen-cast of any of the Rubystars out there, they&#8217;re using &lt;a href=&quot;http://macromates.com/&quot;&gt;Textmate&lt;/a&gt; on a Mac. Textmate is great, really it is! It has two serious flaws however. They are that &lt;strong&gt;you need a Mac to run it&lt;/strong&gt; and &#8230; that &lt;strong&gt;you need a Mac to run it&lt;/strong&gt;.&lt;/p&gt;


	&lt;p&gt;Now, I have nothing against Macs. They look nice, they work well and have lots of cool little (and not so little) apps to help a developer with productivity. It would be more accurate to say that I have nothing against Mac &lt;span class=&quot;caps&quot;&gt;OS X&lt;/span&gt;. What I hate about the Mac hardware is the compromises that have been made in the pursuit of &#8211; what I have to admit is &#8211; attractive design. I have a Dell laptop, it&#8217;s a lot uglier but it does plug into my docking station both in the office and at home with no fiddling with wires for monitors, keyboards, mice etc. Keeran and &lt;a href=&quot;http://www.markboultondesign.com&quot;&gt;Mark&lt;/a&gt; would both insist that it&#8217;s worth it just to have something pretty on your desk. I&#8217;m not convinced&#8230;&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;You watch any screen-cast of any of the Rubystars out there, they&#8217;re using &lt;a href=&quot;http://macromates.com/&quot;&gt;Textmate&lt;/a&gt; on a Mac. Textmate is great, really it is! It has two serious flaws however. They are that &lt;strong&gt;you need a Mac to run it&lt;/strong&gt; and &#8230; that &lt;strong&gt;you need a Mac to run it&lt;/strong&gt;.&lt;/p&gt;


	&lt;p&gt;Now, I have nothing against Macs. They look nice, they work well and have lots of cool little (and not so little) apps to help a developer with productivity. It would be more accurate to say that I have nothing against Mac &lt;span class=&quot;caps&quot;&gt;OS X&lt;/span&gt;. What I hate about the Mac hardware is the compromises that have been made in the pursuit of &#8211; what I have to admit is &#8211; attractive design. I have a Dell laptop, it&#8217;s a lot uglier but it does plug into my docking station both in the office and at home with no fiddling with wires for monitors, keyboards, mice etc. Keeran and &lt;a href=&quot;http://www.markboultondesign.com&quot;&gt;Mark&lt;/a&gt; would both insist that it&#8217;s worth it just to have something pretty on your desk. I&#8217;m not convinced&#8230;&lt;/p&gt;
&lt;p&gt;Anyway this article is turning into a rant about something entirely different to what I intended.&lt;/p&gt;


	&lt;p&gt;I&#8217;m going to be assuming that anyone interested in this article is OS agnostic and is already passionate about &lt;span class=&quot;caps&quot;&gt;BDD&lt;/span&gt;. &lt;em&gt;Oops, just lost half the small numbers of readers that got beyond my Mac-attack&#8230;&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;This article is about using the Gnome default text editor, &lt;strong&gt;gedit&lt;/strong&gt; for developing in Ruby. On the face of it and even after some half-hearted digging, gedit is not a patch on Textmate. However, I would argue all the fundamentals are there and with the wide variety of plugins available. It is a good alternative.&lt;/p&gt;


	&lt;p&gt;Textmate has benefited from a dedicated team of people willing to put time into developing bundles to enhance the functionality. This is certainly true of functionality relating to software development and Ruby/Rails development in particular. There is very little one can&#8217;t do with a few deft strokes and taps of the keyboard when it comes to Textmate.&lt;/p&gt;


	&lt;p&gt;The thing is, Gedit is just as receptive to extension with a mixture of plugins and external commands. This article is about my first tentative step to creating a decent set of tools to help Ruby developers who want a free alternative to Textmate.&lt;/p&gt;


	&lt;h3&gt;Rspec runner for Gedit&lt;/h3&gt;


	&lt;p&gt;The first thing you need to do is enable the &lt;strong&gt;External Tools&lt;/strong&gt; plugin for Gedit. By the way, if you&#8217;re using Ubuntu, like I am, there are a bunch of useful plugins that aren&#8217;t bundled by default. They&#8217;re not important for the purposes of this article but there are a few gems in there. To install them type &lt;code&gt;sudo apt-get install gedit-plugins&lt;/code&gt; or just follow this link &lt;a&gt;apt://gedit-plugins&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;To enable the External Tools plugin open Gedit and follow these steps&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Navigate to the Preferences item in the Edit menu&lt;/li&gt;
		&lt;li&gt;Select the Plugins tab&lt;/li&gt;
		&lt;li&gt;Find the External Tools plugin and enable it&lt;/li&gt;
		&lt;li&gt;Close the Preferences dialog&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Now you&#8217;re ready to add your rspec running tool. To do this open the External Tools dialog by navigating to Tools -&amp;gt; External Tools. First make the dialog bigger, the Command(s) text box is way too small. Click on the &lt;strong&gt;New&lt;/strong&gt; button to create a new tool. Call it &#8220;Run Rspec&#8221; and give it a meaningful description. The shortcut key I elected to use is &lt;em&gt;Shift+Ctrl+F10&lt;/em&gt;. Now copy the following into the &lt;strong&gt;Command(s)&lt;/strong&gt; text area.&lt;/p&gt;


&lt;pre class=&quot;blackboard&quot;&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;!/usr/bin/ruby&lt;/span&gt;

&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; Copyright (c) 2004 - 2008 Beanlogic Limited&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; This file is part of gedit_on_rails.&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; gedit_on_rails is free software: you can redistribute it and/or modify&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; it under the terms of the GNU General Public License as published by&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; the Free Software Foundation, either version 3 of the License, or&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; (at your option) any later version.&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; gedit_on_rails is distributed in the hope that it will be useful,&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; GNU General Public License for more details.&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; You should have received a copy of the GNU General Public License&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; along with gedit_on_rails.  If not, see &amp;lt;http://www.gnu.org/licenses/&amp;gt;.&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; This is based on the Rspec Textmate bundle  &lt;/span&gt;

&lt;span class=&quot;Variable&quot;&gt;SPEC&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;Variable&quot;&gt;ENV&lt;/span&gt;[&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;GEDIT_CURRENT_DOCUMENT_PATH&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]
&lt;span class=&quot;Variable&quot;&gt;DIR&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;Variable&quot;&gt;ENV&lt;/span&gt;[&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;GEDIT_CURRENT_DOCUMENT_DIR&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]
&lt;span class=&quot;Variable&quot;&gt;PROJECT_DIR&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;Variable&quot;&gt;DIR&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;}&lt;/span&gt;&lt;/span&gt;/../..&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;Variable&quot;&gt;REPORT&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;Variable&quot;&gt;PROJECT_DIR&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;}&lt;/span&gt;&lt;/span&gt;/doc/rspec_report.html&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;

rspec_rails_plugin &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Support&quot;&gt;File&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;join&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;PROJECT_DIR&lt;/span&gt;,&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;vendor&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;,&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;plugins&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;,&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;rspec&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;,&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;lib&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)
&lt;span class=&quot;Keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;Support&quot;&gt;File&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;directory?&lt;/span&gt;(rspec_rails_plugin)
  &lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;$&lt;/span&gt;LOAD_PATH&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;unshift&lt;/span&gt;(rspec_rails_plugin)
&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;spec&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;spec/runner/formatter/html_formatter&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;Keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;Spec&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;Runner&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;Formatter&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;      &lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; Formats backtraces so they're clickable in Firefox&lt;/span&gt;
      &lt;span class=&quot;Keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;HtmlFormatter&lt;/span&gt;
        &lt;span class=&quot;Keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;backtrace_line&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;line&lt;/span&gt;)
          line.&lt;span class=&quot;Entity&quot;&gt;gsub&lt;/span&gt;(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;[&lt;/span&gt;^:&lt;span class=&quot;String&quot;&gt;]&lt;/span&gt;&lt;/span&gt;*&lt;span class=&quot;Constant&quot;&gt;\.&lt;/span&gt;rb&lt;span class=&quot;String&quot;&gt;)&lt;/span&gt;&lt;/span&gt;:&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;Constant&quot;&gt;\d&lt;/span&gt;*&lt;span class=&quot;String&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;/&lt;/span&gt;&lt;/span&gt;) &lt;span class=&quot;Keyword&quot;&gt;do&lt;/span&gt;
            &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&amp;lt;a href=&lt;span class=&quot;Constant&quot;&gt;\&amp;quot;&lt;/span&gt;gedit://&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;Support&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;Entity&quot;&gt;expand_path&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;$&lt;/span&gt;1&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;}&lt;/span&gt;&lt;/span&gt;?&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;$&lt;/span&gt;2&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Constant&quot;&gt;\&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;$&lt;/span&gt;1&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;}&lt;/span&gt;&lt;/span&gt;:&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;$&lt;/span&gt;2&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&amp;lt;/a&amp;gt; &lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
        &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;Keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;Support&quot;&gt;File&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;exists?&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;REPORT&lt;/span&gt;
  &lt;span class=&quot;Support&quot;&gt;File&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;REPORT&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;

argv &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; [&lt;span class=&quot;Variable&quot;&gt;SPEC&lt;/span&gt;]
argv &lt;span class=&quot;Keyword&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;--c&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
argv &lt;span class=&quot;Keyword&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;--format&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
argv &lt;span class=&quot;Keyword&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;html:&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;Variable&quot;&gt;REPORT&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;

::&lt;span class=&quot;Support&quot;&gt;Spec&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;Runner&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;CommandLine&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;run&lt;/span&gt;(
  ::&lt;span class=&quot;Entity&quot;&gt;Spec&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;Runner&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;OptionParser&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;parse&lt;/span&gt;(argv, &lt;span class=&quot;Variable&quot;&gt;STDERR&lt;/span&gt;, &lt;span class=&quot;Variable&quot;&gt;STDOUT&lt;/span&gt;))

&lt;span class=&quot;Keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;Support&quot;&gt;File&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;exists?&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;REPORT&lt;/span&gt;
  &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;`&lt;/span&gt;firefox &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;Variable&quot;&gt;REPORT&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;`&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;Close the dialog and open one of your specs from a Rails project. Now you can quickly run the spec with a quick keystroke and get the results displayed nicely in a web browser! Now for the &lt;em&gt;caveats&lt;/em&gt;. This script makes a number of assumptions.&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Firstly, it pretty much assumes that you are running a spec for a rails project and that rspec and rspec_on_rails are frozen into the app as plugins, this is certainly the only context in which it has been tested.&lt;/li&gt;
		&lt;li&gt;The spec file lives in &lt;span class=&quot;caps&quot;&gt;RAILS&lt;/span&gt;_BASE/spec/&amp;lt;models&gt;/&lt;/li&gt;
		&lt;li&gt;You want to use Firefox to view the spec results in a nice &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; format&lt;/li&gt;
	&lt;/ol&gt;


	&lt;h3&gt;Firefox&lt;/h3&gt;


	&lt;p&gt;The eagle-eyed amongst you will have noticed that we&#8217;re overriding part of the HtmlFormatter that ships with Rspec. This draws a lot of inspiration from the Textmate bundle for Rspec. the replacement method not only adds a link to any file displayed in a stacktrace but also specifies a protocol of gedit://. This protocol doesn&#8217;t exist unfortunately. If it did, this article would be half the length.&lt;/p&gt;


	&lt;p&gt;Anyway, we&#8217;ll create it and make Firefox understand it! Save this script as &#8220;gediturl&#8221; somewhere useful and ensure that it executable. A good place might be &lt;code&gt;/user/local/bin&lt;/code&gt; and that&#8217;s what I&#8217;ll be assuming.&lt;/p&gt;


&lt;pre class=&quot;blackboard&quot;&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;!/usr/bin/ruby&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; Copyright (c) 2004 - 2008 Beanlogic Limited&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; This file is part of gedit_on_rails.&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; gedit_on_rails is free software: you can redistribute it and/or modify&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; it under the terms of the GNU General Public License as published by&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; the Free Software Foundation, either version 3 of the License, or&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; (at your option) any later version.&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; gedit_on_rails is distributed in the hope that it will be useful,&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; GNU General Public License for more details.&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; You should have received a copy of the GNU General Public License&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; along with gedit_on_rails.  If not, see &amp;lt;http://www.gnu.org/licenses/&amp;gt;.&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; This file handles the openning of rspec examples &lt;/span&gt;

&lt;span class=&quot;Variable&quot;&gt;GEDIT&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;`&lt;/span&gt;which gedit&lt;span class=&quot;String&quot;&gt;`&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;chomp&lt;/span&gt;

url &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;ARGV&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;first&lt;/span&gt;

url &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; url[&lt;span class=&quot;Constant&quot;&gt;8&lt;/span&gt;..url.&lt;span class=&quot;Entity&quot;&gt;length&lt;/span&gt;]

file, line &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; url.&lt;span class=&quot;Entity&quot;&gt;split&lt;/span&gt;(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;?&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)

&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;Variable&quot;&gt;GEDIT&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;#{&lt;/span&gt;file&lt;span class=&quot;String&quot;&gt;}&lt;/span&gt;&lt;/span&gt; +&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;#{&lt;/span&gt;line&lt;span class=&quot;String&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;Open a new tab or window in firefox and type &lt;strong&gt;about:config&lt;/strong&gt; in the address bar. You might get a warning about messing about with the config. I wasn&#8217;t worried about that but if you are back up your Firefox profile before you continue.&lt;/p&gt;


	&lt;p&gt;You should be presented with a long list of configuration keys and values. Right click somewhere in this list and select New -&amp;gt; String. Give it a name of &lt;strong&gt;network.protocol-handler.app.gedit&lt;/strong&gt; and a value of &lt;strong&gt;/usr/local/bin/gediturl&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;Now when you run your spec in Gedit again and maybe one of the specs fail, the stacktrace for each fail will be presented as useful links that open the files in the trace in Gedit. Not only that it will move the cursor to correct line in that file. I was pretty pleased with myself when I did that because it makes Gedit a really useful tool for behavior driven development.&lt;/p&gt;


	&lt;h3&gt;Caveats&lt;/h3&gt;


	&lt;p&gt;I found Firefox fairly unpredictable when I added the protocol handler. It didn&#8217;t work at first but then worked after no apparent changes were made. If anyone experiences difficulties here and finds out why, please let me know and I&#8217;ll add it here.&lt;/p&gt;


	&lt;h3&gt;Conclusion&lt;/h3&gt;


	&lt;p&gt;Gnome Editor (gedit) could become a very powerful Ruby and Ruby on Rails &lt;span class=&quot;caps&quot;&gt;IDE&lt;/span&gt; given a little bit of work. I&#8217;m planning to start a project perhaps in the form of a Rubygem to empower gedit in this way. I think that then it could really challenge Textmate as a non-IDE alternative for Ruby development. We&#8217;re going to need a hell of a lot more than being able to run Rspec files with a keystroke so anybody who wants to help please get in touch. Specific areas of interest is plugin development for both Gedit and Firefox and whether they too could be bundled into a gem.&lt;/p&gt;


	&lt;p&gt;If I have made any mistakes or stupid assumptions or if I&#8217;ve just reinvented someone else&#8217;s wheel, please let me know and I&#8217;ll correct them.&lt;/p&gt;
          </content>  </entry>
</feed>
