<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Robby on Rails: Tag ajax</title>
    <link>http://www.robbyonrails.com/articles/tag/ajax</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>thoughts.sort_by{|t| t[:topic]}.collect </description>
    <item>
      <title>Designers, Developers, and the x_ Factor</title>
      <description>&lt;p&gt;Our team is lucky enough to be in a position where we have both designers &lt;span class="caps"&gt;AND&lt;/span&gt; developers working on the same code base in parallel.&lt;/p&gt;


	&lt;p&gt;Since Ruby on Rails adopts the Model-View-Control pattern for separating business logic from the presentation layer, we&amp;#8217;re able to give our designers a lot of breathing room to to design the interface, whether it&amp;#8217;s for interaction or aesthetic reasons. However, sometimes this breathing room has resulted in small bugs slipping into the application interface. In general, nothing disastrous, but each bug that slips into the queue, slows down the project and we want to avoid as much of that as possible.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;d like to share a few issues that we&amp;#8217;ve seen occur on various occasions, and then show you what we&amp;#8217;ve done to avoid them happening again.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Scenario #1:&lt;/strong&gt; The case of the changed &lt;code&gt;div&lt;/code&gt; id, (victim: designer)&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Designer adds a few &lt;span class="caps"&gt;HTML&lt;/span&gt; elements to the page, defines an &lt;code&gt;id&lt;/code&gt; on a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; tag and styles it with &lt;span class="caps"&gt;CSS&lt;/span&gt;.&lt;/li&gt;
		&lt;li&gt;A few days later, a developer needs to make some changes, tests it in their favorite browser and commits.&lt;/li&gt;
		&lt;li&gt;Later, the designer doesn&amp;#8217;t understand why the styling is all messed up. &amp;#8220;It &lt;em&gt;was&lt;/em&gt; working fine.&amp;#8221; &lt;/li&gt;
		&lt;li&gt;...minutes, hours&amp;#8230; go by where the designer tries to track down the issue. &amp;#8220;Oh! Someone renamed the &lt;code&gt;id&lt;/code&gt; in this &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; tag. Sigh.&amp;#8221; &lt;/li&gt;
		&lt;li&gt;Developer apologies, but explains that he needed to do it because he needed to make it work with his new &lt;span class="caps"&gt;RJS&lt;/span&gt; code.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;&lt;strong&gt;Scenario #2:&lt;/strong&gt; The case of the changed &lt;code&gt;div&lt;/code&gt; id, (victim: developer)&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Developer is implementing this cool new Ajax feature into the web application
	&lt;ul&gt;
	&lt;li&gt;The code relies on there being one or many &lt;span class="caps"&gt;HTML&lt;/span&gt; elements in the &lt;span class="caps"&gt;DOM&lt;/span&gt; with specific &lt;code&gt;id&lt;/code&gt; values defined.&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Example: &lt;code&gt;&amp;lt;div id="notification_message"&amp;gt;&lt;/code&gt;&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;A few days later, a designer is making some changes to the layout and needs to restyle some of the view that this &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; tag is defined. Designer decides to change the id to a different value for any variety of reasons. (or perhaps they changed it to use a class instead of styling it by the id). Often times, we don&amp;#8217;t know who set the id or class&amp;#8230; and many times the developers aren&amp;#8217;t savvy enough with &lt;span class="caps"&gt;HTML&lt;/span&gt; and designers end up cleaning things up a bit. &lt;/li&gt;
		&lt;li&gt;Later, code is checked in and designer didn&amp;#8217;t notice that the Ajax was now breaking as they weren&amp;#8217;t focusing on just the layout.&lt;/li&gt;
		&lt;li&gt;Day or two later, developer sees bug, &amp;#8220;Feature X isn&amp;#8217;t working, throwing JavaScript error&amp;#8230;&amp;#8221; &lt;/li&gt;
		&lt;li&gt;Developer is confused, &amp;#8220;Hey, that was working! What happened?&amp;#8221; &lt;/li&gt;
		&lt;li&gt;Developer tracks down the problem, discusses with designer, they figure out a solution. Problem solved.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;I could outline a few other examples, but I really wanted to highlight these two types of situations, as our team has seen this happen on several occasions. Luckily, we&amp;#8217;ve learned through these experiences and have taken some measures to try and avoid them in the future.&lt;/p&gt;


	&lt;h2&gt;Moving forward (together)&lt;/h2&gt;


	&lt;p&gt;Both of the examples above, were essentially the same problem, but resulted in problems for a different role in the design and development cycle. While, I&amp;#8217;ve definitely been the victim of #2 several times myself, I know that I&amp;#8217;ve also been the guilty of #1. So, what can we do as designers and developers to work with each other without causing these little problems from occurring? (remember: many little problems can add up to a lot of wasted time spent resolving them)&lt;/p&gt;


	&lt;p&gt;Several months ago, I had a meeting with &lt;a href="http://chriszgriffin.com/"&gt;Chris&lt;/a&gt; (User Interface Designer) and &lt;a href="http://blog.imperialdune.com/"&gt;Graeme&lt;/a&gt; (Lead Architect/Developer) to discuss this very problem. At the time, we were implementing a lot of Ajax into an application and were occasionally running into Scenario #2. We discussed a few possible ways of communicating that, &amp;#8220;yes, this div id should &lt;span class="caps"&gt;NOT&lt;/span&gt; be changed (without talking to a developer first)!&amp;#8221;&lt;/p&gt;


	&lt;h3&gt;Idea 1: Comment our &amp;#8220;special&amp;#8221; &lt;span class="caps"&gt;HTML&lt;/span&gt; elements&lt;/h3&gt;


	&lt;p&gt;We discussed using ERb comments in our views to do something like the following.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
  &amp;lt;% # no seriously, please don't change this id, it's needed for some Ajax stuff %&amp;gt;
  &amp;lt;div id="notification_message"&amp;gt;
    ...
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;We all agreed that, while effective, it was going to clutter up our &lt;span class="caps"&gt;RHTML&lt;/span&gt; code more than any of us desired.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Team Response:&lt;/strong&gt; &lt;em&gt;Meh.&lt;/em&gt;&lt;/p&gt;


	&lt;h3&gt;Idea 2: Reserve id&amp;#8217;s for developers&lt;/h3&gt;


	&lt;p&gt;Another idea that came up, was to ask that designers only use classes and ids wold be used by the developers when they needed it.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
  &amp;lt;div id="developer_terriroty" class="designer_territory"&amp;gt;
    ...
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Chris pointed out that this wasn&amp;#8217;t an ideal solution as there is a distinct case for when to use ids versus classes.. and he is very strict about adhering to the &lt;span class="caps"&gt;HTML&lt;/span&gt;/CSS standards.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Team Response&lt;/strong&gt;: &lt;em&gt;Not hot about it&amp;#8230;&lt;/em&gt;&lt;/p&gt;


	&lt;h3&gt;Idea 3: Naming convention for Ajax-dependent elements&lt;/h3&gt;


	&lt;p&gt;The third idea that was discussed, was specifying a naming convention for any elements that were needed by our Ajax code. We played around on the whiteboard with some ideas and settled on the idea that we&amp;#8217;d prefix our id&amp;#8217;s with something easy to remember for both designers and developers.&lt;/p&gt;


	&lt;p&gt;We agreed on&amp;#8230; &lt;code&gt;x_&lt;/code&gt; (x underscore), which would make an element id look something like this:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
  &amp;lt;div id="x_notification_message"&amp;gt;
    ...
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;&lt;strong&gt;x == ajax&lt;/strong&gt;... get it?&lt;/p&gt;


	&lt;p&gt;While this adds the strain of typing two more characters to much of our &lt;span class="caps"&gt;RJS&lt;/span&gt; code, we don&amp;#8217;t run into Scenario #2 very often anymore.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
  render :update do |page|
    page[:x_notification_message] = 'Something exciting happened... and this is your notification!'
    page[:x_notification_message].visual_effect :highlight
  end
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;or in client-side JavaScript (where we also use this)...&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
  $('x_notification_message').do_something
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;I find that this helps our team keep a clear distinction between what can and shouldn&amp;#8217;t be changed in the views by our designers. Sometimes they have a good reason to do so, but they know that if there is &lt;code&gt;x_&lt;/code&gt;, then they should ask one of the developers on the team for assistance in renaming it without causing any problems in the application. It also allows our designers to add classes to these elements, or style the id that we&amp;#8217;ve defined.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Team Response&lt;/strong&gt;: &lt;em&gt;Wow, was that all we needed to agree on? Hooray!&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;This leads me to some other problems that have/may come up, but I&amp;#8217;ll discuss that in my next post on this topic, when I&amp;#8217;ll show you how we can use RSpec to avoid these sorts of designer versus developer problems.&lt;/p&gt;


	&lt;p&gt;If you&amp;#8217;re working in a similar environment, how are your designers and developers working, together, in perfect harmony?&lt;/p&gt;


	&lt;p&gt;Until next time, remember to &lt;a href="http://www.robbyonrails.com/articles/2007/05/23/hug-your-designer-day-part-2"&gt;hug your designer&lt;/a&gt;. ...and if you&amp;#8217;re still having developer &lt;em&gt;design&lt;/em&gt; your applications, consider hiring a designer. ;-)&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;:&lt;/strong&gt; changed examples after a few comments about using div_for as another solution. (see comments for details)&lt;/p&gt;
