<?xml version="1.0"?>
<rss version="2.0">

<channel>
	<title>Planet Openbox</title>
	<link>http://planetob.openmonkey.com</link>
	<language>en</language>
	<description>Planet Openbox - http://planetob.openmonkey.com</description>

<item>
	<title>K Mandla: Dumping a screensaver to a text file</title>
	<guid>http://kmandla.wordpress.com/2009/07/03/dumping-a-screensaver-to-a-text-file/</guid>
	<link></link>
	<description>I am only days away from completing a rather large real-life project, and finally getting back some of the free time I have lost over the past few months. July is looking much more promising than June, and I already have a stack of things I need to make notes on, as well as an [...]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=kmandla.wordpress.com&amp;amp;blog=353512&amp;amp;post=2786&amp;amp;subd=kmandla&amp;amp;ref=&amp;amp;feed=1&quot; /&gt;</description>
	<pubDate>Thu, 02 Jul 2009 23:45:11 +0000</pubDate>
</item>
<item>
	<title>Akkana Peck: Disabling mouse/keyboard wakeup</title>
	<guid>http://shallowsky.com/blog/linux/kernel/no-mouse-kbd-wakeup.html</guid>
	<link>http://shallowsky.com/blog/linux/kernel/no-mouse-kbd-wakeup.html</link>
	<description>Suspend (sleep) works very well on the dual-Atom desktop. The only
problem with it is that the mouse or keyboard wake it up. I don't mind
the keyboard, but the mouse is quite sensitive, so a breeze through
the window or a big truck driving by on the street can jiggle the
mouse and wake the machine when I'm away.
&lt;p&gt;
I've been through all the BIOS screens looking for a setting to flip,
but there's nothing there. Some web searching told me that under
Windows, there's a setting you can change that will affect this,
but I couldn't find anything similar for Linux, until finally
drc clued me in to /proc/acpi/wakeup.
&lt;p&gt;
&lt;pre&gt;
cat /proc/acpi/wakeup
&lt;/pre&gt;
will tell you all the events that can cause your machine to wake up
from various sleep states.
&lt;p&gt;
Unfortunately, they're also obscurely coded. Here are mine:
&lt;pre&gt;
Device  S-state   Status   Sysfs node
SLPB      S4    *enabled  
P32       S4     disabled  pci:0000:00:1e.0
UAR1      S4     enabled   pnp:00:0a
PEX0      S4     disabled  pci:0000:00:1c.0
PEX1      S4     disabled  
PEX2      S4     disabled  pci:0000:00:1c.2
PEX3      S4     disabled  pci:0000:00:1c.3
PEX4      S4     disabled  
PEX5      S4     disabled  
UHC1      S3     disabled  pci:0000:00:1d.0
UHC2      S3     disabled  pci:0000:00:1d.1
UHC3      S3     disabled  pci:0000:00:1d.2
UHC4      S3     disabled  pci:0000:00:1d.3
EHCI      S3     disabled  pci:0000:00:1d.7
AC9M      S4     disabled  
AZAL      S4     disabled  pci:0000:00:1b.0
&lt;/pre&gt;
&lt;p&gt;
What do all those symbols mean? I have no clue. Apparently the codes
come from the BIOS's DSDT code, and since it varies from board to
board, nobody has published tables of likely translations.
&lt;p&gt;
The only two wakeups that were enabled for me were SLPB and UAR1.
SLPB apparently stands for SLeeP Button, and Rik suggested UAR
probably stood for Universal Asynchronous Receiver (the more familiar
term UART both receives and Transmits.)
Some of the other devices in the list can possibly be identified by
comparing their pci: codes against &lt;code&gt;lspci&lt;/code&gt;, but not those two.

&lt;p&gt;
Time for some experimentation.
You can toggle any of these by writing to the wakeup device:

&lt;pre&gt;
echo UAR1 &gt;/proc/acpi/wakeup
&lt;/pre&gt;

&lt;p&gt;
It turned out that to disable mouse and keyboard wakeup, I had to
disable both SLPB and UAR1. With both disabled, the machine wakes
up when I press the power button.
(What the SLeeP Button is, if it's not the power button, I don't know.)
&lt;p&gt;
My mouse and keyboard are PS/2. For a USB mouse and keyboard, look
for something like USB0, UHC0, USB1.

&lt;p&gt;
The UAR1 setting is remembered even across boots: there's no need to
do anything to make sure the setting is remembered. But the SLPB
setting resets every time I boot. So I edited /etc/rc.local and
added this line:
&lt;pre&gt;
echo SLPB &gt;/proc/acpi/wakeup
&lt;/pre&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;</description>
	<pubDate>Thu, 02 Jul 2009 16:30:35 +0000</pubDate>
</item>
<item>
	<title>David Barr: We came, we saw, we moved on.</title>
	<guid>http://david.chalkskeletons.com/blog/?p=80</guid>
	<link>http://david.chalkskeletons.com/blog/?p=80</link>
	<description>&lt;p&gt;It is sad to see the &lt;a href=&quot;http://blogs.gnome.org/tthurman/&quot;&gt;demise of Metacity&lt;/a&gt;, but its legacy will not be forgotten. Obviously there is &lt;a href=&quot;http://live.gnome.org/GnomeShell&quot;&gt;Mutter&lt;/a&gt;, and of course &lt;a href=&quot;http://www.compiz.org/&quot;&gt;Compiz&lt;/a&gt;, but i think most modern window managers owe a tip of the hat to Metacity; it brought a love of standards, simplicity and of course integration.&lt;/p&gt;
