<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-9134564227051500602</id><updated>2012-02-16T08:37:44.227-05:00</updated><category term='ruby'/><category term='watir'/><category term='code'/><category term='testing'/><category term='automation'/><category term='blog'/><category term='bug'/><category term='rails'/><category term='homeschool'/><category term='db'/><title type='text'>ZBar Zone</title><subtitle type='html'>Where you are is where you are at...</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://zbarzone.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9134564227051500602/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://zbarzone.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Andy Sipe</name><uri>http://www.blogger.com/profile/09692499798860981557</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>12</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-9134564227051500602.post-1223811369033855650</id><published>2009-01-22T13:22:00.008-05:00</published><updated>2009-01-25T13:27:04.632-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='automation'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><category scheme='http://www.blogger.com/atom/ns#' term='watir'/><title type='text'>Watir Sortable Tip</title><content type='html'>Haven't posted much recently, maybe that will change.  Maybe not...&lt;br /&gt;&lt;br /&gt;I recently needed to do some Watir testing against a UI that made use of the &lt;a href="http://wiki.github.com/madrobby/scriptaculous/sortable"&gt;Sortable&lt;/a&gt; features of &lt;a href="http://script.aculo.us/"&gt;script.aculo.us&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I wasn't really interested in writing all the code to simulate drag and drop I just wanted to change the order and verify some behavior that made use of the order.   I dug around in the script.aculo.us docs and found this:  Sortable.setSequence(element, new_sequence).&lt;br /&gt;&lt;br /&gt;Using this I can inject a bit of javascript into the page I'm testing that will force the sort order to a particular order.  For example, if I have a basic Sortable on the page, I can force the order to be whatever I need by doing the following from my Watir script:&lt;br /&gt;&lt;br /&gt;&lt;pre style='color:#000020;background:#f6f8ff;'&gt;@ie&lt;span style='color:#308080; '&gt;.&lt;/span&gt;Document&lt;span style='color:#308080; '&gt;.&lt;/span&gt;parentWindow&lt;span style='color:#308080; '&gt;.&lt;/span&gt;execScript&lt;span style='color:#308080; '&gt;(&lt;/span&gt;&lt;span style='color:#1060b6; '&gt;"Sortable.setSequence('sortorder', [5,1,3,2,4]);"&lt;/span&gt;&lt;span style='color:#308080; '&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In this case the Sortable is using _X as the sort ID, but any values will work as long as they match the pattern used in the web page.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9134564227051500602-1223811369033855650?l=zbarzone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zbarzone.blogspot.com/feeds/1223811369033855650/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9134564227051500602&amp;postID=1223811369033855650' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9134564227051500602/posts/default/1223811369033855650'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9134564227051500602/posts/default/1223811369033855650'/><link rel='alternate' type='text/html' href='http://zbarzone.blogspot.com/2009/01/watir-sortable-tip.html' title='Watir Sortable Tip'/><author><name>Andy Sipe</name><uri>http://www.blogger.com/profile/09692499798860981557</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9134564227051500602.post-6189762099743917540</id><published>2008-08-29T09:15:00.001-04:00</published><updated>2008-08-29T10:05:20.288-04:00</updated><title type='text'>Abstract vs Concrete Parameters (Beck)</title><content type='html'>&lt;blockquote&gt;Now I can state the general rule: to make software controllable, pass concrete parameters when tests don't need much flexibility and pass abstract parameters when they need more flexibility. &lt;/blockquote&gt; - Kent Beck&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.threeriversinstitute.org/AbstractVsConcreteParameters.html"&gt;A great read&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9134564227051500602-6189762099743917540?l=zbarzone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zbarzone.blogspot.com/feeds/6189762099743917540/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9134564227051500602&amp;postID=6189762099743917540' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9134564227051500602/posts/default/6189762099743917540'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9134564227051500602/posts/default/6189762099743917540'/><link rel='alternate' type='text/html' href='http://zbarzone.blogspot.com/2008/08/abstract-vs-concrete-parameters-beck.html' title='Abstract vs Concrete Parameters (Beck)'/><author><name>Andy Sipe</name><uri>http://www.blogger.com/profile/09692499798860981557</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9134564227051500602.post-8771664473942070953</id><published>2008-08-29T07:26:00.010-04:00</published><updated>2009-01-25T13:17:56.915-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='automation'/><title type='text'>Watir, send_keys and Javascript</title><content type='html'>I was recently trying to write some tests for some Javascript code that looked something like this (using &lt;a href="http://www.prototypejs.org/"&gt;prototype&lt;/a&gt;):&lt;br /&gt;&lt;br /&gt;&lt;pre style='color:#000020;background:#f6f8ff;'&gt;&lt;span style='color:#200080; font-weight:bold; '&gt;function&lt;/span&gt; watch_keys&lt;span style='color:#308080; '&gt;(&lt;/span&gt;evt&lt;span style='color:#308080; '&gt;)&lt;/span&gt; &lt;span style='color:#406080; '&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span style='color:#200080; font-weight:bold; '&gt;if&lt;/span&gt; &lt;span style='color:#308080; '&gt;(&lt;/span&gt;&lt;span style='color:#308080; '&gt;(&lt;/span&gt;evt&lt;span style='color:#308080; '&gt;.&lt;/span&gt;keyCode &lt;span style='color:#308080; '&gt;&gt;=&lt;/span&gt; &lt;span style='color:#008c00; '&gt;32&lt;/span&gt;&lt;span style='color:#308080; '&gt;)&lt;/span&gt; &lt;span style='color:#308080; '&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style='color:#308080; '&gt;(&lt;/span&gt;evt&lt;span style='color:#308080; '&gt;.&lt;/span&gt;keyCode &lt;span style='color:#308080; '&gt;&amp;lt;&lt;/span&gt; &lt;span style='color:#008c00; '&gt;127&lt;/span&gt;&lt;span style='color:#308080; '&gt;)&lt;/span&gt;&lt;span style='color:#308080; '&gt;)&lt;/span&gt; &lt;span style='color:#406080; '&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#595979; '&gt;//other work...&lt;/span&gt;&lt;br /&gt;    Event&lt;span style='color:#308080; '&gt;.&lt;/span&gt;stop&lt;span style='color:#308080; '&gt;(&lt;/span&gt;evt&lt;span style='color:#308080; '&gt;)&lt;/span&gt;&lt;span style='color:#406080; '&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style='color:#406080; '&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#406080; '&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Event&lt;span style='color:#308080; '&gt;.&lt;/span&gt;observe&lt;span style='color:#308080; '&gt;(&lt;/span&gt;window&lt;span style='color:#308080; '&gt;,&lt;/span&gt; &lt;span style='color:#1060b6; '&gt;'load'&lt;/span&gt;&lt;span style='color:#308080; '&gt;,&lt;/span&gt; &lt;span style='color:#200080; font-weight:bold; '&gt;function&lt;/span&gt;&lt;span style='color:#308080; '&gt;(&lt;/span&gt;&lt;span style='color:#308080; '&gt;)&lt;/span&gt; &lt;span style='color:#406080; '&gt;{&lt;/span&gt;&lt;br /&gt;  Event&lt;span style='color:#308080; '&gt;.&lt;/span&gt;observe&lt;span style='color:#308080; '&gt;(&lt;/span&gt;$&lt;span style='color:#308080; '&gt;(&lt;/span&gt;&lt;span style='color:#1060b6; '&gt;'some_input_id'&lt;/span&gt;&lt;span style='color:#308080; '&gt;)&lt;/span&gt;&lt;span style='color:#308080; '&gt;,&lt;/span&gt; &lt;span style='color:#1060b6; '&gt;'keypress'&lt;/span&gt;&lt;span style='color:#308080; '&gt;,&lt;/span&gt; watch_keys&lt;span style='color:#308080; '&gt;)&lt;/span&gt;&lt;span style='color:#406080; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#406080; '&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I simplified it down to just the basics.   This code is attaching a key press handler to an input field.  If the key being pressed is a printable character then the handler will do some work on it and then stop its propagation.  The work being done isn't to important.   &lt;br /&gt;&lt;br /&gt;My initial attempts at testing this using &lt;a href="http://wtr.rubyforge.org/"&gt;Watir&lt;/a&gt; (version 1.5.3) used the set method didn't work.  The key press event was fired but it never activated the code because regardless of what character was sent the key code was always 0. &lt;br /&gt;&lt;br /&gt;No big deal, I decided to use the send_keys method of Watir::IE.  Using this method I was able to craft some code that worked some of the time.   It turned out that it never worked on our CI system and it was very sensitive to any screen/mouse movement that occurred on the PC that was running the tests.   I've experienced the same problems using send_keys in the past and this wasn't going to work for the long term.&lt;br /&gt;&lt;br /&gt;Digging into the Watir source and why the set method didn't work revealed this code at the heart of the set method (input_elements.rb):&lt;br /&gt;&lt;br /&gt;&lt;pre style='color:#000020;background:#f6f8ff;'&gt;def doKeyPress&lt;span style='color:#308080; '&gt;(&lt;/span&gt;value&lt;span style='color:#308080; '&gt;)&lt;/span&gt;&lt;br /&gt;  value &lt;span style='color:#308080; '&gt;=&lt;/span&gt; limit_to_maxlength&lt;span style='color:#308080; '&gt;(&lt;/span&gt;value&lt;span style='color:#308080; '&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style='color:#200080; font-weight:bold; '&gt;for&lt;/span&gt; i &lt;span style='color:#200080; font-weight:bold; '&gt;in&lt;/span&gt; &lt;span style='color:#008c00; '&gt;0&lt;/span&gt; &lt;span style='color:#308080; '&gt;.&lt;/span&gt;&lt;span style='color:#308080; '&gt;.&lt;/span&gt; value&lt;span style='color:#308080; '&gt;.&lt;/span&gt;length &lt;span style='color:#308080; '&gt;-&lt;/span&gt; &lt;span style='color:#008c00; '&gt;1&lt;/span&gt;&lt;br /&gt;    sleep @container&lt;span style='color:#308080; '&gt;.&lt;/span&gt;typingspeed&lt;br /&gt;    c &lt;span style='color:#308080; '&gt;=&lt;/span&gt; value&lt;span style='color:#308080; '&gt;[&lt;/span&gt;i&lt;span style='color:#308080; '&gt;,&lt;/span&gt;&lt;span style='color:#008c00; '&gt;1&lt;/span&gt;&lt;span style='color:#308080; '&gt;]&lt;/span&gt;&lt;br /&gt;    @o&lt;span style='color:#308080; '&gt;.&lt;/span&gt;value &lt;span style='color:#308080; '&gt;=&lt;/span&gt; @o&lt;span style='color:#308080; '&gt;.&lt;/span&gt;value&lt;span style='color:#308080; '&gt;.&lt;/span&gt;to_s &lt;span style='color:#308080; '&gt;+&lt;/span&gt; c&lt;br /&gt;    @o&lt;span style='color:#308080; '&gt;.&lt;/span&gt;fireEvent&lt;span style='color:#308080; '&gt;(&lt;/span&gt;&lt;span style='color:#1060b6; '&gt;"onKeyDown"&lt;/span&gt;&lt;span style='color:#308080; '&gt;)&lt;/span&gt;&lt;br /&gt;    @o&lt;span style='color:#308080; '&gt;.&lt;/span&gt;fireEvent&lt;span style='color:#308080; '&gt;(&lt;/span&gt;&lt;span style='color:#1060b6; '&gt;"onKeyPress"&lt;/span&gt;&lt;span style='color:#308080; '&gt;)&lt;/span&gt;&lt;br /&gt;    @o&lt;span style='color:#308080; '&gt;.&lt;/span&gt;fireEvent&lt;span style='color:#308080; '&gt;(&lt;/span&gt;&lt;span style='color:#1060b6; '&gt;"onKeyUp"&lt;/span&gt;&lt;span style='color:#308080; '&gt;)&lt;/span&gt;&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Not very hard to see why this doesn't work with any event handlers that are actually checking key codes....   Though the key press event is fired it doesn't have any event information in it.  I'm guessing that by default IE will generate an event with a 0 key code if nothing was provided.   &lt;br /&gt;&lt;br /&gt;I ended up monkey patching IE with a custom implementation of send keys that seems to work for my purposes.&lt;br /&gt;&lt;br /&gt;&lt;pre style='color:#000020;background:#f6f8ff;'&gt;module Watir&lt;br /&gt;  class IE&lt;br /&gt;    def run_script&lt;span style='color:#308080; '&gt;(&lt;/span&gt;js&lt;span style='color:#308080; '&gt;)&lt;/span&gt;&lt;br /&gt;      ie&lt;span style='color:#308080; '&gt;.&lt;/span&gt;Document&lt;span style='color:#308080; '&gt;.&lt;/span&gt;parentWindow&lt;span style='color:#308080; '&gt;.&lt;/span&gt;execScript&lt;span style='color:#308080; '&gt;(&lt;/span&gt;js&lt;span style='color:#308080; '&gt;)&lt;/span&gt;&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    def send_some_keys&lt;span style='color:#308080; '&gt;(&lt;/span&gt;ele&lt;span style='color:#308080; '&gt;,&lt;/span&gt; text&lt;span style='color:#308080; '&gt;)&lt;/span&gt;&lt;br /&gt;     ele&lt;span style='color:#308080; '&gt;.&lt;/span&gt;focus&lt;br /&gt;     run_script&lt;span style='color:#308080; '&gt;(&lt;/span&gt;&lt;span style='color:#1060b6; '&gt;"var wtr_evt=document.createEventObject();"&lt;/span&gt;&lt;span style='color:#308080; '&gt;+&lt;/span&gt; &lt;br /&gt;                &lt;span style='color:#1060b6; '&gt;"var wtr_ele=$('#ele.id}');"&lt;/span&gt;&lt;span style='color:#308080; '&gt;)&lt;/span&gt;&lt;span style='color:#406080; '&gt;;&lt;/span&gt;&lt;br /&gt;     text&lt;span style='color:#308080; '&gt;.&lt;/span&gt;scan&lt;span style='color:#308080; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; '&gt;/&lt;/span&gt;&lt;span style='color:#308080; '&gt;.&lt;/span&gt;&lt;span style='color:#800000; '&gt;/&lt;/span&gt;&lt;span style='color:#308080; '&gt;)&lt;/span&gt; &lt;span style='color:#200080; font-weight:bold; '&gt;do&lt;/span&gt; &lt;span style='color:#308080; '&gt;|&lt;/span&gt;char&lt;span style='color:#308080; '&gt;|&lt;/span&gt;&lt;br /&gt;     run_script&lt;span style='color:#308080; '&gt;(&lt;/span&gt;&lt;span style='color:#1060b6; '&gt;"wtr_evt.keyCode='#{char}'.charCodeAt(0);"&lt;/span&gt;&lt;span style='color:#308080; '&gt;+&lt;/span&gt; &lt;br /&gt;                &lt;span style='color:#1060b6; '&gt;"wtr_ele.fireEvent('onkeypress', wtr_evt);"&lt;/span&gt;&lt;span style='color:#308080; '&gt;)&lt;/span&gt;&lt;span style='color:#406080; '&gt;;&lt;/span&gt;&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This code injects several pieces of JavaScript into the DOM. It creates new event object which represents the key stroke that is incoming.  It then manually fires the event on the element in question.   &lt;br /&gt;&lt;br /&gt;Note that the element must have a valid ID to work and that the injected JavaScript uses the a Prototype method to locate the element.   It shouldn't be hard to customize the code to work with pure JavaScript methods or a different event type.&lt;br /&gt;&lt;br /&gt;So far it is working well in development and CI environments.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9134564227051500602-8771664473942070953?l=zbarzone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zbarzone.blogspot.com/feeds/8771664473942070953/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9134564227051500602&amp;postID=8771664473942070953' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9134564227051500602/posts/default/8771664473942070953'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9134564227051500602/posts/default/8771664473942070953'/><link rel='alternate' type='text/html' href='http://zbarzone.blogspot.com/2008/08/watir-sendkeys-and-javascript.html' title='Watir, send_keys and Javascript'/><author><name>Andy Sipe</name><uri>http://www.blogger.com/profile/09692499798860981557</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9134564227051500602.post-1989248991278845406</id><published>2008-04-09T06:55:00.023-04:00</published><updated>2008-04-09T14:22:28.714-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='bug'/><category scheme='http://www.blogger.com/atom/ns#' term='db'/><title type='text'>Data Concurrency With a Version Lock</title><content type='html'>I ran into an interesting bug with using a version lock to control changes against a record in a database.&lt;br /&gt;&lt;br /&gt;The system in question uses &lt;a href="http://en.wikipedia.org/wiki/Optimistic_concurrency_control"&gt;optimistic concurrency control&lt;/a&gt; to ensure that users do not overwrite each others changes.   This is implemented as a version column in the database which is an integer column that gets incremented with each update of the  row.     When a record is updated, the version number of the current (in memory) record is compared against the record in the database if they are not the same then an exception is raised and the update is aborted.  All pretty standard stuff.&lt;br /&gt;&lt;br /&gt;This all worked well except for one problem.  The typical usage pattern looked like this:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;User views object with version X - the object is loaded from the DAL and given to the view, the view displays the relevant data from the object and stores the object ID in a hidden form variable.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;User updates object by posting the view - the object is loaded from the DAL, updated and saved back to the database via the DAL.   During this save, the version numbers are compared to be sure they are the same.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;There were test cases that validated this behavior and it seems correct but it isn't.   The implementation is only partially correct.   The problem is in the second load of the object.    Consider this sequence:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;User A views obj with ver 1 at 10:00 AM&lt;/li&gt;&lt;li&gt;User B views obj with ver 1 at 10:05 AM&lt;/li&gt;&lt;li&gt;User B saves obj with ver 1 at 10:06 AM&lt;/li&gt;&lt;li&gt;User A saves obj with ver 1 at 10:10 AM  -- &lt;span style="font-weight: bold;"&gt;this should fail&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;Step 4 should fail and it doesn't.  It doesn't fail because the controller simply reloads the object (based on ID) and gets version 2, updates it and saves it.   The DAL doesn't see any problem because the version numbers of the object being updated and the record stored in the database match. &lt;br /&gt;&lt;br /&gt;What this implementation really checks for is the case where two users update the same record simultaneously between the second read/update cycle.   While this can happen, it really isn't the common case and the time span here is likely milliseconds.  In other words, the chances of this actually catching a concurrency violation are pretty small.&lt;br /&gt;&lt;br /&gt;Fixing the problem is fairly simple, it requires the view also store the current version number along with the ID.  Then the controller can request that the DAL load an object with the provided ID &lt;span style="font-weight: bold;"&gt;and&lt;/span&gt; version number.   If that object no longer exists, then a concurrency violation has occurred and the user should be notified to resolve the issue.  If the object was loaded, then the object can be updated and then saved via the DAL using the same check described above.   Having both checks in place should do the trick.&lt;br /&gt;&lt;br /&gt;This particular application is a C#/ASP.net application.  It occurred to me that the &lt;a href="http://www.rubyonrails.org/"&gt;ruby on rails&lt;/a&gt; framework has a feature which provides the same kind of concurrency check (lock_version) and I wondered how active record implemented the check.   &lt;br /&gt;&lt;br /&gt;I fired up a new rails application and generated a simple scaffold.   It appears to me that rails is doing exactly the same thing and unless you include the version_lock in your views (or session I guess) it doesn't work. This is a bit confusing because most references to version_lock seem to suggest that just having the column defined in your schema is enough to get the concurrency check and don't really mention the fact that the 'working' version_lock must be available during the update.  In fact, the lock_version example given in &lt;a href="http://www.pragprog.com/titles/rails2"&gt;Agile Web Development with Rails&lt;/a&gt; is a good example of the problem I describe at the beginning of the post and only covers the smallest case.&lt;br /&gt;&lt;br /&gt;Note, I'm not picking on rails, it just happened to be the first place I looked for an example :)&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9134564227051500602-1989248991278845406?l=zbarzone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zbarzone.blogspot.com/feeds/1989248991278845406/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9134564227051500602&amp;postID=1989248991278845406' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9134564227051500602/posts/default/1989248991278845406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9134564227051500602/posts/default/1989248991278845406'/><link rel='alternate' type='text/html' href='http://zbarzone.blogspot.com/2008/04/data-concurrency-with-version-lock.html' title='Data Concurrency With a Version Lock'/><author><name>Andy Sipe</name><uri>http://www.blogger.com/profile/09692499798860981557</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9134564227051500602.post-4534565754441168107</id><published>2008-04-07T16:19:00.000-04:00</published><updated>2008-04-07T16:20:46.569-04:00</updated><title type='text'>Cool Visualization</title><content type='html'>Digg &lt;a href="http://labs.digg.com/stack/"&gt;Visualization&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Check out the other styles at that same link - fun stuff!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9134564227051500602-4534565754441168107?l=zbarzone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zbarzone.blogspot.com/feeds/4534565754441168107/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9134564227051500602&amp;postID=4534565754441168107' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9134564227051500602/posts/default/4534565754441168107'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9134564227051500602/posts/default/4534565754441168107'/><link rel='alternate' type='text/html' href='http://zbarzone.blogspot.com/2008/04/cool-visualization.html' title='Cool Visualization'/><author><name>Andy Sipe</name><uri>http://www.blogger.com/profile/09692499798860981557</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9134564227051500602.post-786618991059135377</id><published>2008-04-03T18:23:00.001-04:00</published><updated>2008-04-03T18:33:27.064-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='automation'/><title type='text'>Automation and the Console</title><content type='html'>When I'm writing software, I prefer to work with an editor and a set of consoles.  Editor for code and consoles for building/testing.   Works great in almost any language.   Who needs those stinkin IDEs :)&lt;br /&gt;&lt;br /&gt;One of the downsides to this is that the test/code cycle can get broken up by continually having to switch windows.   With a full blown IDE you just hit some magic key and it all happens.   What I wanted was this magic to happen but still keep the flexibility of having the 2 different tools. &lt;br /&gt;&lt;br /&gt;Enter &lt;a href="http://www.autohotkey.com/"&gt;AutoHotKey&lt;/a&gt;.  AutoHotKey allows you to script a whole bunch of windows stuff and it also allows you to setup system wide hot keys.   So, I wrote a simple script that looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;^+e::&lt;br /&gt;WinGetActiveTitle, Title&lt;br /&gt;IfWinExist Console&lt;br /&gt;{&lt;br /&gt;  WinActivate&lt;br /&gt;  SendInput {Up}&lt;br /&gt;  SendInput {Enter}&lt;br /&gt;  WinActivate, %Title%&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This script is set to register as the global hot key Control-Shift e.   What is does it get/store the current window title, activate the console window, press the up key (to activate the last command), press enter and then reactivate the previous window.    Works like a charm.  Since I got it working I'm unsure how I lived without it.&lt;br /&gt;&lt;br /&gt;Now that I know how to do it, I'm thinking of all kinds of global hot keys that I might be able to use.&lt;br /&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9134564227051500602-786618991059135377?l=zbarzone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zbarzone.blogspot.com/feeds/786618991059135377/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9134564227051500602&amp;postID=786618991059135377' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9134564227051500602/posts/default/786618991059135377'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9134564227051500602/posts/default/786618991059135377'/><link rel='alternate' type='text/html' href='http://zbarzone.blogspot.com/2008/04/automation-and-console.html' title='Automation and the Console'/><author><name>Andy Sipe</name><uri>http://www.blogger.com/profile/09692499798860981557</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9134564227051500602.post-1708875939282421484</id><published>2008-04-03T13:40:00.001-04:00</published><updated>2008-04-03T19:09:39.412-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='watir'/><title type='text'>Watir Bug (kinda sorta)</title><content type='html'>I stumbled upon this a while back and it caused me some grief.  Today I saw some questions on the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;Watir&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;NG&lt;/span&gt; that seem to be about the same problem.&lt;br /&gt;&lt;br /&gt;Consider this &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;irb&lt;/span&gt; session:&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: rgb(85, 85, 85);"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;irb&lt;/span&gt;(main):001:0&amp;gt; &lt;/span&gt;require &lt;span style="color: rgb(0, 0, 255);"&gt;'&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;Watir&lt;/span&gt;'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(136, 136, 136);"&gt;=&amp;gt; true&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(85, 85, 85);"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;irb&lt;/span&gt;(main):002:0&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 128); font-weight: bold;"&gt;include&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;Watir&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(136, 136, 136);"&gt;=&amp;gt; Object&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(85, 85, 85);"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;irb&lt;/span&gt;(main):003:0&amp;gt; &lt;/span&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;ie&lt;/span&gt; = IE::start_process(&lt;span style="color: rgb(0, 0, 255);"&gt;'www.google.com'&lt;/span&gt;)&lt;br /&gt;&lt;span style="color: rgb(136, 136, 136);"&gt;=&amp;gt; #&amp;amp;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;lt&lt;/span&gt;;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;Watir&lt;/span&gt;::IE:0x2c7d86c ....&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(85, 85, 85);"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;irb&lt;/span&gt;(main):006:0&amp;gt; &lt;/span&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;ie&lt;/span&gt;.div(&lt;span style="color: rgb(0, 0, 255);"&gt;:id&lt;/span&gt;, &lt;span style="color: rgb(0, 0, 255);"&gt;'&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;gbar&lt;/span&gt;'&lt;/span&gt;).id&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(136, 136, 136);"&gt;=&amp;gt; "&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;gbar&lt;/span&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(85, 85, 85);"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;irb&lt;/span&gt;(main):007:0&amp;gt; &lt;/span&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;ie&lt;/span&gt;.div(&lt;span style="color: rgb(0, 0, 255);"&gt;:id&lt;/span&gt;=&amp;gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;gbar&lt;/span&gt;'&lt;/span&gt;).id&lt;br /&gt;&lt;span style="color: rgb(136, 136, 136);"&gt;=&amp;gt; "&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;gbar&lt;/span&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(85, 85, 85);"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;irb&lt;/span&gt;(main):008:0&amp;gt; &lt;/span&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;ie&lt;/span&gt;.text_field(&lt;span style="color: rgb(0, 0, 255);"&gt;:name&lt;/span&gt;, &lt;span style="color: rgb(0, 0, 255);"&gt;'q'&lt;/span&gt;).id&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(136, 136, 136);"&gt;=&amp;gt; ""&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(85, 85, 85);"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_21"&gt;irb&lt;/span&gt;(main):009:0&amp;gt; &lt;/span&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_22"&gt;ie&lt;/span&gt;.text_field(&lt;span style="color: rgb(0, 0, 255);"&gt;:name&lt;/span&gt;, &lt;span style="color: rgb(0, 0, 255);"&gt;'q'&lt;/span&gt;).name&lt;br /&gt;&lt;span style="color: rgb(136, 136, 136);"&gt;=&amp;gt; "q"&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(85, 85, 85);"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_23"&gt;irb&lt;/span&gt;(main):010:0&amp;gt; &lt;/span&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_24"&gt;ie&lt;/span&gt;.text_field(&lt;span style="color: rgb(0, 0, 255);"&gt;:name&lt;/span&gt;=&amp;gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'q'&lt;/span&gt;).name&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(136, 136, 136);"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_25"&gt;TypeError&lt;/span&gt;: {:name=&amp;gt;"q"} is not a symbol &lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(136, 136, 136);"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_26"&gt;irb&lt;/span&gt;(main):011:0&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Accessing an input element with a hash fails.   Input elements in &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_27"&gt;Watir&lt;/span&gt; currently only support a single search item and this is the cause of the confusion.&lt;br /&gt;&lt;br /&gt;This patch will solve the problem:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;require &lt;span style="color: rgb(0, 0, 255);"&gt;'&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_28"&gt;watir&lt;/span&gt;'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 128); font-weight: bold;"&gt;module&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_29"&gt;Watir&lt;/span&gt;::Container&lt;br /&gt; &lt;span style="color: rgb(0, 0, 128); font-weight: bold;"&gt;alias&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;:old_locate_input_element&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;:locate_input_element&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; &lt;span style="color: rgb(0, 136, 0); font-style: italic;"&gt;#form elements do not allow the hash syntax for how/what.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; &lt;span style="color: rgb(0, 136, 0); font-style: italic;"&gt;#this change here allows it for single element hashes by &lt;/span&gt;&lt;br /&gt; &lt;span style="color: rgb(0, 136, 0); font-style: italic;"&gt;#just converting the hash into a distinct how and what and then &lt;/span&gt;&lt;br /&gt; &lt;span style="color: rgb(0, 136, 0); font-style: italic;"&gt;#passing it on&lt;/span&gt;&lt;br /&gt; &lt;span style="color: rgb(0, 0, 128); font-weight: bold;"&gt;def&lt;/span&gt; locate_input_element(how, what, types, value=&lt;span style="color: rgb(0, 0, 128); font-weight: bold;"&gt;nil&lt;/span&gt;)&lt;br /&gt;   how, what = *how.to_a[&lt;span style="color: rgb(0, 0, 255);"&gt;0&lt;/span&gt;] &lt;span style="color: rgb(0, 0, 128); font-weight: bold;"&gt;if&lt;/span&gt; (how.kind_of? Hash) &amp;amp;&amp;amp; (how.length == &lt;span style="color: rgb(0, 0, 255);"&gt;1&lt;/span&gt;)&lt;br /&gt;   old_locate_input_element(how, what, types, value)&lt;br /&gt; &lt;span style="color: rgb(0, 0, 128); font-weight: bold;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 128); font-weight: bold;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;All it does is convert a hash into the multiple &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_30"&gt;args&lt;/span&gt; (how and what) that the input element &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_31"&gt;look up&lt;/span&gt; requires.   It doesn't do anything to allow multiple look up values for input elements.&lt;br /&gt;&lt;br /&gt;Update:  Turns out this this is a know &lt;a href="http://jira.openqa.org/browse/WTR-193"&gt;issue&lt;/a&gt;.&lt;br /&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9134564227051500602-1708875939282421484?l=zbarzone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zbarzone.blogspot.com/feeds/1708875939282421484/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9134564227051500602&amp;postID=1708875939282421484' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9134564227051500602/posts/default/1708875939282421484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9134564227051500602/posts/default/1708875939282421484'/><link rel='alternate' type='text/html' href='http://zbarzone.blogspot.com/2008/04/watir-bug-kinda-sorta.html' title='Watir Bug (kinda sorta)'/><author><name>Andy Sipe</name><uri>http://www.blogger.com/profile/09692499798860981557</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9134564227051500602.post-8044539352780649876</id><published>2008-03-29T08:10:00.001-04:00</published><updated>2008-03-31T08:45:20.025-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blog'/><title type='text'>Layout</title><content type='html'>I'm trying to get the code layout to work well in the major browsers.  &lt;br /&gt;&lt;br /&gt;Right now it looks fine in Firefox 2, which is what I mostly use.   In IE 6 all the line breaks are removed, I know why but I'm not sure how to fix it.   I haven't gotten around to testing other browsers so if things look weird, view it in Firefox and hopefully it'll look better :)&lt;br /&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9134564227051500602-8044539352780649876?l=zbarzone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zbarzone.blogspot.com/feeds/8044539352780649876/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9134564227051500602&amp;postID=8044539352780649876' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9134564227051500602/posts/default/8044539352780649876'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9134564227051500602/posts/default/8044539352780649876'/><link rel='alternate' type='text/html' href='http://zbarzone.blogspot.com/2008/03/layout.html' title='Layout'/><author><name>Andy Sipe</name><uri>http://www.blogger.com/profile/09692499798860981557</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9134564227051500602.post-8066270190970907029</id><published>2008-03-27T21:10:00.001-04:00</published><updated>2008-04-03T14:05:05.037-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='watir'/><title type='text'>Dynamic Finders with Watir</title><content type='html'>If you've used rails, then you've probably seen the &lt;a href="http://www.google.com/search?q=dynamic%20finders"&gt;dynamic finders&lt;/a&gt; that active record provides.  I thought it'd be interesting to see if that kind of behavior could be added to &lt;a href="http://wtr.rubyforge.org/"&gt;Watir&lt;/a&gt;.   It turned out to be a nice little exercise. &lt;br /&gt;&lt;br /&gt;I'm not sure how it will play in real test code, but I'm going to try it out over the next couple of days.&lt;br /&gt;&lt;br /&gt;Here is an example of what you can do:&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;require &lt;span style="color: #0000FF"&gt;&amp;#39;watir&amp;#39;&lt;/span&gt;&lt;br /&gt;require &lt;span style="color: #0000FF"&gt;&amp;#39;dynamic_finder.rb&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #000080; font-weight: bold"&gt;include&lt;/span&gt; Watir&lt;br /&gt;&lt;br /&gt;ie = IE::start_process(&lt;span style="color: #0000FF"&gt;&amp;#39;www.google.com&amp;#39;&lt;/span&gt;)&lt;br /&gt;p ie.div_by_id(&lt;span style="color: #0000FF"&gt;/gbar/&lt;/span&gt;).id                    &lt;span style="color: #008800; font-style: italic"&gt;# ie.div(:id =&amp;gt; /gbar/)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;p ie.span_by_class(&lt;span style="color: #0000FF"&gt;/gb1/&lt;/span&gt;).text               &lt;span style="color: #008800; font-style: italic"&gt;# ie.span(:class =&amp;gt; /gb1/)&lt;/span&gt;&lt;br /&gt;p ie.span_by_class_and_index(&lt;span style="color: #0000FF"&gt;/gb1/&lt;/span&gt;, &lt;span style="color: #0000FF"&gt;2&lt;/span&gt;).text  &lt;span style="color: #008800; font-style: italic"&gt;# ie.span(:class =&amp;gt; /gb1/, :index=&amp;gt;2)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;p ie.span_by_index(&lt;span style="color: #0000FF"&gt;2&lt;/span&gt;).text                   &lt;span style="color: #008800; font-style: italic"&gt;# ie.span(:index =&amp;gt; 2)&lt;/span&gt;&lt;br /&gt;p ie.text_field_by_index(&lt;span style="color: #0000FF"&gt;1&lt;/span&gt;).name             &lt;span style="color: #008800; font-style: italic"&gt;# ie.text_field(:index,1)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;ie.text_field_by_name(&lt;span style="color: #0000FF"&gt;&amp;quot;q&amp;quot;&lt;/span&gt;).set(&lt;span style="color: #0000FF"&gt;&amp;#39;watir&amp;#39;&lt;/span&gt;)&lt;br /&gt;ie.button_by_value(&lt;span style="color: #0000FF"&gt;&amp;#39;Google Search&amp;#39;&lt;/span&gt;).click&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000FF"&gt;2&lt;/span&gt;.times &lt;span style="color: #000080; font-weight: bold"&gt;do&lt;/span&gt; &lt;br /&gt;  ie.link_by_text(&lt;span style="color: #0000FF"&gt;/Watir Tutorial/&lt;/span&gt;).click&lt;br /&gt;&lt;span style="color: #000080; font-weight: bold"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;ie.close&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;You can find the source files for the change and the example posted above &lt;a href="http://code.google.com/p/zonecodearchive/source/browse/trunk/ruby/watir/dynamic_finder/?r=3"&gt;here&lt;/a&gt;.   Enjoy!&lt;br /&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9134564227051500602-8066270190970907029?l=zbarzone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zbarzone.blogspot.com/feeds/8066270190970907029/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9134564227051500602&amp;postID=8066270190970907029' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9134564227051500602/posts/default/8066270190970907029'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9134564227051500602/posts/default/8066270190970907029'/><link rel='alternate' type='text/html' href='http://zbarzone.blogspot.com/2008/03/dynamic-finders-with-watir.html' title='Dynamic Finders with Watir'/><author><name>Andy Sipe</name><uri>http://www.blogger.com/profile/09692499798860981557</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9134564227051500602.post-5730610828894227535</id><published>2008-03-27T10:35:00.000-04:00</published><updated>2008-03-27T11:21:38.011-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Trying Python</title><content type='html'>I'm gonna give Python a try!!&lt;br /&gt;&lt;br /&gt;I've been using Ruby as my scripting language of choice for about 3 years now.   It is a great language and I learned a lot using it.     However, there are 2 problems that I have with Ruby.&lt;br /&gt;&lt;br /&gt;First, its Windows support isn't great.   For basic things it works wonders, but when you get beyond that there are a lot of things that Ruby on Windows doesn't do so well.   Some of the more interesting gems do not run well (or at all) on Windows.     Even some of the standard libraries that ship with Ruby don't work on Windows and don't get me started with some of the core library methods that don't work.     It also seems that everything with Ruby runs slower on windows -- very frustrating.&lt;br /&gt;&lt;br /&gt;Second, it seems to me that more and more the Ruby community has an attitude that if you aren't running nix then it doesn't matter.   This is a real shame, Windows is a huge market.  I use Windows for development, most of my clients use Windows so dropping it for a better OS isn't an option.   The community as a whole is struggling with this issue but there doesn't seem to be a good solution right now.   Check out these  (&lt;a href="http://www.rubyinside.com/is-windows-a-first-class-platform-for-ruby-823.html"&gt;here&lt;/a&gt;, &lt;a href="http://blog.mmediasys.com/2008/01/17/ruby-for-windows-part-1/"&gt;here&lt;/a&gt; and &lt;a href="http://blog.mmediasys.com/2008/03/06/is-windows-a-supported-platform-for-ruby-i-guess-not/"&gt;here&lt;/a&gt;)  other blogs for some interesting info (the comments are interesting as well).&lt;a href="http://www.rubyinside.com/is-windows-a-first-class-platform-for-ruby-823.html"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So I'm gonna try some options and see what is what.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9134564227051500602-5730610828894227535?l=zbarzone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zbarzone.blogspot.com/feeds/5730610828894227535/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9134564227051500602&amp;postID=5730610828894227535' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9134564227051500602/posts/default/5730610828894227535'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9134564227051500602/posts/default/5730610828894227535'/><link rel='alternate' type='text/html' href='http://zbarzone.blogspot.com/2008/03/trying-python.html' title='Trying Python'/><author><name>Andy Sipe</name><uri>http://www.blogger.com/profile/09692499798860981557</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9134564227051500602.post-3032833666960690254</id><published>2008-03-26T15:08:00.000-04:00</published><updated>2008-03-26T15:13:11.712-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='homeschool'/><title type='text'>Teaching</title><content type='html'>"&lt;span style="font-weight: bold;"&gt;If you would thoroughly know anything teach it to others&lt;/span&gt;."  -- Tryon Edwards&lt;br /&gt;&lt;br /&gt;If you think you know something, try teaching it.  If you think you really know something, try teaching it to a 7 year old, a 10 year old and a 13 year old in the same day!!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9134564227051500602-3032833666960690254?l=zbarzone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zbarzone.blogspot.com/feeds/3032833666960690254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9134564227051500602&amp;postID=3032833666960690254' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9134564227051500602/posts/default/3032833666960690254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9134564227051500602/posts/default/3032833666960690254'/><link rel='alternate' type='text/html' href='http://zbarzone.blogspot.com/2008/03/teaching.html' title='Teaching'/><author><name>Andy Sipe</name><uri>http://www.blogger.com/profile/09692499798860981557</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9134564227051500602.post-2930949512641611281</id><published>2008-03-26T14:23:00.000-04:00</published><updated>2008-03-31T08:45:35.200-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blog'/><title type='text'>Blogging Again</title><content type='html'>I finally got around to start blogging again.   I've lost all my old posts so I'll be starting from scratch...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9134564227051500602-2930949512641611281?l=zbarzone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zbarzone.blogspot.com/feeds/2930949512641611281/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9134564227051500602&amp;postID=2930949512641611281' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9134564227051500602/posts/default/2930949512641611281'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9134564227051500602/posts/default/2930949512641611281'/><link rel='alternate' type='text/html' href='http://zbarzone.blogspot.com/2008/03/blogging-again.html' title='Blogging Again'/><author><name>Andy Sipe</name><uri>http://www.blogger.com/profile/09692499798860981557</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry></feed>