</description>
      <pubDate>Wed, 01 Aug 2007 00:39:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:bcf3fb50-6b05-48cd-830f-43144d80c243</guid>
      <author>Robby Russell</author>
      <link>http://www.robbyonrails.com/articles/2007/08/01/designers-developers-and-the-x_-factor</link>
      <category>Ruby on Rails</category>
      <category>Programming</category>
      <category>PLANET ARGON</category>
      <category>rails</category>
      <category>ajax</category>
      <category>development</category>
      <category>rubyonrails</category>
      <category>agile</category>
      <category>design</category>
      <category>process</category>
      <category>views</category>
      <category>designers</category>
      <category>developers</category>
      <category>rhtml</category>
      <category>erb</category>
      <category>conventions</category>
      <category>bugs</category>
    </item>
    <item>
      <title>Speaking at Ruby on Rails Seminar in October</title>
      <description>&lt;p&gt;It must be summer and I must be &lt;a href="http://www.flickr.com/photos/robbyrussell/180170091/in/set-72157594193154368/"&gt;busy&lt;/a&gt; as I haven&amp;#8217;t been posting much of anything on my blog over the past two months. Please forgive me! :-)&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://www.flickr.com/photos/robbyrussell/191905271/" title="Photo Sharing"&gt;&lt;img src="http://static.flickr.com/47/191905271_ea8004504e_m.jpg" width="240" height="130" alt="Lincoln City beach at sunset" /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Just a quick mention that I&amp;#8217;ve been invited to speak at the &lt;a href="http://www.rubyonrailsseminar.com/"&gt;Ruby on Rails Seminar&lt;/a&gt;, to be held on Tuesday, October 3, colocated with the &lt;a href="http://www.ajaxworldexpo.com/"&gt;AJAXWorld Conference &amp;#38; Expo&lt;/a&gt;, October 2-4, at the Santa Clara Convention Center, Santa Clara, CA.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;ll be presenting a new talk with an oh-so-familiar topic&amp;#8230; &lt;a href="http://www2.sys-con.com/eventspopups/r05Russell.html"&gt;Rails meets the Legacy-World&lt;/a&gt;. It&amp;#8217;ll be nice to get to share the stage with some of my favorite Rails colleagues&amp;#8230; such as &lt;a href="http://blog.lavalamp.ca/"&gt;Steven Baker&lt;/a&gt;, &lt;a href="http://objo.com/"&gt;Joe O&amp;#8217;Brien&lt;/a&gt;, and &lt;a href="http://www.michaelbuffington.com/"&gt;Michael Buffington&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;For more information on the event, visit &lt;a href="http://www.rubyonrailsseminar.com"&gt;http://www.rubyonrailsseminar.com&lt;/a&gt;.&lt;/p&gt;
