<?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>Wed, 10 Mar 2010 21:21:14 +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>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>0</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>
		<item>
		<title>&#8216;cvs update: move away foo.bar; it is in the way&#8217;</title>
		<link>http://www.missiondata.com/blog/system-administration/81/cvs-update-move-away-foobar-it-is-in-the-way/</link>
		<comments>http://www.missiondata.com/blog/system-administration/81/cvs-update-move-away-foobar-it-is-in-the-way/#comments</comments>
		<pubDate>Thu, 26 Apr 2007 21:00:40 +0000</pubDate>
		<dc:creator>darrend</dc:creator>
				<category><![CDATA[System Administration]]></category>
		<category><![CDATA[CVS]]></category>
		<category><![CDATA[Utilities]]></category>

		<guid isPermaLink="false">http://www.missiondata.com/blog/utilities/81/cvs-update-move-away-foobar-it-is-in-the-way/</guid>
		<description><![CDATA[A client site still uses cvs, the ever trusty version control system. After what seemed a run of the mill merge I noticed this:
C lib/jt400_3_3.jar
cvs update: move away lib/jt400_3_3.jar; it is in the way
Very peculiar. That file hadn&#8217;t changed on the branch. I googled around and an explanation started to come together.
First, from the always [...]]]></description>
			<content:encoded><![CDATA[<p>A client site still uses cvs, the ever trusty version control system. After what seemed a run of the mill merge I noticed this:</p>
<pre><code class="console">C lib/jt400_3_3.jar
cvs update: move away lib/jt400_3_3.jar; it is in the way</code></pre>
<p>Very peculiar. That file hadn&#8217;t changed on the branch. I <a href="http://www.google.com/search?q=cvs+update+move+away">googled around</a> and an explanation started to come together.</p>
<p>First, from the always excellent <a href="http://mindprod.com/jgloss/cvs.html">Roedy Green’s Java &#038; Internet Glossary on Mindprod</a>:</p>
<blockquote><p>
CVS is disturbed by the appearance of repository files it did not put there. Your best bet is simply to delete the entire directory containing the offending file by hand, and re checkout or reupdate the directory to build the necessary entries. Then you can add the files safely.
</p></blockquote>
<p>Then, I found this <a href="http://mail.lon-capa.org/pipermail/lon-capa-admin/Week-of-Mon-20030915/000367.html">mailing list post</a>:</p>
<blockquote><p>
This means the file that CVS wants to checkout exists on the local machine but CVS never created the file in the past. This it isn&#8217;t CVS&#8217;s file and it complains rather than blindly overwriting.
</p></blockquote>
<p>The solution everywhere was the same: just blow away the directory and check it out again. Worked for me. Now I need to puzzle out how it happened in the first place&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.missiondata.com/blog/system-administration/81/cvs-update-move-away-foobar-it-is-in-the-way/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>rails fixtures with models using set_table_name</title>
		<link>http://www.missiondata.com/blog/systems-integration/80/rails-fixtures-with-models-using-set_table_name/</link>
		<comments>http://www.missiondata.com/blog/systems-integration/80/rails-fixtures-with-models-using-set_table_name/#comments</comments>
		<pubDate>Mon, 23 Apr 2007 03:13:47 +0000</pubDate>
		<dc:creator>darrend</dc:creator>
				<category><![CDATA[Systems Integration]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.missiondata.com/blog/uncategorized/80/rails-fixtures-with-models-using-set_table_name/</guid>
		<description><![CDATA[If you have a model that uses set_table_name you may hit a snag when trying to use fixtures and unit tests. The solution is twofold: name the fixture file using the legacy table name, and use the set_fixture_class method in your unit test. I coudn&#8217;t find this method mentioned in Agile Web Development with Rails, [...]]]></description>
			<content:encoded><![CDATA[<p>If you have a model that uses <tt>set_table_name</tt> you may hit a snag when trying to use fixtures and unit tests. The solution is twofold: name the fixture file using the legacy table name, and use the <tt>set_fixture_class</tt> method in your unit test. I coudn&#8217;t find this method mentioned in <em>Agile Web Development with Rails</em>, and there&#8217;s only a brief mention on the <a href="http://wiki.rubyonrails.com/rails/pages/HowToUseLegacySchemas">rubyonrails.com site</a>. Still, some web searches turned up the answers.</p>
<p>Here is a simple example:</p>
<p><span id="more-80"></span></p>
<p>We&#8217;ll start with a table named <code>libris_book</code> that contains book entries. The name <em>libris_book</em> won&#8217;t really fly with the Rails pluralized table name approach. It&#8217;s easy, however, to fix that disconnect in the model:</p>
<pre><code>class Book &lt; ActiveRecord::Base
  set_table_name 'libris_book'
end</code></pre>
<p>Let&#8217;s take a look at our data:</p>
<pre><code class="console">~/src/libris$ script/console
Loading development environment.
&gt;&gt; Book.count
=&gt; 1230</code></pre>
<p>Good enough. Now, we&#8217;ll be good little coders and write some unit tests using fixtures. We&#8217;ll create a fixture file and our test class:<br />
<br />
<tt>books.yml</tt></p>
<pre><code>test_book:
  title: Life in Lawrenceburg
  author: Darren Day</code></pre>
<p><tt>book_test.rb</tt></p>
<pre><code>require File.dirname(__FILE__) + '/../test_helper'

class BookTest &lt; Test::Unit::TestCase
  fixtures :books

  def test_fixtures
    assert_equal(2,Book.count)
    test_book = books(:test_book)
  end
end</code></pre>
<p>Looks good, but it won&#8217;t work!</p>
<pre><code class="console">~/src/libris$ rake test
(in /home/darrend/src/libris)
/usr/local/bin/ruby -Ilib:test "/usr/local/lib/ruby/gems/1.8/gems/rake-0.7.2/lib/rake/rake_test_loader.rb" "test/unit/book_test.rb"
Loaded suite /usr/local/lib/ruby/gems/1.8/gems/rake-0.7.2/lib/rake/rake_test_loader
Started
E
Finished in 0.01133 seconds.

  1) Error:
test_fixtures(BookTest):
ActiveRecord::StatementInvalid: Mysql::Error: Table 'libris_test.books' doesn't exist: DELETE FROM books
...</code></pre>
<p>Ugh. That doesn&#8217;t look pretty. After some <a href="http://www.google.com/search?q=set_table_name+fixtures">googling around</a> the following comes together</p>
<ul>
<li>Rename <tt>books.yml</tt> to <tt>libris_book.yml</tt>. The fixture yaml file has to share the same name as the database table name.
<li>Change the <tt>fixtures</tt> declaration to <code>fixtures :libris_book</code>.
<li> Use <tt>set_fixture_class</tt> to connect the fixture to the model class.
</ul>
<p>Here is our new and improved <tt>book_test.rb</tt> file:</p>
<pre><code>require File.dirname(__FILE__) + '/../test_helper'

class BookTest &lt; Test::Unit::TestCase
  set_fixture_class :libris_book =&gt; Book
  fixtures :libris_book

  def test_fixtures
    assert_equal(2,Book.count)
    test_book = libris_book(:test_book)
  end
end</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.missiondata.com/blog/systems-integration/80/rails-fixtures-with-models-using-set_table_name/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
