<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mission Data Blog</title>
	<atom:link href="http://www.missiondata.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.missiondata.com/blog</link>
	<description>Louisville-based Web Development &#038; Software Engineering</description>
	<lastBuildDate>Tue, 18 May 2010 14:24:23 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Painting our portrait of Marvin Chartoff</title>
		<link>http://www.missiondata.com/blog/news/232/painting-our-portrait-of-marvin-chartoff/</link>
		<comments>http://www.missiondata.com/blog/news/232/painting-our-portrait-of-marvin-chartoff/#comments</comments>
		<pubDate>Tue, 18 May 2010 14:23:02 +0000</pubDate>
		<dc:creator>joev</dc:creator>
				<category><![CDATA[News]]></category>

		<guid isPermaLink="false">http://www.missiondata.com/blog/?p=232</guid>
		<description><![CDATA[ Once upon a time, it was said that “Every man&#8217;s work, whether it be literature or music or pictures or architecture or anything else, is always a portrait of himself.” To that same end, when asked to create a portrait of a man, each person will draw that image with a hand and eye [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignnone size-medium wp-image-233" style="float:left; margin:0 15px 15px 0;" title="10857_1270638016143_1535662917_716224_5238311_n" src="http://www.missiondata.com/blog/wp-content/uploads/2010/05/10857_1270638016143_1535662917_716224_5238311_n-300x238.jpg" alt="10857_1270638016143_1535662917_716224_5238311_n" width="220" height="158" /> Once upon a time, it was said that “Every man&#8217;s work, whether it be literature or music or pictures or architecture or anything else, is always a portrait of himself.” To that same end, when asked to create a portrait of a man, each person will draw that image with a hand and eye loaded by a wealth of their own unique memories and perspectives. As we here at Mission Data create our portraits of Marvin Chartoff, some of us will think partially of a quiet, diligent, grounded and light-humored man that was able to maintain a balanced level of multitasking, both in his personal and professional life, that would have left most people clamoring over themselves. And here was an individual who could do it all with barely making a sound, often surprising with his hereto unknown presence in the office. Quite simply: it amazed us.</p>
<p>There will be many joining us in mourning during this period. We know that many friends, family, colleagues, and acquaintances will be creating an image this week, and in the coming days, with a hand burdened by grief and an eye weighted with tears. A man walks through life painting a portrait, not of what he would, could, or should have done but of what he did. So, it is from there that we draw our inspiration &#8211; with a smile on our face. A smile because we had the great fortune and opportunity to connect with and know such a wonderful human being. It&#8217;s the impressions that he left with us that will guide our hand and eyes. And, it&#8217;s for those very impressions that we&#8217;ll be painting our portrait of Marvin Chartoff with a smile on his face. We hope that you&#8217;ll join us in that, too.</p>
<style type="text/css">
#outbrain_container_0_bottom { display:none;}
</style>
]]></content:encoded>
			<wfw:commentRss>http://www.missiondata.com/blog/news/232/painting-our-portrait-of-marvin-chartoff/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Chuck Olmstead Memorial Fund</title>
		<link>http://www.missiondata.com/blog/news/site-launch/191/chuck-olmstead-memorial-fund/</link>
		<comments>http://www.missiondata.com/blog/news/site-launch/191/chuck-olmstead-memorial-fund/#comments</comments>
		<pubDate>Mon, 22 Mar 2010 18:53:54 +0000</pubDate>
		<dc:creator>adelaides</dc:creator>
				<category><![CDATA[Site Launch]]></category>

		<guid isPermaLink="false">http://www.missiondata.com/blog/?p=191</guid>
		<description><![CDATA[Chuck Olmstead, a former news reporter for WHAS 11 in Louisville, KY, passed away from a brain aneurysm on March 9th, 2009.  His wife and children started the Chuck Olmstead Memorial Fund to honor his life and memory.  The monies from the Fund provide support of community education and screenings so as to help those [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: left;">Chuck Olmstead, a former news reporter for WHAS 11 in Louisville, KY, passed away from a brain aneurysm on March 9th, 2009.  His wife and children started the Chuck Olmstead Memorial Fund to honor his life and memory.  The monies from the Fund provide support of community education and screenings so as to help those at risk detect aneurysms before they rupture.  A partnership with Norton Neuroscience Institute has been made in hopes of bringing a mobile unit to the uninsured or those unable to travel to hospitals for screenings.</p>
<p style="text-align: left;">We have been fortunate to get to know members of the Olmstead family.  Over the past year they have been inundated with calls from supporters and those interested in finding out how they can help.  It was time The Chuck Olmstead Memorial Fund had an informational website to which the Olmstead family could direct supporters regarding events, resources and donations.</p>
<p style="text-align: left;">We were honored to design and build a platform for the fund: <a href="http://chuckolmsteadfund.com">http://chuckolmsteadfund.com/</a> that provided for simple and clean navigation for the diverse population of likely visitors.  The website features a multitude of information along with an event calendar, resource videos, a contact form, and a portal for donations.</p>
<p style="text-align: left;">The site launched in time to accept donations for two successful telethons (which raised over $40,000 dollars) and a memorial walk in Louisville!</p>
<p style="text-align: left;">Please visit the site to keep up-to-date on the progress of the Olmstead family&#8217;s mission in fighting this disease for others.  Please mark your calendars and join the Olmstead&#8217;s in support of the Fund as there will be a race in honor of Chuck at Churchill Downs on May 15, 2010.  Mission Data will certainly be there!</p>
<p style="text-align: center;"><img class="size-full wp-image-199 aligncenter" title="Chuck-Olmstead-Memorial-Fund-Logo" src="http://www.missiondata.com/blog/wp-content/uploads/2010/03/Chuck-Olmstead-Memorial-Fund-Logo3.jpg" alt="Chuck-Olmstead-Memorial-Fund-Logo" width="271" height="105" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.missiondata.com/blog/news/site-launch/191/chuck-olmstead-memorial-fund/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Introduction to the Social Web</title>
		<link>http://www.missiondata.com/blog/news/156/introduction-to-the-social-web/</link>
		<comments>http://www.missiondata.com/blog/news/156/introduction-to-the-social-web/#comments</comments>
		<pubDate>Thu, 11 Feb 2010 20:12:53 +0000</pubDate>
		<dc:creator>adelaides</dc:creator>
				<category><![CDATA[News]]></category>

		<guid isPermaLink="false">http://www.missiondata.com/blog/?p=156</guid>
		<description><![CDATA[Engaging with your clients and community through the Social Web is powerful and necessary. On February 11th, two of our team members, Annastasia Webster, Business Analyst and Jim Cook, VP of Interactive Strategy and Services partnered with The Center for Nonprofit Excellence (CNPE) to discuss the Social Web.]]></description>
			<content:encoded><![CDATA[<p>Engaging with your clients and community through the Social Web is powerful and necessary.  On February 11th, two of our team members, Annastasia Webster, Business Analyst and Jim Cook, VP of Interactive Strategy and Services partnered with The Center for Nonprofit Excellence (CNPE) to discuss the Social Web.</p>
<p>This introductory course was intimate and collaborative.  The attendees learned about the different aspects of the Social Web and how to apply them to their nonprofit organization.  The Social Web is not a fad.  Our goal for this course was to help our partners navigate through this intricate and forever changing space.</p>
<p>We will continue to partner with CNPE to offer courses that will dive further into specific types of Social Media.</p>
<p><a href="http://www.bizjournals.com/louisville/calendar/">http://www.bizjournals.com/louisville/calendar/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.missiondata.com/blog/news/156/introduction-to-the-social-web/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Business First article spotlights Mission Data</title>
		<link>http://www.missiondata.com/blog/news/154/business-first-article-spotlights-mission-data/</link>
		<comments>http://www.missiondata.com/blog/news/154/business-first-article-spotlights-mission-data/#comments</comments>
		<pubDate>Fri, 30 Oct 2009 16:01:18 +0000</pubDate>
		<dc:creator>adelaides</dc:creator>
				<category><![CDATA[News]]></category>

		<guid isPermaLink="false">http://www.missiondata.com/blog/?p=154</guid>
		<description><![CDATA[It has been a busy few years.  The Mission Data team has grown by 50% and our revenue has increased by 20% each year. Focusing on strategic partnerships has been instrumental in growing our business.
In an interview by Business First, Stuart Gavurin, CEO of Mission Data, spoke to our talent and our offerings.
Read the full [...]]]></description>
			<content:encoded><![CDATA[<p>It has been a busy few years.  The Mission Data team has grown by 50% and our revenue has increased by 20% each year. Focusing on strategic partnerships has been instrumental in growing our business.</p>
<p>In an interview by Business First, Stuart Gavurin, CEO of Mission Data, spoke to our talent and our offerings.</p>
<p><a href="http://www.louisville.bizjournals.com/louisville/stories/2009/11/02/smallb1.html">Read the full Business First article</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.missiondata.com/blog/news/154/business-first-article-spotlights-mission-data/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Presentation at the Kentucky Association of Realtors Annual Conference</title>
		<link>http://www.missiondata.com/blog/news/152/presentation-at-the-kentucky-association-of-realtors-annual-conference/</link>
		<comments>http://www.missiondata.com/blog/news/152/presentation-at-the-kentucky-association-of-realtors-annual-conference/#comments</comments>
		<pubDate>Thu, 24 Sep 2009 21:35:44 +0000</pubDate>
		<dc:creator>adelaides</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[presentation]]></category>
		<category><![CDATA[strategy]]></category>

		<guid isPermaLink="false">http://www.missiondata.com/blog/?p=152</guid>
		<description><![CDATA[Mission Data recently designed and developed the new Kentucky Association of Realtors (KAR) website, check it out: www.kar.com! We had a blast working with the KAR team and collaborating on a website that would work well for them, their membership and their visitors.
Our work with KAR led to a request for Mission Data to present [...]]]></description>
			<content:encoded><![CDATA[<p>Mission Data recently designed and developed the new Kentucky Association of Realtors (KAR) website, check it out: <a href="http://www.kar.com/">www.kar.com</a>! We had a blast working with the KAR team and collaborating on a website that would work well for them, their membership and their visitors.</p>
<p>Our work with KAR led to a request for Mission Data to present at their annual convention and expo. Todd Budnikas, Creative Director for Mission Data and Marvin Chartoff, VP of Managed Services gave a talk about Website Trends and Design Strategies. We were honored to have the opportunity to speak to realtors about strategies they can use to attract more business and influence their existing clients. Realtors are in a competitive space, the use of the web, social media and mobile devices is critical to conducting and attracting business.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.missiondata.com/blog/news/152/presentation-at-the-kentucky-association-of-realtors-annual-conference/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Showing progress using dd</title>
		<link>http://www.missiondata.com/blog/system-administration/87/showing-progress-using-dd/</link>
		<comments>http://www.missiondata.com/blog/system-administration/87/showing-progress-using-dd/#comments</comments>
		<pubDate>Wed, 16 Sep 2009 15:04:39 +0000</pubDate>
		<dc:creator>steveny</dc:creator>
				<category><![CDATA[System Administration]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://www.missiondata.com/blog/linux/87/showing-progress-using-dd/</guid>
		<description><![CDATA[One of the frustrating behaviors of dd is that it provides no feedback about what it is doing.  It does however provide a signal (USR1) that you can send to the process that will dump the current progress.  Open a new terminal (I use screen) and type:

while true; do kill -USR1 `pidof dd`; [...]]]></description>
			<content:encoded><![CDATA[<p>One of the frustrating behaviors of <a href="http://en.wikipedia.org/wiki/Dd_%28Unix%29">dd</a> is that it provides no feedback about what it is doing.  It does however provide a signal (USR1) that you can send to the process that will dump the current progress.  Open a new terminal (I use screen) and type:</p>
<pre>
<code>while true; do kill -USR1 `pidof dd`; sleep 2; done</code>
</pre>
<p>(NOTE: if `pidof dd` doesn&#8217;t work for you, just use the process id directly)</p>
<p>Switch back to the terminal where dd is running and you should see:</p>
<pre>
<code>9902751744 bytes (9.9 GB) copied, 732.883 s, 13.5 MB/s
9469+0 records in
9468+0 records out
9927917568 bytes (9.9 GB) copied, 734.914 s, 13.5 MB/s
9496+0 records in
9495+0 records out
9956229120 bytes (10 GB) copied, 736.941 s, 13.5 MB/s</code>
</pre>
<p>updating every couple of seconds.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.missiondata.com/blog/system-administration/87/showing-progress-using-dd/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mission Data awarded the prestigious Alfred P. Sloan Award</title>
		<link>http://www.missiondata.com/blog/news/158/mission-data-awarded-the-prestigious-alfred-p-sloan-award/</link>
		<comments>http://www.missiondata.com/blog/news/158/mission-data-awarded-the-prestigious-alfred-p-sloan-award/#comments</comments>
		<pubDate>Wed, 19 Aug 2009 14:44:02 +0000</pubDate>
		<dc:creator>adelaides</dc:creator>
				<category><![CDATA[News]]></category>

		<guid isPermaLink="false">http://www.missiondata.com/blog/?p=158</guid>
		<description><![CDATA[Mission Data has been selected as a winner of the 2009 Alfred P. Sloan Awards for Business Excellence in Workplace Flexibility in the greater Louisville area!
This prestigious award recognizes employers that are successfully using workplace flexibility to meet both employer and employee goals. As a winner, Mission Data ranks in the top 20% &#8212; the [...]]]></description>
			<content:encoded><![CDATA[<p>Mission Data has been selected as a winner of the 2009 Alfred P. Sloan Awards for Business Excellence in Workplace Flexibility in the greater Louisville area!</p>
<p>This prestigious award recognizes employers that are successfully using workplace flexibility to meet both employer and employee goals. As a winner, Mission Data ranks in the top 20% &#8212; the 80th percentile &#8212; of employers nationally in terms of flexible work programs, policies and culture.</p>
<p>The Alfred P. Sloan Awards for Business Excellence in Workplace Flexibility are part of the When Work Works project, an ongoing initiative of Families and Work Institute, the Institute for a Competitive Workforce (an affiliate of the U.S. Chamber of Commerce), and the Twiga Foundation. Through When Work Works, these partner organizations provide research, resources, and recognition to employers nationwide. The project shares the results of research on creating effective and flexible workplaces that meet the needs of the 21st century.</p>
<p>We are honored to receive this award. Workplace flexibility is an integral part of our business practices.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.missiondata.com/blog/news/158/mission-data-awarded-the-prestigious-alfred-p-sloan-award/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Treetop: Grammar&#8217;s Cool</title>
		<link>http://www.missiondata.com/blog/web-development/85/treetop-grammars-cool/</link>
		<comments>http://www.missiondata.com/blog/web-development/85/treetop-grammars-cool/#comments</comments>
		<pubDate>Wed, 13 Feb 2008 01:27:39 +0000</pubDate>
		<dc:creator>darrend</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.missiondata.com/blog/uncategorized/85/treetop-grammars-cool/</guid>
		<description><![CDATA[Treetop was one of the more exciting projects I saw at last year&#8217;s RubyConf. Nathan Sobo&#8217;s Treetop talk is available online and I urge you to watch it. Nathan did a great job of explaining the basics of syntactic analysis, and then got into the specifics of using Treetop&#8217;s implementation of parsing expression grammars to [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://treetop.rubyforge.org/">Treetop</a> was one of the more exciting projects I saw at last year&#8217;s RubyConf. <a href="http://rubyconf2007.confreaks.com/d1t1p5_treetop.html">Nathan Sobo&#8217;s Treetop talk</a> is available online and I urge you to watch it. Nathan did a great job of explaining the basics of syntactic analysis, and then got into the specifics of using Treetop&#8217;s implementation of <a href="http://en.wikipedia.org/wiki/Parsing_expression_grammar">parsing expression grammars</a> to put the concepts to work. </p>
<p>Treetop appeared to gather all the concepts together into an understandable domain specific language. All of the tokenization and node structure can go into a single file, and the interactive nature of Ruby makes for the perfect sand box. I felt like I could get somewhere if I invested just an hour into this. I was happy to find that my impressions were correct. </p>
<p>After a short time I had caught on enough to start writing my own code. Once over the hump the rest was easy. I was able to write and test a Treetop grammar for parsing CSV files within a few hours. I chose CSV parsing because I was already familiar with the format, and I could compare my implementation to not just one but two existing Ruby libraries.<br />
<span id="more-85"></span></p>
<pre><code>commaseparatedfile.treetop</code></pre>
<pre><code>grammar CommaSeparatedFile
  rule lines
    line (newline line)*
    {
      def values
        vals = []
        vals &lt;&lt; line.values
        more.elements.each { |additional| vals &lt;&lt; additional.line.values }
        vals
      end
    }
  end

  rule line
    valueline / emptyline
  end

  rule emptyline
    '' {
      def values
        []
      end
    }
  end

  rule valueline
    leading:(value separator)* trailing:value
    {
      def values
        list = []
        list += leading.elements.collect { |lead| lead.value.text_value } if leading
        list &lt;&lt; trailing.text_value if trailing
        list
      end
    }
  end

  rule value
    quotedvalue / nakedvalue
  end

  rule quotedvalue
    '"' wrapped:( !'"' . / '""' )* '"' {
      def text_value
        wrapped.text_value.gsub(/""/,'"')
      end
    }
  end

  rule nakedvalue
    (!(separator / newline ) .)*
  end

  rule separator
    ','
  end

  rule newline
    [\n]
  end
end</code></pre>
<p>One concept that became clear to me is that the tokens that are defined in the grammar are objects in the resulting tree returned after input is parsed. Ruby code embedded in the Treetop&#8217;s node definitions are added as methods to the object declared by that node.</p>
<p>In the simple harness below, the <code>lines</code> object returned from the parse call below is the object representation of the <code>rule lines</code> node above, defined as the root of the parse tree. The <code>values</code> method I call below is defined above in the definition of the <code>lines</code> node.</p>
<pre><code>require 'rubygems'
require 'treetop'
require 'commaseparatedfile' 

parser = CommaSeparatedFileParser.new
lines = parser.parse("this,that,these,those")
puts lines.values.inspect #-&gt; [["this", "that", "these", "those"]]</code></pre>
<p>I think it was much simpler for me to write this parsing as a grammar instead of trying to combine regular expressions with Ruby code. The grammar above handles multiple lines and quote-wrapped values, and escaped quotes.</p>
<p>It was actually fun to write as well, and I&#8217;m still learning a lot. Notice that my <code>lines</code> node and my <code>valueline</code> node both approach a similar problem (a list of 0 or more items) differently. For the lines the grammar grabs one line followed by 0 or more separators followed by lines. For the valueline I grab 0 ore more values followed by separators and terminate on the last value. Is one approach better than the other? Are they both junk? I can&#8217;t wait to figure that out.</p>
<p>My poor parser is left in the dust by both Ruby&#8217;s <a href="http://www.ruby-doc.org/stdlib/libdoc/csv/rdoc/index.html">stdlib csv library</a>, and the <a href="http://fastercsv.rubyforge.org/">fastercsv gem</a>. I ran these tests under the 1.8.5 version of Ruby. The <a href="http://www.missiondata.com/blog/wp-content/uploads/2008/02/kentuckycsv.gz">dataset I used</a> is 44k in total and has 961 records.</p>
<pre>
                       user     system      total        real
stdlib_csv:        0.210000   0.000000   0.210000 (  0.217275)
faster_csv:        0.040000   0.000000   0.040000 (  0.060788)
treetop_grammar:   2.910000   0.010000   2.920000 (  3.126020)
</pre>
<p>I don&#8217;t know what sort of speed I should reasonably expect, actually. I&#8217;d hoped that my compiler would be competitive with the standard library&#8217;s csv parsing. It&#8217;s possible that my grammar&#8217;s definition could be innefficient. If anyone has any ideas let me know. </p>
<p>After playing around with Treetop I&#8217;ll definitely tinker some more. There are many other features I haven&#8217;t explored yet, like extending a base grammar to create a new grammar. PEGs have implementations in other languages so this isn&#8217;t a Ruby-only facility, either. </p>
<p>On a side note, I used stdlib&#8217;s benchmark to generate the numbers above. Pretty swank stuff.</p>
<pre><code>require 'rubygems'
require 'treetop'
require 'commaseparatedfile'
require 'fastercsv'
require 'csv'
require 'benchmark'

def with_stdlib_csv(csv)
  parsed = CSV.parse(csv)
  parsed.size
end

def with_fastercsv(csv)
  rows = FasterCSV.parse(csv)
  rows.size
end

def with_treetop_parser(csv)
  parser = CommaSeparatedFileParser.new
  parsed = parser.parse(csv)
  parsed.values.size
end

csv = File.read('../kentucky.csv')

Benchmark.bmbm("treetop_parser:".length) do |x|
  x.report("stdlib_csv:") { with_stdlib_csv(csv) }
  x.report("faster_csv:") { with_fastercsv(csv) }
  x.report("treetop_grammar:") { with_treetop_parser(csv) }
end</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.missiondata.com/blog/web-development/85/treetop-grammars-cool/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Deploying a Subversion branch with Capistrano</title>
		<link>http://www.missiondata.com/blog/system-administration/84/deploying-an-svn-branch-with-capistrano/</link>
		<comments>http://www.missiondata.com/blog/system-administration/84/deploying-an-svn-branch-with-capistrano/#comments</comments>
		<pubDate>Wed, 30 Jan 2008 15:39:34 +0000</pubDate>
		<dc:creator>steveny</dc:creator>
				<category><![CDATA[System Administration]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.missiondata.com/blog/ruby/84/deploying-an-svn-branch-with-capistrano/</guid>
		<description><![CDATA[Capistrano is a tool for automating tasks via SSH on remote servers.  It has many uses, I (and many others) use it to deploy their (rails) applications.  The best I can tell there is no built in way to deploy a branch from your source code control system.  There are a couple [...]]]></description>
			<content:encoded><![CDATA[<p><a href='http://www.capify.org/'>Capistrano</a> is a tool for automating tasks via SSH on remote servers.  It has many uses, I (and many others) use it to deploy their (rails) applications.  The best I can tell there is no built in way to deploy a branch from your source code control system.  There are a couple <a href='http://blog.aisleten.com/2007/09/04/deploying-svn-tags-using-capistrano/'>ways of accomplishing</a> this.  I chose passing in the branch as a parameter to the Capistrano command:</p>
<pre>
<code>cap --set-before branch=testbranch  deploy</code>
</pre>
<p><span id="more-84"></span><br />
&#8230;where &#8216;testbranch&#8217; is the name of my subversion branch, and &#8216;deploy&#8217; is the action to take.  The &#8216;&#8211;set-before option&#8217; sets a variable before the recipes are loaded (<a href='http://osdir.com/ml/lang.ruby.capistrano.general/2006-11/msg00012.html'>sort of)</a>.  All you need to do to make this work you just need to set the repository URL correctly based on if the branch variable exists or not.  In my case, that is editing the top of deploy.rb in the config section of my rails app:</p>
<pre>
<code>if variables.include?(:branch)
  set :repository,  "http://svn.example.com/project/branches/#{branch}"
else
  set :repository,  "http://svn.example.com/project/trunk"
end</code>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.missiondata.com/blog/system-administration/84/deploying-an-svn-branch-with-capistrano/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Handling Session Timeouts (and other errors) using Ajax</title>
		<link>http://www.missiondata.com/blog/web-development/83/handling-session-timeouts-and-other-errors-using-ajax/</link>
		<comments>http://www.missiondata.com/blog/web-development/83/handling-session-timeouts-and-other-errors-using-ajax/#comments</comments>
		<pubDate>Fri, 11 Jan 2008 20:18:11 +0000</pubDate>
		<dc:creator>steveny</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://www.missiondata.com/blog/uncategorized/83/handling-session-timeouts-and-other-errors-using-ajax/</guid>
		<description><![CDATA[Ajax can bring a much more responsive and intuitive feel to web applications.  However, many times developers overlook error cases when using Ajax.  What if the request fails?  In one particular case a user&#8217;s session may have timed out before they made an Ajax call.  This post describes one such way [...]]]></description>
			<content:encoded><![CDATA[<p><a href='http://en.wikipedia.org/wiki/Ajax_(programming)'>Ajax</a> can bring a much more responsive and intuitive feel to web applications.  However, many times developers overlook error cases when using Ajax.  What if the request fails?  In one particular case a user&#8217;s session may have timed out before they made an Ajax call.  This post describes one such way of handling this in a somewhat friendly way.<br />
<span id="more-83"></span></p>
<h3>Handling session timeouts on non-Ajax requests </h3>
<p>The first step to handing session timeouts with AJAX is to handle them for non-Ajax requests first.  One way of doing this is trapping the URL the user is attempting to access  (but not authenticated to), redirecting them to a login page, and upon success, redirecting them back to their original request.</p>
<p>If they aren&#8217;t authenticated, send them to the login page:</p>
<pre>
<code>if(!loggedIn())
{
  response.sendRedirect("/login.jsp?uri=" + URLEncoder.encode(fullURI, "UTF8"));
}</code>
</pre>
<p>Hide the original request in the page:</p>
<pre>
<code>&lt;form action="/account/login" method='POST'&gt;
  &lt;input type="hidden" name="uri" value="&lt;%=request.getParameter("uri")%&gt;"&gt;
  &lt;label for="user_login"&gt;ID:&lt;/label&gt;
  &lt;input type="text" id="user_login" name="user_login" value=""/&gt;
  &lt;label for="user_password"&gt;Password:&lt;/label&gt;
  &lt;input type="password" id="user_password" name="user_password"/&gt;
  &lt;input type="submit" name="login" value=""/&gt;
&lt;/form&gt;</code>
</pre>
<p>&#8230;and after a successful signup, send them back to where they wanted to go:</p>
<pre>
<code>if(authenticated())
{
  response.sendRedirect(request.getParameter("uri"));
}</code>
</pre>
<h3>Handling Session Timeouts for Ajax Requests </h3>
<p>The first thing we need to know is if it is an ajax request or not.  Since I am going to use <a href='http://www.prototypejs.org/'>prototype</a> for all my ajax calls it is as straight forward as looking for the special header prototype sends on each request:</p>
<pre>
<code>private boolean isXMLHttpRequest(HttpServletRequest request)
{
  return request.getHeader("x-requested-with") != null &amp;&amp; request.getHeader("x-requested-with").equals("XMLHttpRequest");
}</code>
</pre>
<p>Once we know the request type, we will send a non-200 <a href='http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html'>HTTP status code</a> if their is an authentication error.  From the standards, the most appropriate status code is a 401 (Unauthorized).  This code, however, comes with some baggage.  On a non-ajax HTTP request all browsers will respond by displaying an authentication dialog.  Most browsers don&#8217;t do this on ajax calls.  Most.  Safari decided that it should pop up the authentication dialog on ajax requests.  Without going too deeply into how this is probably correct and we should be using HTTP to its full advantage and using HTTP authentication instead of a custom authentication scheme, I don&#8217;t want this behavior.  I landed on using the much less appropriate 403 (Forbidden).</p>
<p>So, if the user isn&#8217;t authenticated  (such as with an expired session), send the 403 response back to the browser:</p>
<pre>
<code>if(isXMLHttpRequest(request))
{
  response.sendError(403);
}</code>
</pre>
<p>Now we handle the 403 on the browser side of things:</p>
<pre>
<code>new Ajax.Request('/search',
     {asynchronous:true,
       evalScripts:true,
       onException: function(req,exception) {
         alert('An exception "' + exception + '" was thrown accessing "' + request.url + '"' )
         return true
       },
       on403: function(t) {
         alert('Your session appears to have expired.  You will asked to log in again and returned here.')
         window.location.reload()
         return true
       },
       onFailure: function(request) {
         alert('An unhandled error occured ' + t.status + ': ' + t.statusText);
         return true
       },
       onLoading:function(request){Element.show('loading')},
       onComplete:function(request){Element.hide('loading')},
       onSuccess: function(t) {
         //do something with the results
       },
       parameters:Form.serialize(this)
     })</code>
</pre>
<p>The interesting bit of this call is the on403 method.  Prototype will call onXXX() where XXX is a non-200 HTTP response code.  When a 403 is returned, I simply reload the current page.  Since we handled the scenario of authenticating and returning to the requested page for the non-Ajax call, this &#8216;just works&#8217;.  You may wish to do something else here, including some nifty ajax widget that authenticates in-line and makes the call again.</p>
<p>Now that we have an Ajax request that suits our needs, we will want to use it throughout our project.  Instead of repeating the same code over and over again, let&#8217;s <a href='http://c2.com/cgi/wiki?DontRepeatYourself'>DRY</a> it up.</p>
<h3>Creating a Wrapper Class</h3>
<p>Since I am going to use this scheme for <a href='http://www.prototypejs.org/api/ajax/request'>Ajax.Request</a> and <a href='http://www.prototypejs.org/api/ajax/updater'>Ajax.Updater</a> I created two wrapper classes that use a common function for setting the options.  This scheme allows you to override any of the default options I use in the wrapper:</p>
<pre>
<code>Ajax.MyRequest = Class.create(Ajax.Request, {
  initialize: function($super, url, options) {
    $super(url,_options(options));
  }
})

Ajax.MyUpdater = Class.create(Ajax.Updater, {
  initialize: function($super, container, url, options) {
    $super({success:container},url,_options(options));
  }
})

function _options(options) {
  return Object.extend({
     asynchronous:true,
     evalScripts:true,
     onException: function(request,exception) {
       Element.hide('loading')
       alert('An exception "' + exception + '" was thrown accessing "' + request.url + '"' )
       return true
     },
     on403: function(t) {
       Element.hide('loading')
       alert('Your session appears to have expired.  You will asked to log in again and returned here.')
       window.location.reload()
       return true
     },
     onFailure: function(t) {
       Element.hide('loading')
       alert('An unhandled error occured ' + t.status + ': ' + t.statusText);
     },
     onLoading:function(request){Element.show('loading')},
     onComplete:function(request){window.setTimeout('Element.hide("loading");', 100);}
  }, options || {});
}</code>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.missiondata.com/blog/web-development/83/handling-session-timeouts-and-other-errors-using-ajax/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