</description>
      <pubDate>Thu, 20 Jul 2006 17:29:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:f9ee339d-7c09-4bbc-bb6a-009341f77241</guid>
      <author>Robby Russell</author>
      <link>http://www.robbyonrails.com/articles/2006/07/20/speaking-at-ruby-on-rails-seminar-in-october</link>
      <category>ajax</category>
      <category>ajax</category>
      <category>legacy</category>
      <category>legacy</category>
      <category>rubyonrails</category>
      <category>rubyonrails</category>
      <category>speaking</category>
      <category>speaking</category>
      <category>seminar</category>
      <category>seminar</category>
      <category>conference</category>
      <category>conference</category>
    </item>
    <item>
      <title>Fluxiom Unleashed!</title>
      <description>&lt;p&gt;While in Vancouver BC, I had the privilege of meeting Thomas Fuchs, the guy behind &lt;a href="http://script.aculo.us/"&gt;script.aculo.us&lt;/a&gt; and &lt;a href="http://mir.aculo.us"&gt;mir.aculo.us&lt;/a&gt;. His company &lt;a href="http://www.wollzelle.com/"&gt;Wollzelle&lt;/a&gt; has just launched their new web service called, &lt;a href="http://www.fluxiom.com"&gt;fluxiom&lt;/a&gt;. I&amp;#8217;ve seen the videos and saw him demo some of it at &lt;a href="http://www.canadaonrails.org"&gt;Canada on Rails&lt;/a&gt;. The stuff that they&amp;#8217;ve trained the browser to do with &lt;span class="caps"&gt;AJAX&lt;/span&gt; is unbelievable and it&amp;#8217;s also built on Ruby on Rails! :-)&lt;/p&gt;


	&lt;p&gt;They are offering a &lt;strong&gt;free 30 day trial&lt;/strong&gt;... so go check it out!&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://www.fluxiom.com/"&gt;http://www.fluxiom.com/&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;