&lt;p&gt;It was not without the doubters though, and it certainly felt unloved toward the end (despite the ongoing work of Thomas Thurman and whoever wrote the compositor? Ian&amp;#8230;?). The problem with Metacity, for me, was that it was just never that predictable, I&amp;#8217;m not really fussy with focus issues but Metacity still seemed to grate on me, it always &lt;em&gt;felt&lt;/em&gt; very incomplete, it always &lt;em&gt;felt&lt;/em&gt; just not right - probably because people (I blame Ubuntu, but I blame them for everything) jumped on the Compiz bling wagon far too early when what was needed was boring bug fixes to Metacity for a better window manager experience. The problem with Compiz was that it became very apparent that those who shouted loudest were more interested in how their menus exploded rather than how their windows were managed.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;http://blogs.gnome.org/metacity/&quot;&gt;Metacity blog&lt;/a&gt; was always an interesting read as well which I guess will go out the window now, people just aren&amp;#8217;t interested in window managers unless a) they tile (which is foolish) or b) they have stupid effects. I hope Mutter is a solid window manager with tasteful warranted effects that aid usability and maybe even accessibility.  Gnome-shell right now look wholly underwhelming but that might be a good thing?&lt;/p&gt;
&lt;p&gt;Metacity still has the best simple composite manager for my money and I&amp;#8217;d love to see something like it in Openbox ;)&lt;/p&gt;</description>
	<pubDate>Thu, 02 Jul 2009 09:48:31 +0000</pubDate>
</item>
<item>
	<title>Miklos Bacso: Gmail interface changed</title>
	<guid>http://miklos.ca/log/2009/07/gmail-interface-changed.html</guid>
	<link>http://feedproxy.google.com/~r/memento_log/~3/umCt2vTBMFg/gmail-interface-changed.html</link>
	<description>I noticed some &lt;a href=&quot;http://gmailblog.blogspot.com/2009/07/labels-drag-and-drop-hiding-and-more.html&quot;&gt;changes in the Gmail interface&lt;/a&gt; today and I'm not sure what to think of it yet. I used to change my site &lt;i&gt;all&lt;/i&gt; the time; functionality, design... everything. I mean I just changed it recently--albeit a minor CSS change (went from a white background to a black one if you haven't noticed!)--but the functionality has stayed the same. Changes like this new Gmail change makes me realize that when people use a site as often as one might use the Gmail interface, they're used to a certain way of navigating... changing that is not necessarily good!</description>
	<pubDate>Wed, 01 Jul 2009 18:33:14 +0000</pubDate>
</item>
<item>
	<title>Tim Riley: Using RSpec Ordered Message Expectations to Tighten your Specs</title>
	<guid>tag:openmonkey.com,2009-04-25:/articles/2009/07/rspec-ordered-message-expectations</guid>
	<link>http://feedproxy.google.com/~r/BlahBlahWoofWoof/~3/DRoxyTl-020/rspec-ordered-message-expectations</link>
	<description>&lt;p&gt;I quite enjoy the competitive undercurrent of ping pong pair programming. As the person writing the implementation code, it is fun to write something that will turn a test green, but still not necessarily do what my partner was expecting. Taking this approach has also been helpful for improving our specs. Take this example controller spec:&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ArticlesController&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;handling create&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;before&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@article&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mock_model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Article&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:save&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;Article&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;and_return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@article&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      
      &lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mock_model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;controller&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:current_user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;and_return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;should build a new article from posted data&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;Article&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;should_receive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'title'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Test Post'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:article&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Test Post'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;should assign the current user as the article's author&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@article&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;should_receive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:author&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:create&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;should save the article&quot;&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@article&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;should_receive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:create&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This looks like a reasonable set of concise, clear examples, but you can easily make them all pass and without building a controller action that does what you expect:&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ArticlesController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@article&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Article&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:article&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@article&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@article&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current_user&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This satisfies the examples, but saving the article &lt;em&gt;before&lt;/em&gt; assigning the current user as author isn’t what we would have intended. Enter RSpec’s &lt;a href=&quot;http://rspec.info/documentation/mocks/message_expectations.html&quot;&gt;ordered message expectations&lt;/a&gt;. These allow you to specify the order in which you expect an object to receive message calls.&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ArticlesController&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;handling create&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;should save the article after assigning the current user as author&quot;&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@article&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;should_receive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:author&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ordered&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@article&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;should_receive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ordered&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:create&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This example would fail with the above controller action, and force us to write it properly:&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ArticlesController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@article&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Article&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:article&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@article&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current_user&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@article&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The result is a controller that does what you expect, a stronger set of specs, and an increased capacity for true behaviour driven development. Win, win, win!&lt;/p&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;http://feeds.feedburner.com/~r/BlahBlahWoofWoof/~4/DRoxyTl-020&quot; /&gt;</description>
	<pubDate>Wed, 01 Jul 2009 14:33:41 +0000</pubDate>
</item>
<item>
	<title>Tim Riley: De-@wip Your Cucumber Stories</title>
	<guid>tag:openmonkey.com,2009-04-25:/articles/2009/06/de-wip-your-cucumber-stories</guid>
	<link>http://feedproxy.google.com/~r/BlahBlahWoofWoof/~3/MG8SCjzjxJY/de-wip-your-cucumber-stories</link>
	<description>&lt;p&gt;We’ve been really hitting the &lt;a href=&quot;http://cukes.info/&quot;&gt;Cucumber&lt;/a&gt; hard in the recent few iterations of our current project. Now that we’re &lt;a href=&quot;http://en.wikipedia.org/wiki/Pair_programming#Ping_pong_pair_programming&quot;&gt;ping pong pair programming&lt;/a&gt;, the Cucumber story is the first thing we write, and we revisit regularly during the &lt;a href=&quot;http://jamesshore.com/Blog/Red-Green-Refactor.html&quot;&gt;red-green-refactor&lt;/a&gt; cycle.&lt;/p&gt;
        
        
        	&lt;p&gt;To make this easy, we place a &lt;code&gt;@wip&lt;/code&gt; &lt;em&gt;work in progress&lt;/em&gt; &lt;a href=&quot;http://wiki.github.com/aslakhellesoy/cucumber/tags&quot;&gt;tag&lt;/a&gt; at the top of the current stories:&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;no&quot;&gt;Feature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Make&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;coffee&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# This one is done.&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Scenario&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;First&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;coffee&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;day&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;# This is the one we're working on.&lt;/span&gt;
  &lt;span class=&quot;vi&quot;&gt;@wip&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Scenario&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Afternoon&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;perk&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;up&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then we use &lt;code&gt;cucumber -t wip&lt;/code&gt; to run just the stories in progress. Once the stories are green and we’re happy to move on, we often forget to remove the &lt;code&gt;@wip&lt;/code&gt; tags before committing. I wrote a little sed command in a bash alias to make this easier:&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# Remove any @wip tags from Cucumber features.&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dewip&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;sed -E -i '' -e '/^[[:blank:]]*@wip$/d;s/,[[:blank:]]*@wip//g;s/@wip,[[:blank:]]*//g' features/**/*.feature&quot;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Throw it in your &lt;code&gt;.bash_profile&lt;/code&gt; for ease of access! Here’s a &lt;a href=&quot;http://gist.github.com/136294&quot;&gt;gist&lt;/a&gt; for your forking pleasure.&lt;/p&gt;
      &lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;http://feeds.feedburner.com/~r/BlahBlahWoofWoof/~4/MG8SCjzjxJY&quot; /&gt;</description>
	<pubDate>Wed, 01 Jul 2009 14:33:41 +0000</pubDate>
</item>
<item>
	<title>Tim Riley: Rails Templates as the New Geek Code</title>
	<guid>tag:openmonkey.com,2009-04-25:/articles/2009/05/rails-templates-as-geek-code</guid>
	<link>http://feedproxy.google.com/~r/BlahBlahWoofWoof/~3/7Xli_qTqV0I/rails-templates-as-geek-code</link>
	<description>&lt;p&gt;Anyone who’s been around the Internet long enough should remember &lt;a href=&quot;http://www.geekcode.com/&quot;&gt;The Geek Code&lt;/a&gt;. This meme sought to provide a – however obsbcure – succinct textual distillation of the attributes and interests of any geek.&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;GED/J d-- s:++&amp;gt;: a-- C++(++++) ULU++ P+ L++ E---- W+(-) N+++ o+ K+++ w---
O- M+ V-- PS++&amp;gt;$ PE++&amp;gt;$ Y++ PGP++ t- 5+++ X++ R+++&amp;gt;$ tv+ b+ DI+++ D+++
G+++++ e++ h r-- y++**&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This geek code block represents someone trained in education and law who is tall and dresses casually, knows his way around Linux and Ultrix pretty well, hates emacs, but loves indulging in a little Dilbert. &lt;a href=&quot;http://www.geekcode.com/geek.html&quot;&gt;Look it up&lt;/a&gt;, it’s elaborate.&lt;/p&gt;
        
        
        	&lt;p&gt;Today, a Rails developer can provide a &lt;a href=&quot;http://m.onkey.org/2008/12/4/rails-templates&quot;&gt;template&lt;/a&gt; for generating new apps that can uniquely embody all their development tools and preferences in a single place.&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'haml'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'mislav-will_paginate'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;   &lt;span class=&quot;ss&quot;&gt;:lib&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'will_paginate'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;ss&quot;&gt;:source&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'http://gems.github.com'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'chriseppstein-compass'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;ss&quot;&gt;:lib&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'compass'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;        &lt;span class=&quot;ss&quot;&gt;:source&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'http://gems.github.com'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'thoughtbot-paperclip'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;   &lt;span class=&quot;ss&quot;&gt;:lib&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'paperclip'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;      &lt;span class=&quot;ss&quot;&gt;:source&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'http://gems.github.com'&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;yes?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Paperclip gem?'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'authlogic'&lt;/span&gt;                                                                               &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;yes?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Authlogic gem?'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You’re a haml guy? Right on. Plus compass for &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt;! You must like really things semantic.&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'.testgems'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;%q{config.gem 'rspec'&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;config.gem 'rspec-rails'&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;config.gem 'notahat-machinist', :lib =&amp;gt; 'machinist',  :source =&amp;gt; 'http://gems.github.com'&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;config.gem 'ianwhite-pickle',   :lib =&amp;gt; 'pickle',     :source =&amp;gt; 'http://gems.github.com'&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;config.gem 'webrat'&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;config.gem 'cucumber'&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'cat .testgems &amp;gt;&amp;gt; config/environments/test.rb &amp;amp;&amp;amp; rm .testgems'&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;RSpec along with Cucumber backed by Machinist and Pickle for test data factories. You must be Australian. But that’s cool, that’s a pretty helpful combo for tests.&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:init&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:add&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'.'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:commit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'-a -m &quot;Initial commit from AMC Rails template&quot;'&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Building a complete Rails template has been really useful for us at the &lt;a href=&quot;http://www.amc.org.au/&quot;&gt;&lt;span class=&quot;caps&quot;&gt;AMC&lt;/span&gt;&lt;/a&gt;. We’re often asked to bring up quick, single-purpose apps alongside the many components that we’re building in our mostly service-oriented architecture.&lt;/p&gt;
        
        
        	&lt;p&gt;Our template is &lt;a href=&quot;http://github.com/timriley/amc-rails-template&quot;&gt;available on GitHub&lt;/a&gt; for your perusal and reuse. It does everything from setting up plugins and gem dependencies, to generating a deploy script using our custom capistrano extensions, to including a default layout and stylesheet. This is how we roll, captured in a single file.&lt;/p&gt;
      &lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;http://feeds.feedburner.com/~r/BlahBlahWoofWoof/~4/7Xli_qTqV0I&quot; /&gt;</description>
	<pubDate>Wed, 01 Jul 2009 14:33:41 +0000</pubDate>
</item>
<item>
	<title>Tim Riley: Importing Legacy Data in Rails</title>
	<guid>tag:openmonkey.com,2009-04-25:/articles/2009/05/importing-legacy-data-in-rails</guid>
	<link>http://feedproxy.google.com/~r/BlahBlahWoofWoof/~3/kTFQNYv-4Qo/importing-legacy-data-in-rails</link>
	<description>&lt;h2&gt;How Did we Get Here?&lt;/h2&gt;
        
        
        	&lt;p&gt;Our current &lt;a href=&quot;http://www.amc.org.au/&quot;&gt;work&lt;/a&gt; project is a long-overdue rebuild of a critical business system as a modern Rails web app. We’re building this thing according to agile practices to the best of our ability. Each week we provide a new, working release that is an incremental improvement on the last. We’re not looking to replace the current system in a single swoop, and expect the new system to work alongside the old one for quite a while.&lt;/p&gt;
        
        
        	&lt;p&gt;This means that we’ll need to maintain the same data in both systems for the duration of their lives together. We don’t want the new Rails app to access the data directly from the old app’s database, since this would prevent us from following the conventions that makes working with Rails so pleasant. Instead, we’ve come up with a way to import the legacy data into a new database.&lt;/p&gt;
        
        
        	&lt;p&gt;In doing this, I’ve built a Rails plugin to make the experience easier. It is called &lt;strong&gt;Acts as Importable&lt;/strong&gt; and it is now &lt;a href=&quot;http://github.com/timriley/acts-as-importable&quot;&gt;available on GitHub&lt;/a&gt;. This article will show our technique for importing the legacy data and how Acts as Importable helps.&lt;/p&gt;
        
        
        	&lt;h2&gt;Accessing the Legacy Data&lt;/h2&gt;
        
        
        	&lt;p&gt;We use ActiveRecord to access the legacy data. It takes a bit of legwork to shoehorn the legacy schema into ActiveRecord models, but once that is done, we have satisfactory access to the data we want to import.&lt;/p&gt;
        
        
        	&lt;p&gt;The first thing we do is provide a &lt;code&gt;Legacy::Base&lt;/code&gt; model from which all other legacy models can inherit. This provides a single place to define access to the legacy database.&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abstract_class&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;establish_connection&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;legacy_&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;acts_as_importable&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can setup the extra database connections in &lt;code&gt;config/database.yml&lt;/code&gt;, like below. Our legacy connection is to an &lt;span class=&quot;caps&quot;&gt;MS SQL&lt;/span&gt; server via &lt;span class=&quot;caps&quot;&gt;ODBC&lt;/span&gt;. Tim Lucas has &lt;a href=&quot;http://toolmantim.com/articles/getting_rails_talking_to_sqlserver_on_osx_via_odbc&quot;&gt;an excellent tutorial&lt;/a&gt; on how to get that set up.&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;l-Scalar-Plain&quot;&gt;legacy_development&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;adapter&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;sqlserver&lt;/span&gt;
  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;odbc&lt;/span&gt;
  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;dsn&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;LEGACY&lt;/span&gt;
  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;autocommit&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;localhost&lt;/span&gt;
  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;NTDOMAIN\username&lt;/span&gt;
  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;password&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, here are a couple of the legacy models that inherit from &lt;code&gt;Legacy::Base&lt;/code&gt; to access the legacy database. For the sake of this article, consider the code examples to come from a quiz application with models for categories, questions, and responses.&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Question&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;set_table_name&lt;/span&gt;  &lt;span class=&quot;s1&quot;&gt;'quiz_questions'&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;set_primary_key&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'QuestionNumber'&lt;/span&gt;
  
  &lt;span class=&quot;n&quot;&gt;belongs_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:category&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
             &lt;span class=&quot;ss&quot;&gt;:class_name&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Legacy::Category'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
             &lt;span class=&quot;ss&quot;&gt;:foreign_key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'CategoryCode'&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Category&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;set_table_name&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'quiz_categories'&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;set_primary_key&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Code'&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These are simple examples, but you get the idea. &lt;code&gt;set_table_name&lt;/code&gt; and &lt;code&gt;set_primary_key&lt;/code&gt; are your friends when you have table names and keys that defy Rails’ conventions. If you want to use ActiveRecord associations to access your legacy data, you will also want to become familiar with the options available for specifying things like the class, join table and column names. Check the rdocs for &lt;code&gt;has_many&lt;/code&gt;, &lt;code&gt;belongs_to&lt;/code&gt; and &lt;code&gt;has_and_belongs_to_many&lt;/code&gt; and look out for options like &lt;code&gt;:class_name&lt;/code&gt;, &lt;code&gt;:foreign_key&lt;/code&gt;, &lt;code&gt;:join_table&lt;/code&gt;, and &lt;code&gt;:association_foreign_key&lt;/code&gt;.&lt;/p&gt;
        
        
        	&lt;h2&gt;Converting the Legacy Data&lt;/h2&gt;
        
        
        	&lt;p&gt;Each of the legacy models provides a &lt;code&gt;to_model&lt;/code&gt; method that returns a new model ready to be saved into the new, non-legacy database.&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c1&quot;&gt;# New model&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Category&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Legacy model&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Category&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;set_table_name&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'quiz_categories'&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;set_primary_key&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Code'&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;to_model&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Category&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Description&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2&gt;Importing the Legacy Data&lt;/h2&gt;
        
        
        	&lt;p&gt;Now that the import rules are defined for all the legacy models we care about, how do we get them all into the new database? This is where &lt;a href=&quot;http://github.com/timriley/acts_as_importable&quot;&gt;Acts as Importable&lt;/a&gt; comes in. This plugin helps to smoothen the import of an entire system’s worth of legacy data. You saw it enabled above in the &lt;code&gt;Legacy::Base&lt;/code&gt; class:&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abstract_class&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;establish_connection&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;legacy_&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;acts_as_importable&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Acts as importable will let you import your legacy models in different ways:&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c1&quot;&gt;# Import a single question&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Question&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;123&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# or&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Question&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;123&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;import&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Import all questions&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Question&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;import_all&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Import all the questions, 1000 at a time&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Question&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;import_all_in_batches&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These are all different ways of instantiating your legacy models, calling the &lt;code&gt;to_model&lt;/code&gt; method, and saving the returned object. The value of the plugin is that it adds a little bit of extra smarts to this basic premise.&lt;/p&gt;
        
        
        	&lt;h3&gt;belongs_to Relationships &amp;amp; Caching&lt;/h3&gt;
        
        
        	&lt;p&gt;Acts as Importable provides a &lt;code&gt;lookup&lt;/code&gt; class method for finding the new ID of an imported legacy model. When each legacy model is imported using the above methods, Acts as Importable saves the legacy model’s class name and ID along with the rest of the data in new model (be sure to provide &lt;code&gt;legacy_class&lt;/code&gt; and &lt;code&gt;legacy_id&lt;/code&gt; columns for this to work). The first time you &lt;code&gt;lookup&lt;/code&gt; a legacy record, it uses &lt;code&gt;ActiveRecord::Base#find&lt;/code&gt; with the appropriate values for &lt;code&gt;legacy_class&lt;/code&gt; and &lt;code&gt;legacy_id&lt;/code&gt; as conditions. It will save the ID in a lookup hash in memory, so that the next time you want to lookup from the same ID, the result is returned without a trip to the database.&lt;/p&gt;
        
        
        	&lt;p&gt;This is really best seen in action:&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c1&quot;&gt;# New models&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Question&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;belongs_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:category&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:responses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:dependent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:destroy&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Category&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:questions&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Legacy model&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Question&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;to_model&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Question&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# import the category association&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;category_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Category&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lookup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;category&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Setting the id for associations directly like this is important for conserving trips to the database importing a model’s &lt;code&gt;belongs_to&lt;/code&gt; relationships, just like the one above. Be wary when using lookups for large data sets, however, as it will likely consume quite a bit of memory to store the ID mappings.&lt;/p&gt;
        
        
        	&lt;p&gt;As an aside, we use &lt;code&gt;#try(:id__)&lt;/code&gt; on the legacy model to provide the ID for the lookup, because &lt;code&gt;#id&lt;/code&gt; on a nil value actually returns its &lt;code&gt;#object_id&lt;/code&gt;. If the associated object doesn’t exist, we don’t want to pass a bogus ID. Acts as Importable provides &lt;code&gt;Object#try&lt;/code&gt; and the &lt;code&gt;ActiveRecord::Base#id__&lt;/code&gt; to &lt;code&gt;id&lt;/code&gt; alias for you.&lt;/p&gt;
        
        
        	&lt;p&gt;The lookups will work automatically if the class name of the model you’re importing is the same as the legacy model’s, eg. &lt;code&gt;Legacy::Question&lt;/code&gt; to &lt;code&gt;Question&lt;/code&gt;. If the class name of the model you’re creating is different, you can tell that to Acts as Importable so that the lookups can continue to work:&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c1&quot;&gt;# New model&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DifferentThing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Legacy model&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Thing&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;acts_as_importable&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:to&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'DifferentThing'&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;to_model&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;DifferentThing&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3&gt;has_many Relationships &amp;amp; Building&lt;/h3&gt;
        
        
        	&lt;p&gt;You can import &lt;code&gt;has_many&lt;/code&gt; relationships quite easily, using the &lt;code&gt;#build&lt;/code&gt; method on the association proxy. Here it is in action, expanding on the Question’s &lt;code&gt;#to_model&lt;/code&gt; method from above:&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c1&quot;&gt;# New models&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Question&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;belongs_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:category&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;belongs_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:question&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Legacy model&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Question&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;to_model&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Question&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;category_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Category&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lookup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;category&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      
      &lt;span class=&quot;c1&quot;&gt;# Build the responses&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;responses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:body&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:&quot;response_&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When you save the new model, the newly built associated models are saved too.&lt;/p&gt;
        
        
        	&lt;h3&gt;Importing Large Sets of Legacy Records&lt;/h3&gt;
        
        
        	&lt;p&gt;We ran into some slowness importing legacy models with large numbers of records, or with other models with large amounts of data in particular fields. To get around this, we use &lt;code&gt;#import_all_in_batches&lt;/code&gt;, which only retrieves 1000 models at a time for processing. This is based on Jamis Buck’s technique for &lt;a href=&quot;http://weblog.jamisbuck.org/2007/4/6/faking-cursors-in-activerecord&quot;&gt;faking cursors in ActiveRecord&lt;/a&gt;, and as such, it requires a numeric primary key for the legacy models (you’d normally expect this to be the case, but it isn’t for a few of our legacy tables).&lt;/p&gt;
        
        
        	&lt;h3&gt;Idempotence of Imports&lt;/h3&gt;
        
        
        	&lt;p&gt;As I mentioned in the introduction, the legacy app we’re replacing will remain in use as we incrementally build the new system. We will need to continue to synchronise the legacy data with the new system during this time. We’ll therefore need our import process to be &lt;a href=&quot;http://en.wikipedia.org/wiki/Idempotence&quot;&gt;idempotent&lt;/a&gt;, meaning that multiple imports can run and result in the same set of data at the other end. Mostly, this just means that we’ll want to avoid creation of duplicate records in the new database.&lt;/p&gt;
        
        
        	&lt;p&gt;We approach this pretty simply. Each night the old records are deleted and new ones re-imported in their place. You’ll want to pick an approach that best suits your situation.&lt;/p&gt;
        
        
        	&lt;p&gt;There is one complication, however, insofar as the new system is used to create some entirely new content that relates to the imported models. If models are deleted and re-imported from the legacy system every night, their IDs would be different each time. To get around this, we hard-code the ID of certain imported models to the same value as their respective legacy model’s ID. This is very simply done:&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Question&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;to_model&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Question&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# Hard-code the ID&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;
      
      &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;category_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Category&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lookup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;category&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;responses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:body&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:&quot;response_&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2&gt;Final steps&lt;/h2&gt;
        
        
        	&lt;p&gt;There are two final pieces to our import system. Firstly, a way to control the order of the imports:&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Importer&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Category&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;import_all&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Question&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;import_all_in_batches&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Flush all the lookup tables&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Category&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flush_lookups!&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Question&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flush_lookups!&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It is important to control the order if your imported models are going to relate to each other. Some records will need to exist before the others can link to them.&lt;/p&gt;
        
        
        	&lt;p&gt;And finally, a rake task:&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:legacy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Import the legacy data.&quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:import&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:environment&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Importer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That’s it! This approach certainly works to our liking, but I would love to hear your thoughts on this issue. Please feel free to post a comment below.&lt;/p&gt;
        
        
        	&lt;h2&gt;Further Reading&lt;/h2&gt;
        
        
        	&lt;p&gt;These articles were of great use in getting our legacy imports up and running:&lt;/p&gt;
        
        
        	&lt;ul&gt;
        	&lt;li&gt;&lt;a href=&quot;http://pragdave.blogs.pragprog.com/pragdave/2006/01/sharing_externa.html&quot;&gt;Sharing External ActiveRecord Connections&lt;/a&gt;&lt;/li&gt;
        		&lt;li&gt;&lt;a href=&quot;http://www.pathf.com/blogs/2008/03/using-activerec/&quot;&gt;Agile Ajax » Using ActiveRecord to Migrate Legacy Data&lt;/a&gt;&lt;/li&gt;
        	&lt;/ul&gt;
      &lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;http://feeds.feedburner.com/~r/BlahBlahWoofWoof/~4/kTFQNYv-4Qo&quot; /&gt;</description>
	<pubDate>Wed, 01 Jul 2009 14:33:41 +0000</pubDate>
</item>
<item>
	<title>Tim Riley: Adaptive script/console Shell Alias for both Rails and Sinatra</title>
	<guid>tag:openmonkey.com,2009-04-25:/articles/2009/03/adaptive-script-console-shell-alias-for-both-rails-and-sinatra</guid>
	<link>http://feedproxy.google.com/~r/BlahBlahWoofWoof/~3/whchNFTMCEY/adaptive-script-console-shell-alias-for-both-rails-and-sinatra</link>
	<description>&lt;p&gt;Like many keystroke-efficient Rails hackers, I’ve long had a line in my &lt;code&gt;.bash_profile&lt;/code&gt; file to alias &lt;code&gt;sc&lt;/code&gt; to &lt;code&gt;script/console&lt;/code&gt;, along with a &lt;a href=&quot;http://gist.github.com/74761&quot;&gt;host of other tricks&lt;/a&gt;.&lt;/p&gt;
        
        
        	&lt;p&gt;This shortcut was more than sufficient until recently, when I started writing Sinatra apps. The minimal framework that it is, Sinatra doesn’t provide a console script like Rails, but I found you can easily achieve the same effect by running &lt;code&gt;irb -r your_sinatra_app.rb&lt;/code&gt;.&lt;/p&gt;
        
        
        	&lt;p&gt;Not wanting my fingers to have to deviate from habits long held, I changed my &lt;code&gt;sc&lt;/code&gt; alias into a full-blown bash function that will drop you into a Rails console, Sinatra console or just a plain irb console based on your location within the filesystem:&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;function &lt;/span&gt;sc &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; -x script/console &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;    &lt;/span&gt;script/console
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;sinatra_rb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;egrep -l &lt;span class=&quot;s2&quot;&gt;&quot;^require.+sinatra.$&quot;&lt;/span&gt; *.rb 2&amp;gt;/dev/null&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; -e &lt;span class=&quot;nv&quot;&gt;$sinatra_rb&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;      &lt;/span&gt;irb -r &lt;span class=&quot;nv&quot;&gt;$sinatra_rb&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;      &lt;/span&gt;irb
    &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;  fi&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Throw it in your &lt;code&gt;.bash_profile&lt;/code&gt; and have fun!&lt;/p&gt;
      &lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;http://feeds.feedburner.com/~r/BlahBlahWoofWoof/~4/whchNFTMCEY&quot; /&gt;</description>
	<pubDate>Wed, 01 Jul 2009 14:33:41 +0000</pubDate>
</item>
<item>
	<title>Miklos Bacso: Ancsa's pictures in Canada</title>
	<guid>http://miklos.ca/log/2009/07/ancsas-pictures-in-canada.html</guid>
	<link>http://feedproxy.google.com/~r/memento_log/~3/x_8H4rSNhJY/ancsas-pictures-in-canada.html</link>
	<description>My cousin Anita from Hungary is staying with us for 6 weeks. View her photo journal at &lt;a href=&quot;http://imgs.miklos.ca/archives/ancsa_2009/&quot;&gt;http://imgs.miklos.ca/archives/ancsa_2009/&lt;/a&gt;</description>
	<pubDate>Wed, 01 Jul 2009 12:39:47 +0000</pubDate>
</item>
<item>
	<title>Og Maciel: Going to GUADEC</title>
	<guid>http://www.ogmaciel.com/?p=714</guid>
	<link>http://www.ogmaciel.com/?p=714</link>
	<description>&lt;p&gt;&lt;img class=&quot;alignleft size-full wp-image-715&quot; title=&quot;GUADEC Sponsored&quot; src=&quot;http://www.ogmaciel.com/wp-content/uploads/2009/06/sponsored-badge-simple.png&quot; alt=&quot;GUADEC Sponsored&quot; width=&quot;213&quot; height=&quot;213&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Thanks to the amazing support from the &lt;strong&gt;GNOME Travel Committee&lt;/strong&gt;, I will be attending my first &lt;a href=&quot;http://www.grancanariadesktopsummit.org/&quot;&gt;GUADEC&lt;/a&gt; this year in Gran Canaria! I am very thankful for their commitment to accomodate my needs and I&amp;#8217;ll try to make the most of it!&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll be arriving July 3rd around lunch time and will stay until the 11th, so there will be plenty of time to meet up and discuss. I&amp;#8217;m mostly interested in localization, accessibility, and tests automation but am equaly interested in community building and the organization toward GNOME 3.0!&lt;/p&gt;
&lt;p&gt;If you see some really fast crutches running around the terminals in Boston or Madrid, come by and say hi to me! &lt;img src=&quot;http://www.ogmaciel.com/wp-includes/images/smilies/icon_smile.gif&quot; alt=&quot;:)&quot; class=&quot;wp-smiley&quot; /&gt; &lt;/p&gt;</description>
	<pubDate>Tue, 30 Jun 2009 13:22:23 +0000</pubDate>
</item>
<item>
	<title>Akkana Peck: A Beginner's Guide to Free Software Programming Languages</title>
	<guid>http://shallowsky.com/blog/writing/prog-lang-intro.html</guid>
	<link>http://shallowsky.com/blog/writing/prog-lang-intro.html</link>
	<description>Linux Planet asked me for an intro article for prospective
programmers, explaining the pros and cons of various programming
languages. Here it is:
&lt;a href=&quot;http://www.linuxplanet.com/linuxplanet/tutorials/6784/&quot;&gt;A
 Beginner's Guide to Free Software Programming Languages&lt;/a&gt;</description>
	<pubDate>Sun, 28 Jun 2009 20:00:00 +0000</pubDate>
</item>
<item>
	<title>Akkana Peck: Keeping external kernel modules from being deleted</title>
	<guid>http://shallowsky.com/blog/linux/kernel/external-kernel-modules.html</guid>
	<link>http://shallowsky.com/blog/linux/kernel/external-kernel-modules.html</link>
	<description>I've been enjoying my
&lt;a href=&quot;http://shallowsky.com/blog/linux/randombeeps.html&quot;&gt;random
system beeps&lt;/a&gt;, different every day. At least up until yesterday,
when I didn't seem to have one. Today I didn't have one either,
and discovered that was because the beep module was no longer loaded.
&lt;p&gt;
Why not? Well, I updated my kernel to tweak some ACPI parameters
(fruitlessly, as it turns out; I'm trying to get powertop to give
me more information but I haven't found the magic combination of
kernel parameters it wants on this machine) and so I did a
&lt;code&gt;make modules_install&lt;/code&gt;. And it seems that
&lt;code&gt;make modules_install&lt;/code&gt; starts out by doing
&lt;code&gt;rm -rf /lib/modules/&lt;i&gt;VERSION&lt;/i&gt;/kernel&lt;/code&gt; which removed
my externally built beep module along with everything else.
&lt;p&gt;
I couldn't find documentation on this, but I did find
&lt;a href=&quot;http://intellinuxwireless.org/bugzilla/show_bug.cgi?id=556&quot;&gt;Intel
Wireless bug 556&lt;/a&gt; which talks about the issue. Apparently
somewhere along the way 2.6 started doing this rm -rf,
but you can get around it by installing outside the &lt;i&gt;kernel&lt;/i&gt;
directory.
&lt;p&gt;
In other words, instead of
&lt;pre&gt;
cp beep.ko /lib/modules/2.6.29.4/kernel/drivers/input/misc/
&lt;/pre&gt;
do 
&lt;pre&gt;
cp beep.ko /lib/modules/2.6.29.4/drivers/input/misc/
&lt;/pre&gt;
Then your external module won't get wiped out at the next
&lt;code&gt;modules_install&lt;/code&gt;.
&lt;p&gt;
I've let the maintainer of
&lt;a href=&quot;http://www.carcosa.net/jason/software/beep/&quot;&gt;Fancy Beeper&lt;/a&gt;
know about this, so it won't be a problem for that module,
but it's a good tip to know about in general --
I'm sure there are lots of modules that hit this problem.&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;</description>
	<pubDate>Wed, 24 Jun 2009 17:30:00 +0000</pubDate>
</item>
<item>
	<title>David Barr: All good things must come to an end, but all bad things can continue forever</title>
	<guid>http://david.chalkskeletons.com/blog/?p=79</guid>
	<link>http://david.chalkskeletons.com/blog/?p=79</link>
	<description>&lt;p&gt;It has come to my attention that I have generally knocked out a blag every month, it seems a shame to break this amazing run.&lt;/p&gt;
&lt;p&gt;I have nothing much to reckon really, but I have started to learn how to use GIT, which is sort of interesting. I&amp;#8217;m using &lt;a href=&quot;http://github.com&quot;&gt;github&lt;/a&gt; as it seems the easiest way to get started and i don&amp;#8217;t know enough to overly criticism it in anyway. I am more or less incapable of coding to an acceptable standard, so my repos are all theme related. I hope to add a couple of little hacks when I move on to learning how to fork or whatever, and possibly some php frame work stuff - which isn&amp;#8217;t real code ;) But right now I just need *something* to learn with.&lt;/p&gt;
&lt;p&gt;It is mostly older stuff that I update a bit but never really publically make any &amp;#8216;releases&amp;#8217;&lt;/p&gt;
&lt;p&gt;They are all &lt;a href=&quot;http://github.com/mulberry/&quot;&gt;here&lt;/a&gt;. There are a couple of icon themes (&lt;a href=&quot;http://github.com/mulberry/Eggshell-Icon-Theme/tree/master&quot;&gt;Eggshell&lt;/a&gt; should really be a branch of &lt;a href=&quot;http://github.com/mulberry/Ecru-Icon-Theme/tree/master&quot;&gt;Ecru&lt;/a&gt;) and a&lt;a href=&quot;https://github.com/mulberry/Ecru-Meta-Theme/tree&quot;&gt; meta-theme&lt;/a&gt; (metacity, openbox, gtk) and other themes maybe.&lt;/p&gt;
&lt;p&gt;Anyway that is all.&lt;/p&gt;</description>
	<pubDate>Tue, 23 Jun 2009 17:28:34 +0000</pubDate>
</item>
<item>
	<title>Akkana Peck: Pytopo 0.8 released</title>
	<guid>http://shallowsky.com/blog/programming/pytopo-0.8.html</guid>
	<link>http://shallowsky.com/blog/programming/pytopo-0.8.html</link>
	<description>On my last Mojave trip, I spent a lot of the evenings hacking on
&lt;a href=&quot;http://shallowsky.com/software/topo/&quot;&gt;PyTopo&lt;/a&gt;.
&lt;p&gt;
I was going to try to stick to OpenStreetMap and other existing mapping
applications like TangoGPS, a neat little smartphone app for
downloading OpenStreetMap tiles that also runs on the desktop -- 
but really, there still isn't any mapping app that works well enough
for exploring maps when you have no net connection.
&lt;p&gt;
In particular, uploading my GPS track logs after a day of mapping,
I discovered that Tango really wasn't a good way of exploring them,
and I already know Merkaartor, nice as it is for entering new OSM
data, isn't very good at working offline. There I was, with PyTopo
and a boring hotel room; I couldn't stop myself from tweaking a bit.
&lt;p&gt;
Adding tracklogs was gratifyingly easy. But other aspects of the
code bother me, and when I started looking at what I might need to
do to display those Tango/OSM tiles ... well, I've known for a while
that some day I'd need to refactor PyTopo's code, and now was the time.
&lt;p&gt;
Surprisingly, I completed most of the refactoring on the trip.
But even after the refactoring, displaying those OSM tiles turned out
to be a lot harder than I'd hoped, because I couldn't find any
reliable way of mapping a tile name to the coordinates of that tile.
I haven't found any documentation on that anywhere, and Tango and
several other programs all do it differently and get slightly
different coordinates.  That one problem was to occupy my spare time
for weeks after I got home, and I still don't have it solved.
&lt;p&gt;
But meanwhile, the rest of the refactoring was done, nice features
like track logs were working, and I've had to move on to other
projects. I am going to finish the OSM tile MapCollection class,
but why hold up a release with a lot of useful changes just for that?
&lt;p&gt;
So here's &lt;a href=&quot;http://shallowsky.com/software/topo/&quot;&gt;PyTopo 0.8&lt;/a&gt;,
and the couple of known problems with the new features will have to wait
for 0.9.&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;</description>
	<pubDate>Sun, 21 Jun 2009 03:49:00 +0000</pubDate>
</item>
<item>
	<title>Akkana Peck: Python: show all methods in a given object or module</title>
	<guid>http://shallowsky.com/blog/programming/python-allmethods.html</guid>
	<link>http://shallowsky.com/blog/programming/python-allmethods.html</link>
	<description>A silly little thing, but something that Python books mostly don't
mention and I can never find via Google:
&lt;p&gt;
How do you find all the methods in a given class, object or module?
&lt;p&gt;
Ideally the documentation would tell you.  Wouldn't that be nice?
But in the real world, you can't count on that,
and examining all of an object's available methods can often give
you a good guess at how to do whatever you're trying to do.
&lt;p&gt;
Python objects keep their symbol table in a dictionary
called __dict__ (that's two underscores on either end of the word).
So just look at &lt;code&gt;object.__dict__&lt;/code&gt;. If you just want the
names of the functions, use &lt;code&gt;object.__dict__.keys()&lt;/code&gt;.
&lt;p&gt;
&lt;p class=&quot;update&quot;&gt;
Thanks to JanC for suggesting dir(object) and help(object), which
can be more helpful -- not all objects have a __dict__.
&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;</description>
	<pubDate>Fri, 19 Jun 2009 19:44:00 +0000</pubDate>
</item>
<item>
	<title>Lostson: ugh</title>
	<guid>http://lostsonsvault.org/geek/?p=127</guid>
	<link>http://lostsonsvault.org/geek/?p=127</link>
	<description>&lt;p&gt;Well its getting hot, and nothing like having to wear long sleeves in your job when your outside all day in the blistering sun !!&lt;/p&gt;</description>
	<pubDate>Fri, 19 Jun 2009 03:55:40 +0000</pubDate>
</item>
<item>
	<title>Akkana Peck: Random beeps</title>
	<guid>http://shallowsky.com/blog/linux/randombeeps.html</guid>
	<link>http://shallowsky.com/blog/linux/randombeeps.html</link>
	<description>A couple of year ago I figured out how to make
&lt;a href=&quot;http://shallowsky.com/blog/linux/custom-beep.html&quot;&gt;custom
system beep sounds&lt;/a&gt; on Linux, like MacOS has done forever.
But then I changed machines and somehow never got around to setting it
up on any other machine.
&lt;p&gt;
But the Intel dual-Atom board doesn't seem to support a system beep --
there's no obvious place on the motherboard to plug in the connector
going to the case speaker. How odd!
&lt;p&gt;
With the alternative being no beep at all,
I dusted off my old blog post and went to see if
&lt;a href=&quot;http://www.carcosa.net/jason/software/beep/&quot;&gt;Fancy Beeper
Daemon&lt;/a&gt; kernel module still existed. Happily, it does, and it's
up-to-date for current kernels, so all I had to do was download the
latest and build it. Easy! Then I added &quot;beep&quot; to the list of
automatically loaded modules in &lt;code&gt;/etc/modules&lt;/code&gt;,
blacklisted the pcspkr module using the
&lt;a href=&quot;http://shallowsky.com/blog/linux/etch-firewire-net.html&quot;&gt;/etc/modprobe.d/00local
technique&lt;/a&gt;, and I was all set.
&lt;p&gt;
Except for the &lt;i&gt;really&lt;/i&gt; important question: what sound to choose?
I did a little web searching for free sounds and downloaded some samples
to try out. Then I added a few bird calls from my
&lt;a href=&quot;http://www.amazon.com/exec/obidos/ASIN/1570425884/shallowsky-20&quot;&gt;Stokes
Field Guide to Western Bird Songs&lt;/a&gt; CD,
editing them in audacity to make them shorter and
more appropriate for system beeps.
&lt;p&gt;
But I still couldn't decide on just one ... and why should I?
I've really been enjoying my
&lt;a href=&quot;http://shallowsky.com/blog/programming/random-wallpaper.html&quot;&gt;random
wallpaper&lt;/a&gt;: every time I log in, I get a different desktop background.
It's fun to see a new picture every day.
Why not do the same for my system beep?
&lt;p&gt;
That's no problem, using the same
&lt;a href=&quot;http://shallowsky.com/software/scripts/randomline&quot;&gt;randomline&lt;/a&gt;
script I use for wallpaper. I just put this in my .xinitrc:

&lt;pre&gt;
$HOME/bin/mybeepd `find $HOME/Music/beeps -name &quot;*.wav&quot; | randomline` &amp;amp;
&lt;/pre&gt;

and now I get a different beep sound each day.

&lt;p&gt;
Yesterday it was a loon. Today it's a cow mooing.&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;</description>
	<pubDate>Thu, 18 Jun 2009 04:11:00 +0000</pubDate>
</item>
<item>
	<title>Akkana Peck: Programming With PyGTK, part 3: Key events and object oriented Python</title>
	<guid>http://shallowsky.com/blog/writing/python-gtk-graphics-3.html</guid>
	<link>http://shallowsky.com/blog/writing/python-gtk-graphics-3.html</link>
	<description>Part 3 of &quot;Graphical Python Programming With PyGTK&quot;
uses object-oriented Python to clean up the code from Part 2,
and also adds handling of key events to get rid of that silly
Quit button.
&lt;a href=&quot;http://www.linuxplanet.com/linuxplanet/tutorials/6771/&quot;&gt;PythonGTK
Programming part 3: Screensaver, Objects, and User Input&lt;/a&gt;</description>
	<pubDate>Sun, 14 Jun 2009 19:18:00 +0000</pubDate>
</item>
<item>
	<title>Og Maciel: GeekDeck Issue 3 Published</title>
	<guid>http://www.ogmaciel.com/?p=712</guid>
	<link>http://www.ogmaciel.com/?p=712</link>
	<description>&lt;p&gt;&lt;a href=&quot;http://geekdeck.wordpress.com&quot;&gt;GeekDeck&lt;/a&gt; has just released &lt;strong&gt;Issue 3&lt;/strong&gt;, including;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://geekdeck.wordpress.com/2009/06/13/editors-letter-weve-come-a-long-way-in-a-short-time/&quot;&gt;Editor&amp;#8217;s Letter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://geekdeck.wordpress.com/2009/06/13/review-cherry-picks-of-the-month-foresight-linux/&quot;&gt;My look at Foresight Linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://geekdeck.wordpress.com/2009/06/13/interview-opencandy-ceo-darrius-thompson/&quot;&gt;Damien interviews OpenCandy CEO&lt;/a&gt;&lt;a href=&quot;http://geekdeck.wordpress.com/2009/06/13/interview-opencandy-ceo-darrius-thompson/&quot;&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://geekdeck.wordpress.com/2009/06/13/culture-where-have-all-the-geekers-gone/&quot;&gt;Why does society hate geeks?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://geekdeck.wordpress.com/2009/06/13/programming-undo-adds-usability-to-our-frictionless-desktop/&quot;&gt;Are modal dialogs a thing of the past?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://geekdeck.wordpress.com/2009/06/13/feature-creating-your-own-linux-live-cd-from-scratch/&quot;&gt;Our feature on creating a Live CD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://geekdeck.wordpress.com/2009/06/13/gaming-me-gamer-me-angry/&quot;&gt;Mark gets angry&amp;#8230;Very angry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://geekdeck.wordpress.com/2009/06/13/industry-if-it-werent-for-ignorance/&quot;&gt;Pete get&amp;#8217;s something off his chest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://geekdeck.wordpress.com/2009/06/13/culture-the-not-so-virtual-internet/&quot;&gt;Is the Internet really so virtual anymore?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://geekdeck.wordpress.com/2009/06/13/review-lowepro-compudaypack/&quot;&gt;The best bag in the business?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://geekdeck.wordpress.com/2009/06/13/sign-off-do-my-eyes-deceive-me-a-skeptic’s-view-of-the-e3-announcements/&quot;&gt;Pete gets a break as Mark talks E3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What are you waiting for? Go &lt;a href=&quot;http://geekdeck.wordpress.com&quot;&gt;read&lt;/a&gt; it now! &lt;img src=&quot;http://www.ogmaciel.com/wp-includes/images/smilies/icon_smile.gif&quot; alt=&quot;:)&quot; class=&quot;wp-smiley&quot; /&gt; &lt;/p&gt;</description>
	<pubDate>Sat, 13 Jun 2009 22:20:55 +0000</pubDate>
</item>
<item>
	<title>Akkana Peck: A Table of Closed versus Open Formats</title>
	<guid>http://shallowsky.com/blog/tech/open-formats-table.html</guid>
	<link>http://shallowsky.com/blog/tech/open-formats-table.html</link>
	<description>My last Toastmasters speech was on open formats: why you should use
open formats rather than closed/proprietary ones and the risks of
closed formats.
&lt;p&gt;
To make it clearer, I wanted to print out handouts people could take home
summarizing some of the most common closed formats, along with
open alternatives.
&lt;p&gt;
Surely there are lots of such tables on the web, I thought.
I'll just find one and customize it a little for this specific audience.
&lt;p&gt;
To my surprise, I couldn't find a single one. Even
&lt;a href=&quot;http://www.openformats.org/&quot;&gt;openformats.org&lt;/a&gt; didn't
have very much.
&lt;p&gt;
So I started one:
&lt;a href=&quot;http://shallowsky.com/openformats/&quot;&gt;Open vs. Closed Formats&lt;/a&gt;.
It's far from complete, so
I hope I'll continue to get contributions to flesh it out more.
&lt;p&gt;
And the talk? It went over very well, and people appreciated the
handout. There's a limit to how much information you can get across
in under ten minutes, but I think I got the point across.
The talk itself, such as it is, is here:
&lt;a href=&quot;http://shallowsky.com/openformats/openup-talk.html&quot;&gt;Open up!&lt;/a&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;</description>
	<pubDate>Fri, 12 Jun 2009 18:37:00 +0000</pubDate>
</item>
<item>
	<title>Akkana Peck: Bing thinks we're WHERE?</title>
	<guid>http://shallowsky.com/blog/tech/bing-portugal.html</guid>
	<link>http://shallowsky.com/blog/tech/bing-portugal.html</link>
	<description>Lots has been written about &lt;a href=&quot;http://bing.com&quot;&gt;Bing&lt;/a&gt;,
Microsoft's new search engine.
It's better than Google, it's worse than Google, it'll never catch
up to Google.  Farhad Manjoo of Slate had perhaps the best reason
to use Bing:
&lt;a href=&quot;http://www.slate.com/id/2219608/&quot;&gt;&quot;If you switch,
Google's going to do some awesome things to try to win you back.&quot;&lt;/a&gt;
&lt;p&gt;
&lt;a href=&quot;http://shallowsky.com/blog/images/screenshots/omnigal.jpg&quot;&gt;
&lt;img src=&quot;http://shallowsky.com/blog/images/screenshots/omnigalT.jpg&quot; align=&quot;right&quot; width=&quot;482&quot; height=&quot;178&quot; alt=&quot;[Bing in Omniweb thinks we're in Portugal]&quot; /&gt;&lt;/a&gt;
But what I want to know about Bing is this:
Why does it think we're in Portugal when Dave runs it under Omniweb on Mac?
&lt;p&gt;
In every other browser it gives the screen you've probably seen,
with side menus (and a horizontal scrollbar if your window isn't
wide enough, ugh) and some sort of pretty picture as a background.
In Omniweb, you get a cleaner layout with no sidebars or horizontal
scrollbars, a &lt;i&gt;different&lt;/i&gt; pretty picture -- often
prettier than the one you get on all the other browsers, though
both images change daily -- and a set of togglebuttons that don't
show up in any of the other browsers, letting you restrict results
to only English or only results from Portugal.
&lt;p&gt;
Why does it think we're in Portugal when Dave uses Omniweb?
&lt;p&gt;
Equally puzzling, why do only people in Portugal have the option
of restricting the results to English only?
&lt;br clear=&quot;all&quot; /&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;</description>
	<pubDate>Wed, 10 Jun 2009 17:37:00 +0000</pubDate>
</item>
<item>
	<title>Og Maciel: Three Dot Five</title>
	<guid>http://www.ogmaciel.com/?p=710</guid>
	<link>http://www.ogmaciel.com/?p=710</link>
	<description>&lt;p&gt;Celebrating my 35th birthday today! A year older, a year (hopefully) wiser, and every day glad to have the life I have! Can&amp;#8217;t wait to see what the next year will bring! &lt;img src=&quot;http://www.ogmaciel.com/wp-includes/images/smilies/icon_smile.gif&quot; alt=&quot;:)&quot; class=&quot;wp-smiley&quot; /&gt; &lt;/p&gt;</description>
	<pubDate>Mon, 08 Jun 2009 03:52:48 +0000</pubDate>
</item>
<item>
	<title>Akkana Peck: No X acceleration (DRI) in Jaunty: solved</title>
	<guid>http://shallowsky.com/blog/linux/install/jaunty-x-no-dri.html</guid>
	<link>http://shallowsky.com/blog/linux/install/jaunty-x-no-dri.html</link>
	<description>I upgraded to Ubuntu's current 9.04 release, &quot;Jaunty Jackalope&quot;, quite a
while ago, but I haven't been able to use it because its X server
crashes or hangs regularly. (Fortunately I only upgraded a copy
of my working 8.10 &quot;Intrepid&quot; install, on a separate partition.)
&lt;p&gt;
The really puzzling thing, though, wasn't the crashes, but the fact
that X acceleration didn't work at &lt;i&gt;all&lt;/i&gt;. Programs like tuxracer
(etracer) and Google earth would display at something like one frame
update every two seconds, and &lt;code&gt;glxinfo | grep renderer&lt;/code&gt; said
&lt;pre&gt;
OpenGL renderer string: Software Rasterizer
&lt;/pre&gt;
&lt;p&gt;
But that was all on my old desktop machine, with an
ATI Radeon 9000 card that I know no one cares about much.
I have a new machine now! An Intel dual Atom D945GCLF2D board
with 945 graphics. Finally, a graphics chip that's supported!
Now everything would work!
&lt;p&gt;
Well, not quite -- there were major teething pains, including
returning the first nonworking motherboard, but that's a
separate article. Eventually I got it running nicely with Intrepid.
DRI worked! Tuxracer worked! Even Google Earth worked! Unbelievable!
&lt;p&gt;
I copied the Jaunty install from my old machine to a partition on
the new machine. Booted into it and -- no DRI.
Just like on the Radeon.
&lt;p&gt;
Now, there's a huge pile of bugs in Ubuntu's bug system on problems
with video on Jaunty, all grouped by graphics card manufacturer even
though everybody seems to be
seeing pretty much the same problems on every chipset.
But hardly any of the bugs talk about not getting any DRI at all --
they're all about whether EXA acceleration works
better or worse than XAA and whether it's worth trying UXA.
I tried them all: EXA and UXA both gave me no DRI, while XAA
crashed/rebooted the machine every time. Clearly, there was something
about &lt;i&gt;my&lt;/i&gt; install that was disabling DRI, regardless of
graphics card. But I poked and prodded and couldn't figure out what it was.
&lt;p&gt;
The breakthrough came when, purely by accident, I ran that same
&lt;code&gt;glxinfo | grep renderer&lt;/code&gt; from a root shell. Guess what?
&lt;pre&gt;
OpenGL renderer string: Mesa DRI Intel(R) 945G GEM 20090326 2009Q1 RC2 x86/MMX/SSE2
&lt;/pre&gt;
&lt;p&gt;
As me (non-root), it still said &quot;Software Rasterizer.&quot;
It was a simple permissions problem! But wait ... doesn't X run as root?
&lt;p&gt;
Well, it does, but the DRI part doesn't, as it turns out.
(This is actually a good thing, sort of, in the long term:
eventually the hope is to get X not to need root permissions either.)
&lt;p&gt;
Armed with the keyword &quot;permissions&quot; I went back to the web, and the
&lt;a href=&quot;https://wiki.ubuntu.com/X/Troubleshooting/IntelPerformance&quot;&gt;Troubleshooting
Intel Performance&lt;/a&gt; page on the Ubuntu wiki, and found the
solution right away.
(I'd looked at that page before but never got past the part right at
the beginning that says it's for problems involving EXA vs. UXA
vs. XAA, which mine clearly wasn't).

&lt;h3&gt;The Solution&lt;/h3&gt;
&lt;p&gt;
In Jaunty, the user has to be in group &lt;b&gt;video&lt;/b&gt; to use DRI in X.
But if you've upgraded from an Ubuntu version prior to Jaunty, where
this wasn't required, you're probably not in that group. The upgrader
(I used do-release-upgrade) doesn't check for this or warn you
that you have desktop users who aren't in the video group,
so you're on your own to find out about the problem.
Fixing it is easy, though:
edit &lt;i&gt;/etc/group&lt;/i&gt; as root and add your user(s) to the group.
&lt;p&gt;
You might think this would have been an error worth reporting,
say, at X startup, or in glxinfo, or even in /var/log/Xorg.0.log.
You'd think wrong. Xorg.0.log blithely claims that DRI is enabled
and everything is fine, and there's no indication of an error
anywhere else.
&lt;p&gt;
I hope this article makes it easier for other people with this problem
to find the solution.&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;</description>
	<pubDate>Mon, 08 Jun 2009 03:23:00 +0000</pubDate>
</item>
<item>
	<title>Lostson: another week</title>
	<guid>http://lostsonsvault.org/geek/?p=125</guid>
	<link>http://lostsonsvault.org/geek/?p=125</link>
	<description>&lt;p&gt;Well another week of work over with, whew. Mandatory OT coming up shortly so less and less time to do things a guy wants to do. &lt;/p&gt;</description>
	<pubDate>Sun, 07 Jun 2009 16:16:54 +0000</pubDate>
</item>
<item>
	<title>Akkana Peck: Bullfrogs in stereo</title>
	<guid>http://shallowsky.com/blog/nature/bullfrogs-in-stereo.html</guid>
	<link>http://shallowsky.com/blog/nature/bullfrogs-in-stereo.html</link>
	<description>&lt;a href=&quot;http://shallowsky.com/images/frogs/showpix.php?pic=frogear.jpg&quot;&gt;
&lt;img src=&quot;http://shallowsky.com/blog/images/frogear.jpg&quot; align=&quot;right&quot; width=&quot;425&quot; height=&quot;259&quot; alt=&quot;bullfrog&quot; /&gt;&lt;/a&gt;
The Walden West pond is hopping -- literally!
This afternoon around 3pm the pond's resident bullfrogs,
who normally just float quietly in the scum on the surface,
would suddenly hop out of the water for no obvious
reason, then settle back down a few feet away.
One pair was apparently mating like that, the larger frog hopping
onto the back of the smaller frog, then immediately off again.
And the pond was full of sound, sometimes with two or more
frogs booming at once. Bullfrogs in stereo!
&lt;p&gt;
I didn't have the SLR along, but some of the frogs were close enough
(and calm enough not to submerge when we got near them) that I was
able to get a few decent shots.
&lt;p&gt;
But I really wanted to capture that sound. So I put the camera
in video mode and shot a series of videos hoping to catch some
of the music ... and did.
They sound like this:
&lt;a href=&quot;http://akkana.com/videos/bullfrogs.mp3&quot;&gt;bullfrog (mp3, 24kb)&lt;/a&gt;.

&lt;p&gt;
Despite the title of this entry, the recording doesn't have any
interesting stereo effects; the only microphone was the one built
in to my Canon A540. It did okay, though! You'll just have to
use your imagination to place two frogs as you listen, one 20 feet
to the left and the other 15 feet to the right.

&lt;h4&gt;How to extract the audio from a camera video&lt;/h4&gt;
(Non open source people can quit reading here.)

&lt;p&gt;
Extracting the audio was a little tricky. I found lots of pages ostensibly
telling me how to do it with mencoder, but none of them seemed to work.
This did:

&lt;pre&gt;
mplayer -vc null -af volume=15 -vo null -ao pcm -benchmark mvi_8992.avi
&lt;/pre&gt;

&lt;p&gt;
I added that &lt;code&gt;-af volume=15&lt;/code&gt; argument to make the sound
louder, since it was a bit quiet as it came from the camera.

&lt;p&gt;
That produced a file named audiodump.wav, which I turned into an
mp3 like this:

&lt;pre&gt;
lame audiodump.wav bullfrogs.mp3
&lt;/pre&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;</description>
	<pubDate>Thu, 04 Jun 2009 04:42:00 +0000</pubDate>
</item>
<item>
	<title>Akkana Peck: A GPX file manager</title>
	<guid>http://shallowsky.com/blog/mapping/gpx-file-manager.html</guid>
	<link>http://shallowsky.com/blog/mapping/gpx-file-manager.html</link>
	<description>Someone on the OSM newbies list asked how he could strip
waypoints out of a GPX track file. Seems he has track logs of an
interesting and mostly-unmapped place that he wants to add to
&lt;a href=&quot;http://openstreetmap.org&quot;&gt;openstreetmap&lt;/a&gt;, but there
are some waypoints that shouldn't be included, and he wanted a
good way of separating them out before uploading.
&lt;p&gt;
Most of the replies involved &quot;just edit the XML.&quot; Sure, GPX files
are pretty simple and readable XML -- but a user shouldn't ever have
to do that! Gpsman and gpsbabel were also mentioned, but they're not
terribly easy to use either.
&lt;p&gt;
That reminded me that I had another XML-parsing task I'd been wanting
to write in Python: a way to split track files from my Garmin GPS.
&lt;p&gt;
Sometimes, after a day of mapping, I end up with several track
segments in the same track log file. Maybe I mapped several different
trails; maybe I didn't get a chance to upload one day's mapping before
going out the next day. Invariably some of the segments are of zero
length (I don't know why the Garmin does that, but it always does).
Applications like merkaartor don't like this one bit, so I
usually end up editing the XML file and splitting it into
segments by hand. I'm comfortable with XML -- but it's still silly.
&lt;p&gt;
I already have some basic XML parsing as part
of PyTopo and Ellie, so I know the parsing very easy to do.
So, spurred on by the posting on OSM-newbies,
I wrote a little GPX parser/splitter called
&lt;a href=&quot;http://shallowsky.com/software/mapping&quot;&gt;gpxmgr&lt;/a&gt;.
&lt;i&gt;gpxmgr -l file.gpx&lt;/i&gt; can show you how many track logs are
in the file; &lt;i&gt;gpxmgr -w file.gpx&lt;/i&gt; can write new files for
each non-zero track log. Add -p if you want to be prompted for
each filename (otherwise it'll use the name of the track log,
which might be something like &quot;ACTIVE\ LOG\ #2&quot;).
&lt;p&gt;
How, you may wonder, does that help the original
poster's need to separate out waypoints from track files?
It doesn't. See, my GPS won't save tracklogs and
waypoints in the same file, even if you want them that way;
you have to use two separate gpsbabel commands to upload a track
file and a waypoint file. So I don't actually know what a
tracklog-plus-waypoint file looks like.
If anyone wants to use gpxmgr to manage waypoints as well as tracks,
send me a sample GPX file that combines them both.&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;</description>
	<pubDate>Tue, 02 Jun 2009 03:43:00 +0000</pubDate>
</item>
<item>
	<title>David Barr: Faking Gnome</title>
	<guid>http://david.chalkskeletons.com/blog/?p=78</guid>
	<link>http://david.chalkskeletons.com/blog/?p=78</link>
	<description>&lt;p&gt;I was trying to get the adobe air &lt;a href=&quot;http://www.bbc.co.uk/iplayer/install&quot;&gt;iplayer thingy&lt;/a&gt; working in openbox, it turns out it is crap anyway.&lt;/p&gt;
&lt;p&gt;But to find out that it is was a waste of time I had to figure out how to pretend I had a gnome session going on; so it would even bother to load in the first place.&lt;/p&gt;
&lt;p&gt;Normally you will get the:&lt;br /&gt;
&lt;code&gt;Unknown desktop manager, only Gnome and KDE are supported&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;It turns out gnome session doesn&amp;#8217;t really do much in this area and the checks performed are poor and depreciated.&lt;/p&gt;
&lt;p&gt;Anyway, you can just dump these in your openbox session or .xinitrc or somewhere?&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
export DESKTOP_SESSION=&quot;gnome&quot;&lt;br /&gt;
export GNOME_DESKTOP_SESSION_ID=&quot;openbox&quot;&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The first line might not even be needed, but it is nice anyway.&lt;/p&gt;
&lt;p&gt;Another side effect of this is that it will work for other apps (which may suck less than the iplayer app), notably &lt;a href=&quot;http://tweetdeck.com/beta/&quot;&gt;tweetdeck&lt;/a&gt; which the kids love, apparently.&lt;/p&gt;
&lt;p&gt;I guess you could make a new openbox session like this which would be very fake gnome-y.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
if test -n &quot;$1&quot;; then&lt;br /&gt;
echo &quot;Syntax: openbox-session&quot;&lt;br /&gt;
echo&lt;br /&gt;
echo &quot;See the openbox-session(1) manpage for help.&quot;&lt;br /&gt;
exit&lt;br /&gt;
fi&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;br /&gt;
export OOO_FORCE_DESKTOP=&quot;gnome&quot;&lt;br /&gt;
export WINDOW_MANAGER=&quot;/usr/bin/openbox&quot;&lt;br /&gt;
export DESKTOP_SESSION=&quot;gnome&quot;&lt;br /&gt;
export GNOME_DESKTOP_SESSION_ID=&quot;openbox&quot;&lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
if test -e $AUTOSTART; then&lt;br /&gt;
. $AUTOSTART&lt;br /&gt;
else&lt;br /&gt;
if test -e $GLOBALAUTOSTART; then&lt;br /&gt;
. $GLOBALAUTOSTART&lt;br /&gt;
fi&lt;br /&gt;
fi&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;br /&gt;
AUTOSTART=&quot;$HOME/.config/openbox/autostart.sh&quot;&lt;br /&gt;
GLOBALAUTOSTART=&quot;/etc/xdg/openbox/autostart.sh&quot;&lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
exec /usr/bin/openbox &quot;$@&quot;&lt;/code&gt;&lt;/p&gt;</description>
	<pubDate>Sun, 31 May 2009 09:47:22 +0000</pubDate>
</item>
<item>
	<title>Og Maciel: A Fistfull of News</title>
	<guid>http://www.ogmaciel.com/?p=704</guid>
	<link>http://www.ogmaciel.com/?p=704</link>
	<description>&lt;p&gt;Been quite busy at work these days, as well as playing the host to my parents during the holidays. I did keep up with what was happening around the world, thanks to my G1 (I love this gadget!), and wanted to share a few nice nuggets.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First of all, the birth of &lt;a href=&quot;http://blog.transifex.net/2009/05/introducing-lotte/&quot;&gt;Lotte&lt;/a&gt;, the online translation editor! This new feature will help the &lt;a href=&quot;http://www.transifex.org&quot;&gt;Transifex&lt;/a&gt; guys deliver a fatal 1,2 punch combination in the fight against bad translation tools and processes!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;http://farm3.static.flickr.com/2436/3571486264_c6765b89ae_o_d.png&quot;&gt;&lt;img class=&quot;alignnone&quot; title=&quot;Lotte&quot; src=&quot;http://farm3.static.flickr.com/2436/3571486264_c6765b89ae_o.png&quot; alt=&quot;&quot; width=&quot;872&quot; height=&quot;299&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;As if Dimitris and his crew didn&amp;#8217;t have enough on their plate (I tell you, they have macchiato running through their veins), a new fledgling &lt;a href=&quot;http://www.transifex.net&quot;&gt;web portal&lt;/a&gt; portal for translators is in the makings. Think of a place where translators can offers their skills to projects in need of translators and you can see where this could lead.&lt;/li&gt;
&lt;li&gt;Still speaking of translations, hanging out on #transifex on Freenode I picked up that the &lt;a href=&quot;http://www.selenic.com/mercurial/wiki/&quot;&gt;Mercurial&lt;/a&gt; guys really like Transifex and what it has to offer their current legion of translators! Sounds like some experimenting may take place soon between these 2 projects (I&amp;#8217;ll keep my fingers crossed!).&lt;/li&gt;
&lt;li&gt;On a different subject, I have started working on a &lt;strong&gt;Snowy Appliance&lt;/strong&gt; yesterday and will have something done and consumable by this weekend. Don&amp;#8217;t know what &lt;a href=&quot;http://live.gnome.org/Snowy&quot;&gt;snowy&lt;/a&gt; is? Then check &lt;strong&gt;Paul Cutler&lt;/strong&gt;&amp;#8217;s blog &lt;a href=&quot;http://feedproxy.google.com/~r/silwenae/~3/83IvWoG-rUM/&quot;&gt;post&lt;/a&gt; and the links within it. Want to lend me a hand? Ping me on IRC, email, comment here, &lt;a href=&quot;http://www.twitter.com/OgMaciel&quot;&gt;Twitter&lt;/a&gt;, etc, etc.&lt;/li&gt;
&lt;li&gt;I&amp;#8217;m running this year for the &lt;a href=&quot;http://foundation.gnome.org/elections/overview.html&quot;&gt;GNOME Board of Directors&lt;/a&gt;! Take a look at the &lt;a href=&quot;http://mail.gnome.org/archives/foundation-list/2009-May/msg00037.html&quot;&gt;list of candidates&lt;/a&gt; and if you&amp;#8217;re a &lt;strong&gt;GNOME Foundation&lt;/strong&gt; member, remember to vote! If you&amp;#8217;re not a member, what are you waiting for?&lt;/li&gt;
&lt;li&gt;My &lt;strong&gt;35th&lt;/strong&gt; birthday is fast approaching (June 8th actually) and I will be updating my &lt;a href=&quot;http://www.amazon.com/wishlist/32BX7VP2GEFI1&quot;&gt;wishlist&lt;/a&gt; juuuuust in case someone feels like surprising me, &lt;em&gt;hint hint&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
	<pubDate>Thu, 28 May 2009 17:11:44 +0000</pubDate>
</item>
<item>
	<title>David Barr: Getting on the bus</title>
	<guid>http://david.chalkskeletons.com/blog/?p=74</guid>
	<link>http://david.chalkskeletons.com/blog/?p=74</link>
	<description>&lt;p&gt;I have been working on a little aggregator for my &amp;#8216;&lt;a href=&quot;http://david.chalkskeletons.com&quot; title=&quot;David Barr&quot;&gt;homepage&lt;/a&gt;&amp;#8216; which is a glorified index page to many directories of files and crap, but over time I have become fond of it and decided it might need some love. The best idea I could come up with was to aggregate all the feeds of sites I use, such as twitter, my blag and flickr (for now) as a sort of centralised hub.&lt;/p&gt;
&lt;p&gt;I am going to have to re-assess all my hosting and whatnot at some point (for money reasons) and centralise everything in one place, I have a few domains but I will probably keep chalkskeletons, even though the comic/original idea is very dead, I have had it a while and i am fond of it.&lt;/p&gt;
&lt;p&gt;I am currently auditioning a centralised bookmark things, obviously delicious is an option as is google bookmarks, but i am not sure what is out there these days?&lt;/p&gt;</description>
	<pubDate>Tue, 26 May 2009 10:46:02 +0000</pubDate>
</item>

</channel>
</rss>