</description>
      <pubDate>Thu, 20 Apr 2006 08:05:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:4947c5c8-2724-4427-8799-a568a0ada659</guid>
      <author>Robby Russell</author>
      <link>http://www.robbyonrails.com/articles/2006/04/20/fluxiom-unleashed</link>
      <category>rails</category>
      <category>ajax</category>
      <category>fluxiom</category>
    </item>
    <item>
      <title>When TSearch2 Met AJAX</title>
      <description>&lt;p&gt;Last night, a local &lt;span class="caps"&gt;PDX&lt;/span&gt;.rb-ist, asked about full text searching in &lt;a href="http://www.postgresql.org"&gt;PostgreSQL&lt;/a&gt;. I pointed him to &lt;a href="http://rubyurl.com/4g6"&gt;TSearch2&lt;/a&gt;, which is a nice little addon to handle full text searching with indexing, ranking, highlighting, etc. To my knowledge, it&amp;#8217;s the closest to a google-like search that you can get with PostgreSQL. Some people in #postgresql (irc.freenode.net), said that you can build custom functions that will allow you to quote content, and do other fun stuff within your search string. We can discuss that another time.&lt;/p&gt;


	&lt;p&gt;After thinking it over, I thought, &amp;#8220;why not put ajax on top of a full text search and see what it can do?&amp;#8221;&lt;/p&gt;


	&lt;p&gt;The first question, where was I going to get a bunch of content that I could search through and have it be somewhat meaningful for the public, if I decide to put it up as a demo page. The RubyOnRails mailing list came to mind, so after seeing that I couldn&amp;#8217;t download the full archive from the rails mailman page (at least not that I could tell), I decided that I would just import my Maildir for that mailing list.&lt;/p&gt;


	&lt;p&gt;This added another initial step. What would be a good way to import the 13,000~ emails that I had in the folder?&lt;/p&gt;


	&lt;p&gt;I knew that worst case, I could find a module on &lt;span class="caps"&gt;CPAN&lt;/span&gt; and build a perl script to import it&amp;#8230; since I didn&amp;#8217;t see anything in the standard ruby library. Then I found &lt;a href="http://rubyurl.com/kwO"&gt;TMail&lt;/a&gt;. Someone said that they think ActionMailer uses TMail as well.&lt;/p&gt;


	&lt;p&gt;The resulting quick and dirty script became:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;#!/usr/bin/env ruby&lt;/span&gt;

&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;tmail&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;rubygems&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;postgres&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;dbi&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="ident"&gt;conn&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;DBI&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;connect&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;DBI:Pg:database=rails_mailinglist;host=localhost;port=5403&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;username&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;password&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt;

&lt;span class="constant"&gt;MAILBOX&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;.MailingLists.Ruby.RubyOnRails&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="ident"&gt;sql&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;INSERT INTO archives (sender, recipient, subject, body) VALUES (?,?,?,?)&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="attribute"&gt;@sth&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;conn&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;prepare&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;sql&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

&lt;span class="ident"&gt;box&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;TMail&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Maildir&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;MAILBOX&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

&lt;span class="ident"&gt;box&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;port&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
        &lt;span class="ident"&gt;mail&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;TMail&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Mail&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;port&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
        &lt;span class="ident"&gt;p&lt;/span&gt; &lt;span class="ident"&gt;mail&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;subject&lt;/span&gt;
        &lt;span class="attribute"&gt;@sth&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;execute&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;mail&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;from&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;mail&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;mail&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;subject&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;mail&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;body&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="ident"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Not rocket science. :-)&lt;/p&gt;


	&lt;p&gt;Okay, so I let that start running through the mailing list emails that I have, and opened up another tab in &lt;a href="http://iterm.sourceforge.net/"&gt;iTerm&lt;/a&gt; and typed our friend, &lt;code&gt;rails archives&lt;/code&gt; followed by &lt;code&gt;cd archives&lt;/code&gt;. The next step was to modify the &lt;code&gt;config/database.yml&lt;/code&gt; file.&lt;/p&gt;


	&lt;p&gt;(you all know how to do that, right?)&lt;/p&gt;


	&lt;p&gt;Okay, you should still be with me&amp;#8230;so far.&lt;/p&gt;


	&lt;p&gt;After I got my database settings in place, I ran &lt;code&gt;./script/generate scaffold Archive&lt;/code&gt; and watched it created my new filles to play with.&lt;/p&gt;


&lt;code&gt;./script/server&lt;/code&gt; and I am looking at the first several emails that are in my RubyOnRails mailing list folder. I notice that the first one is the confirmation email from the day that I signed up on the mailing list. &lt;b&gt;Mon, 24 Jan 2005 16:00:14 +0000 (GMT) &lt;/b&gt;. So, I delete that email and the &amp;#8216;welcome to..&amp;#8217; one so that no one sees my mailman password/confirm info. ;-)

	&lt;p&gt;&lt;b&gt;Installation&lt;/b&gt;&lt;/p&gt;


	&lt;p&gt;So, Rails has no problem with the data. So, I then head over to the &lt;a href="http://rubyurl.com/4g6"&gt;Tsearch2&lt;/a&gt; site and look for some installation information. I walked through &lt;a href="http://rubyurl.com/Crk"&gt;this walkthrough&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;&lt;b&gt;Database Structure&lt;/b&gt;&lt;/p&gt;


	&lt;p&gt;For this example, I kept it pretty simple for the database structure. I believe the create script was:&lt;/p&gt;


&lt;code&gt;
&lt;pre&gt;
CREATE TABLE archives (
  id SERIAL PRIMARY KEY,
  sender VARCHAR(255),
  recipient VARCHAR(255),
  subject VARCHAR(255),
  body TEXT
);
&lt;/pre&gt;
&lt;/code&gt;

	&lt;p&gt;The rest was basically following through with those steps and building the triggers and functions around the &lt;code&gt;subject&lt;/code&gt; and &lt;code&gt;body&lt;/code&gt; fields in the table.&lt;/p&gt;


	&lt;p&gt;To use the tsearch2 functionality, I used &lt;code&gt;find_by_sql&lt;/code&gt; rather than using just &lt;code&gt;find&lt;/code&gt;.&lt;/p&gt;


&lt;code&gt;
&lt;pre&gt;
@archives = Archive.find_by_sql("SELECT id, headline(body,q) as headline, body, rank(idxfti,q) as rank, sender, subject  FROM archives, to_tsquery('#{@str}') AS q WHERE idxfti @@ q ORDER BY rank(idxfti,q) DESC LIMIT 100") 
&lt;/pre&gt;
&lt;/code&gt;

	&lt;p&gt;The &lt;code&gt;@str&lt;/code&gt; variable is a value that I build based on the string(s) that the user is typing in the search field. &lt;b&gt;Tsearch2&lt;/b&gt; requires that you sepeare each string with a pipe (&lt;code&gt;|&lt;/code&gt;). So, I put in a few checks on the string that was being passed to my method in my controller by &lt;span class="caps"&gt;AJAX&lt;/span&gt;. (I&amp;#8217;ll let you take the time to figure out how to get &lt;span class="caps"&gt;AJAX&lt;/span&gt; in Rails working and watching a text field&amp;#8230; it&amp;#8217;s not hard to find info on google. ) :-)&lt;/p&gt;


	&lt;p&gt;&lt;b&gt;The end result?&lt;/b&gt;&lt;/p&gt;


	&lt;p&gt;I will warn you that this does&amp;#8217;t work in all browsers, some IE people said they had issues&amp;#8230; and I spent enough time tinkering with it to just settle with this for now. :-)&lt;/p&gt;


	&lt;p&gt;I present&amp;#8230; &lt;a href="http://railslist.robbyonrails.com/archives/"&gt;fulltext searching with PostgreSQL on Rails&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;There are approx 13,000 emails in the system, so I put a limit on the number of responses that show up to 100.&lt;/p&gt;


	&lt;p&gt;&lt;b&gt;My Thoughts&lt;/b&gt;&lt;/p&gt;


	&lt;p&gt;Well, it was an interesting concept. I&amp;#8217;m not a big fan of livesearching, it doesn&amp;#8217;t really seem to buy us much when working with this sort of data. I do find live auto-completion to be quite useful though. It&amp;#8217;s not practical to have &lt;span class="caps"&gt;AJAX&lt;/span&gt; peg the database every second as I type for new content and it&amp;#8217;s obvious that a database with that much content is not going to respond as snappy as you would hope. However, I decided to compare the speed to searching in Thunderbird and Evolution. From my sophesticated benchmarking suite (my imaginary stop watch)...&lt;/p&gt;


	&lt;p&gt;&lt;b&gt;&lt;span class="caps"&gt;AJAX&lt;/span&gt; won!&lt;/b&gt;&lt;/p&gt;


	&lt;p&gt;okay, I should be fair and say, &lt;b&gt;Tsearch2 won&lt;/b&gt; as it is doing all the heavy lifting.&lt;/p&gt;


	&lt;p&gt;Enjoy!&lt;/p&gt;
</description>
      <pubDate>Sun, 21 Aug 2005 21:48:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:58dfd916704b1d543e5e6dcdcde99efb</guid>
      <author>Robby Russell</author>
      <link>http://www.robbyonrails.com/articles/2005/08/21/when-tsearch2-met-ajax</link>
      <category>Ruby on Rails</category>
      <category>PostgreSQL</category>
      <category>ajax</category>
      <category>tsearch2</category>
      <category>postgresql</category>
      <category>rails</category>
    </item>
  </channel>
</rss>
