<?xml version="1.0"?>
<!-- name="generator" content="blosxom/2.0" -->
<!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN" "http://my.netscape.com/publish/formats/rss-0.91.dtd">

<rss version="0.91">
  <channel>
    <title>rlucas.net   </title>
    <link>http://rlucas.net/blog/bugfix/index.rss</link>
    <description>Blog of Randall Lucas (rlucas)</description>
    <language>en</language>

  <item>
    <title>Fixing Net::Google error with 404 File does not exist</title>
    <link>http://rlucas.net/blog/bugfix/index.rss/2008/08/26#net_google_wsdl_file</link>
    <description>&lt;p&gt;

I was trying to install Net::Google 1.0 using CPANPLUS on my Mac OS X 10.5
machine, and kept getting a pesky error:
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;Service description 'file:' can't be loaded: 404 File `' does not exist

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
One thing I had to do to fix it was install an apparent prerequisite,
SOAP::WSDL.  It wasn't included by CPANPLUS.
&lt;/p&gt;


&lt;p&gt;
Another thing I had to do to make the tests run was to include the lib/
(not just the blib/) directory in @INC when running the tests:
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;perl -Iblib/lib -Ilib t/001-search.t

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
Even though that made the tests succeed, the installed module still wouldn't
work and gave the same darn error.
&lt;/p&gt;


&lt;p&gt;
It turns out that some deeply, deeply nested code in Net::Google searches
through @INC to find:
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;$DIR/Net/Google/Services/GoogleSearch.wsdl

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
This file doesn't get installed by &quot;make install&quot;, unfortunately.
&lt;/p&gt;


&lt;p&gt;
So, I had to do the following:
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;rlucas:/Library/Perl/5.8.8/Net/Google$ sudo mkdir Services
Password:
rlucas:/Library/Perl/5.8.8/Net/Google$ cd Services/
rlucas:/Library/Perl/5.8.8/Net/Google/Services$ sudo cp \
~/.cpanplus/5.8.8/build/Net-Google-1.0/lib/Net/Google/Services/GoogleSearch.wsdl \
.

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
Now my Net::Google using scripts seem to work right.
&lt;/p&gt;


&lt;p&gt;
$Id: net_google_wsdl_file.txt 1127 2008-08-27 02:11:49Z rlucas $

&lt;/p&gt;
</description>
  </item>
  <item>
    <title>Entering a Hard Line Break in a Text Cell in Excel 2004 for Mac OS X</title>
    <link>http://rlucas.net/blog/bugfix/index.rss/2007/11/12#excel_mac_os_x_line_break</link>
    <description>&lt;p&gt;

No cutesy commentary for once:
&lt;/p&gt;


&lt;p&gt;
The equivalent on Mac OS X of alt-enter for entering a hard line break within a cell in
Excel is command-control-enter (open apple-control-enter).
&lt;/p&gt;


&lt;p&gt;
$Id: excel_mac_os_x_line_break.txt 1025 2007-11-13 04:11:18Z rlucas $

&lt;/p&gt;
</description>
  </item>
  <item>
    <title>wxPerl on Mac OS X must be run with special binary</title>
    <link>http://rlucas.net/blog/bugfix/index.rss/2007/10/04#wxperl_mac_os_x_must_use_special_binary</link>
    <description>&lt;p&gt;

If you are having trouble with your &quot;hello world&quot; wxPerl script
on Mac OS X, check your shebang (&lt;tt&gt;#!&lt;/tt&gt;) line and make sure you're running
&lt;tt&gt;/usr/bin/wxPerl&lt;/tt&gt; (or &lt;tt&gt;which&lt;/tt&gt; ever &lt;tt&gt;wxPerl&lt;/tt&gt; you have) rather than
merely &lt;tt&gt;/usr/bin/perl&lt;/tt&gt; -- the normal perl will display the main window
but won't allow interaction between the window and the interface (e.g. you
can see hello world but can't click the button).
&lt;/p&gt;


&lt;p&gt;
&lt;a href=&quot;//www.nntp.perl.org/group/perl.wxperl.users/2007/06/msg3181.html&quot;&gt;This posting&lt;/a&gt;
seems to imply that Mac OS X 10.4 comes with a wxPerl installed; you can also
get it via &lt;tt&gt;cpan&lt;/tt&gt; / &lt;tt&gt;cpanp&lt;/tt&gt; or from the wxPerl website if you don't have it
on your Mac.
&lt;/p&gt;


&lt;p&gt;
$Id: wxperl_mac_os_x_must_use_special_binary.txt 997 2007-10-04 16:52:41Z rlucas $

&lt;/p&gt;
</description>
  </item>
  <item>
    <title>Rails form_tag Changes in Rails 1.2</title>
    <link>http://rlucas.net/blog/bugfix/index.rss/2007/08/06#rails_form_tag_changes_in_1-2</link>
    <description>&lt;p&gt;

I recently updated my dev machine (Mac OS X) to the latest Rails gems, and was
getting deprecation warnings for using &lt;tt&gt;form_tag&lt;/tt&gt; in its old, non-block,
pre-Rails 1.2 way.
&lt;/p&gt;


&lt;p&gt;
Then, in moving between my development and acceptance-testing boxes (you &lt;em&gt;do&lt;/em&gt;
have a mirror of your production environment running as an acceptance testing
server before you push things from your laptop to production, right?)
I started getting blank HTML pages out of the testing box.  Whoops.
&lt;/p&gt;


&lt;p&gt;
Well, one thing is that the two different versions of &lt;tt&gt;form_tag&lt;/tt&gt; act
differently with respect to output -- so with the old one, you needed to put:
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;&amp;lt;%= form_tag ... %&amp;gt;

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
While the new one takes:
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;&amp;lt;% form_tag ... do %&amp;gt;
  ...
&amp;lt;% end %&amp;gt;

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
(Note &lt;em&gt;lack&lt;/em&gt; of &lt;tt&gt;=&lt;/tt&gt; sign in the new, block version.)
&lt;/p&gt;


&lt;p&gt;
But that wasn't it.  My problem was that, even with the equal signs fixed, I
was getting no love from my testing box.  Things that should have been
enclosed in the form tag block were just not happening.
&lt;/p&gt;


&lt;p&gt;
My hunch was that the old version of Rails was barfing (this was sort of
true: the new block form of &lt;tt&gt;form_tag&lt;/tt&gt; is not backwards compatible).  I
updated Rails with a one-two punch of &lt;tt&gt;apt-get update; apt-get upgrade&lt;/tt&gt;
mixed with a &lt;tt&gt;gem install rails&lt;/tt&gt;.  No luck.  Aha!  Have to kill and restart
the server process: still, I got no form tag love.
&lt;/p&gt;


&lt;p&gt;
I checked the Rails version with &lt;tt&gt;rails -v&lt;/tt&gt; and got 1.2.3, the latest
version.  &lt;tt&gt;gem list&lt;/tt&gt; showed that 1.2.3 was coexisting with some older
versions.  Aha!  And a real aha this time -- for this was, it turns out, the
problem.
&lt;/p&gt;


&lt;p&gt;
Thanks to the folks who author the
&lt;a href=&quot;//technoweenie.stikipad.com/plugins/show/Acts+as+Authenticated&quot;&gt;acts_as_authenticated&lt;/a&gt;
wiki.  It was there that I found a reminder that the &lt;tt&gt;RAILS_GEM_VERSION&lt;/tt&gt;
variable, in &lt;tt&gt;config/environment.rb&lt;/tt&gt;, can be set to peg which, among several
possible installed versions of Rails, the app will use.
&lt;/p&gt;


&lt;p&gt;
It appears that if you comment out &lt;tt&gt;RAILS_GEM_VERSION&lt;/tt&gt;, you get the latest
installed version -- which in my case fixed it to use 1.2.3, thereby giving
me my &lt;tt&gt;form_tag&lt;/tt&gt;s back.
&lt;/p&gt;


&lt;p&gt;
$Id: rails_form_tag_changes_in_1-2.txt 964 2007-08-08 00:06:56Z rlucas $

&lt;/p&gt;
</description>
  </item>
  <item>
    <title>God Help You If You Get Derailed: &quot;Model is Deprecated&quot;</title>
    <link>http://rlucas.net/blog/bugfix/index.rss/2007/08/03#god_help_you_if_you_go_off_the_rails-model_is_deprecated</link>
    <description>&lt;p&gt;

The comprehensible but often superfluous &lt;tt&gt;model&lt;/tt&gt; method in Rails is used in
an ActionController to tell it about an ActiveRecord model that it ought to
have loaded in order to have the AR classes available to it.  It's kind of
got the feeling of a &lt;tt&gt;require&lt;/tt&gt; or a &lt;tt&gt;use&lt;/tt&gt; in Perl.  It's fairly
straightforward to reason by analogy about what it does.  
&lt;/p&gt;


&lt;p&gt;
(The only confusing thing, I think, is that it works by imputing a filename
from a symbol representing the class to do its &quot;magic&quot; so if you define
multiple AR classes in a single file, you'd want to make sure that the symbol
that matches the filename containing the multiple classes is what you pass to
the &lt;tt&gt;model&lt;/tt&gt; method.)
&lt;/p&gt;


&lt;p&gt;
But in a nutshell, you stick &lt;tt&gt;model :my_object_class&lt;/tt&gt; in, say, the base
ApplicationController class and you're good to go to use MyObjectClass and
any subclasses defined in the same file.
&lt;/p&gt;


&lt;p&gt;
Well, it &lt;em&gt;was&lt;/em&gt; the way you do it.  Around Rails 1.2, it started barfing up
preemptive deprecation warnings: 
&lt;tt&gt;model is deprecated and will be removed from Rails 2.0&lt;/tt&gt;.  
&lt;/p&gt;


&lt;p&gt;
So, you follow the URL they give you for more info.
Unhappily, nowadays (August 2007), the page they point you to,
&lt;a href=&quot;//rubyonrails.org/deprecation&quot;&gt;//rubyonrails.org/deprecation&lt;/a&gt;, doesn't say anything about &lt;tt&gt;model&lt;/tt&gt;.
WTF, guys?
&lt;/p&gt;


&lt;p&gt;
Googling around tells you that you should use &lt;tt&gt;require_dependency&lt;/tt&gt; instead.
Oh, good.  Way longer to type and harder to remember, but it's OK, 
because &lt;tt&gt;require&lt;/tt&gt; is part of
the language itself and is familiar to those who understand it.  Er, wait:
it's &lt;tt&gt;require_dependency&lt;/tt&gt;, not &lt;tt&gt;require&lt;/tt&gt;:
&lt;a href=&quot;//wiki.rubyonrails.com/rails/pages/RequireDependency&quot;&gt;it's a Rails feature, not a Ruby core language feature.&lt;/a&gt;
&lt;/p&gt;


&lt;p&gt;
Fine, you say, I'll do it if I must.  Just do a replace on those lines, and
you're good, right?  Oh, wait again, now my app is bombing with an error 500,
and the log says &lt;tt&gt;undefined method `ends_with?' for :my_object_class:Symbol&lt;/tt&gt;.
I won't keep you in suspense: you can't give a symbol &lt;tt&gt;:my_object_class&lt;/tt&gt; to
&lt;tt&gt;require_dependency&lt;/tt&gt;, you have to give it a String (&lt;tt&gt;&quot;my_object_class&quot;&lt;/tt&gt;).
&lt;/p&gt;


&lt;p&gt;
All of this highlights a pretty big issue with Rails.  It's really an
infantile, nascent culture.  To keep up with it, you really need to be in
constant conversation with the community (like &lt;em&gt;constant&lt;/em&gt;: I mean, you need
to be sitting in the session at RailsConf with Colloquy open on your MacBook,
chatting about stuff on an hour-by-hour basis).  This isn't &lt;em&gt;bad&lt;/em&gt;, but you
better understand it.  And you better be refactoring your app constantly in
order to keep up with best practices and to be able to use new plugins, 
etc. -- which also isn't &lt;em&gt;bad&lt;/em&gt;, but it's expensive and a hassle.
&lt;/p&gt;


&lt;p&gt;
And to anybody who thinks a Perl app is tough to maintain: yeah, right.  Try
Rails code from a year or so ago if all you know is Ruby and you haven't been
heavily engaged in Rails culture during that time.
&lt;/p&gt;


&lt;p&gt;
&quot;Convention over Configuration&quot; is &lt;em&gt;fine and dandy&lt;/em&gt; as long as you're steeped
in the culture that maintains the shared conventions.
&lt;/p&gt;


&lt;p&gt;
$Id: god_help_you_if_you_go_off_the_rails-model_is_deprecated.txt 962 2007-08-03 18:10:18Z rlucas $

&lt;/p&gt;
</description>
  </item>
  <item>
    <title>Printing From Mac OS X Without Going Bankrupt</title>
    <link>http://rlucas.net/blog/bugfix/index.rss/2007/05/10#print_on_your_mac_without_going_bankrupt</link>
    <description>&lt;p&gt;

One thing about buying a new(ish) MacBook Pro loaded with Tiger: they really
aren't cutting a lot of corners.  This includes in the area of resource
usage (see e.g. memory usage, as you buy another gig of RAM).  This, of
course, is done in the name of an &quot;Insanely Great&quot; user experience, and
mostly, it works.
&lt;/p&gt;


&lt;p&gt;
One difference from Windows is that the Mac, when printing, defaults to the
best mode possible on our big office multifunction color laser printer; in
this case, it's fully glossy color.  Those of you who've ever had to buy
toner for such a printer are now wincing: it is damn expensive.
&lt;/p&gt;


&lt;p&gt;
In Windows, it seemed, I had to opt &lt;em&gt;in&lt;/em&gt; to print in color.  I'd like to run
the same sort of system on my Mac.
&lt;/p&gt;


&lt;p&gt;
Well, as it happens, this is one sad case where the Mac requires you to know
&lt;em&gt;more&lt;/em&gt; about how the OS works than does Windows.  Specifically, we want to
use a feature of &quot;Quartz&quot; (the graphical engine) to convert colors to
greyscale before sending them to the printer.  Do it like this:
&lt;/p&gt;


&lt;ol&gt;
&lt;li&gt;Open a print dialog with command-P.
&lt;li&gt;It should show a box with pulldowns at top for &quot;Printer&quot; and &quot;Presets&quot;
&lt;ol&gt;
&lt;li&gt;Make sure you're working with the Printer in question.
&lt;li&gt;You're probably using Standard Presets -- that's fine for now.
&lt;/ol&gt;
&lt;li&gt;In the middle is a third pulldown that says &quot;Copies &amp;amp; Pages.&quot;
&lt;ol&gt;
&lt;li&gt;Choose it and change to &quot;ColorSync.&quot;
&lt;li&gt;Set a &quot;Quartz Filter&quot; to greyscale or black &amp;amp; white (maybe test each to see what works best).
&lt;/ol&gt;
&lt;li&gt;When satisfied, go up to &quot;Presets&quot; and save your settings under a name like &quot;dreary grey.&quot;  
&lt;li&gt;Keep this selected and it should now show up as your default settings for this printer.
&lt;/ol&gt;
&lt;p&gt;

$Id: print_on_your_mac_without_going_bankrupt.txt 865 2007-05-10 16:49:40Z rlucas $

&lt;/p&gt;
</description>
  </item>
  <item>
    <title>Making Subversion Set Reasonable Default Properties Like Keyword Substitution</title>
    <link>http://rlucas.net/blog/bugfix/index.rss/2007/05/09#svn_set_default_properties_like_keywords</link>
    <description>&lt;p&gt;

(Programmers: skip down to the &lt;b&gt;Meat&lt;/b&gt; section below.)
&lt;/p&gt;


&lt;p&gt;
If you are so bored as to actually have read all the articles on this blog,
you may have noticed that the &lt;em&gt;&quot;Id: lucas blah blah blah&quot;&lt;/em&gt; string that shows
up at the bottom of the articles.  This is an interpolated keyword, put in by
the revision control system, that shows in the text of the document when it
was last committed to revision control.
&lt;/p&gt;


&lt;p&gt;
Subversion (svn) is a revision control system -- probably the leading such
system for new deployments (I am not counting Microsoft-land, where old,
proprietary systems still abound).  It's most familiar as the replacement for
the venerable CVS, which used to do replacement more or less automatically.
But a stock Subversion install won't do keyword replacement unless you do a
&quot;property setting,&quot; or propset, on a file-by-file basis (this is to prevent
clobbering a file that happens to have the magical string in it).
&lt;/p&gt;


&lt;p&gt;
Therefore, you have to remember to do something like this to your new files:
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;svn propset svn:keywords Id myfile.txt

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
This tells svn to set the &quot;svn:keywords&quot; property to &quot;Id,&quot; meaning it will
replace instances of $Word: $ with the ID string (when &quot;Word&quot; is &quot;Id&quot;).
&lt;/p&gt;


&lt;p&gt;
However, this is a pain, and although you could conceivably script this
action as a hook upon new additions to svn, there's an easier way.
&lt;/p&gt;


&lt;p&gt;
&lt;b&gt;Meat&lt;/b&gt;
&lt;/p&gt;


&lt;p&gt;
Find your local ~/.subversion/config file and edit it.  Set the following:
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;[miscellany]
enable-auto-props=yes

[auto-props]
*.txt=svn:keywords=Id

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
(The default config file has a bunch of examples commented out for you to
base your settings on, but the above is the minimal set to get textfiles set
with keyword substitution for the &quot;Id&quot; keyword.)
&lt;/p&gt;


&lt;p&gt;
$Id: svn_set_default_properties_like_keywords.txt 858 2007-05-09 17:21:17Z rlucas $

&lt;/p&gt;
</description>
  </item>
  <item>
    <title>Ruby's ActiveRecord Makes Dropping to Raw SQL a Royal Pain (Probably on Purpose)</title>
    <link>http://rlucas.net/blog/bugfix/index.rss/2007/05/09#ruby_active_record_makes_raw_sql_a_royal_pain</link>
    <description>&lt;p&gt;

The opinionated programmers behind Rails have generally done a good job.
(There are couple of FUBARs in their bag of tricks, such as the boneheaded
choice to use pluralized table names (in some places) and use automagical
pluralization code to try and mediate between the singular and plural.)
&lt;/p&gt;


&lt;p&gt;
There's another item I'd like to bring up, however, and that's the fact that
ActiveRecord intentionally cripples your ability to do raw SQL queries.  This
is, I'm sure, done to discourage raw SQL hacking in favor of using the
ActiveRecord objects (which, for small numbers of objects, is admittedly a
superior way to do many things, because of concerns for clarity,
maintainability, etc.).
&lt;/p&gt;


&lt;p&gt;
However, sometimes you need SQL, dammit.  Especially when you're doing a
correlation between, say, different tags that describe business plans, and the
people that link those business plans together, plus the number of times that
such tags appear, there's just no sense in pulling thousands of records into
memory, instantiating Ruby objects, and improperly reimplementing basic CS
sorting algorithms to link them up.  You've got all that sitting right there
in your RDBMS.
&lt;/p&gt;


&lt;p&gt;
ActiveRecord lets you do something like this:
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;BusinessPlan.find_by_sql( 
  [ 
    'SELECT s2.id FROM (COMPLICATED_SUBSELECT) AS s2', 
    var1, var2, var3 
  ]
)

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
Which will run the complicated SQL and replace the bind vars (question marks)
in the raw SQL with var1, var2, var3, etc., and give you a bunch of
&lt;tt&gt;BusinessPlan&lt;/tt&gt; objects that it's instantiated off those IDs.  Easy enough.
&lt;/p&gt;


&lt;p&gt;
But what if you need not merely to get the objects, but to get some other
important info (say, &lt;tt&gt;COUNT(something)&lt;/tt&gt;) out?  You're shit out of luck with
ActiveRecord.  The &lt;tt&gt;.connection.select_all&lt;/tt&gt; method returns you an array of
record hashes, but it requires fully-baked SQL (no bind vars).
&lt;/p&gt;


&lt;ul&gt;
&lt;li&gt;You could manually construct the SQL and manually quote each bind variable into its place, but &lt;em&gt;avoiding&lt;/em&gt; that kind of retarded scut work is exactly why you're using Rails in the first place.  
&lt;li&gt;You could try and get the DBI handle that underlies ActiveRecord (does it?), but it's very unclear as to how or if you can do that.  If you call &lt;tt&gt;.connection.raw_connection&lt;/tt&gt; you get a PGConn object (for PostgreSQL), not a DBI handle.
&lt;li&gt;You could open up your own new DBI handle, which involves recapitulating the Rails initialization code for ripping the config values and rewriting connection-pooling code, which is bad for all sorts of reasons, not least of which is that you're &lt;em&gt;already f'ing connected to the DB!&lt;/em&gt;
&lt;/ul&gt;
&lt;p&gt;

WTF?  If you read the code for the &lt;tt&gt;find_by_sql&lt;/tt&gt; method, you'll see:
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;def find_by_sql(sql)
  connection.select_all(
    sanitize_sql(sql), 
    &quot;#{name} Load&quot;
  ).collect! { |record| instantiate(record) }
end

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
Given this, you might think: &quot;aha, I'll just use a similar method and pass to
&lt;tt&gt;sanitize_sql&lt;/tt&gt; an array with my SQL and bind vars, then pass that on to
&lt;tt&gt;select_all&lt;/tt&gt;.  No can do.  &lt;tt&gt;sanitize_sql&lt;/tt&gt; is a protected method.
&lt;/p&gt;


&lt;p&gt;
So, here's my encapsulation-breaking, OO-unfriendly, scofflaw workaround to
let you have access to what you should already get: a decent bit of code for
binding SQL parameters:
&lt;/p&gt;


&lt;p&gt;
(In &lt;tt&gt;helpers/application_helper.rb&lt;/tt&gt;)
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;arb = ActiveRecord::Base
def arb.sanitize_fucking_sql(*args)
  sanitize_sql(*args)
end

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
Now, you can happily go about your business and, when necessary, call
&lt;tt&gt;ActiveRecord.sanitize_fucking_sql(...)&lt;/tt&gt; to get 'er done.  No special-purpose
DB connections, no wrangling thousands of objects in memory.
&lt;/p&gt;


&lt;p&gt;
Caveats:
&lt;/p&gt;


&lt;ol&gt;
&lt;li&gt;I suck at Ruby, I know.  There's a more elegant way to add a public method to a class, but that works and I understand it.
&lt;li&gt;Eventually, this will break.  But it will probably be a long time and the, er, &lt;em&gt;unique&lt;/em&gt; method signature I suggest should be easily globally replaced.
&lt;/ol&gt;
&lt;p&gt;

$Id: ruby_active_record_makes_raw_sql_a_royal_pain.txt 863 2007-05-09 18:07:04Z rlucas $

&lt;/p&gt;
</description>
  </item>
  <item>
    <title>Hurrah for Kwiki</title>
    <link>http://rlucas.net/blog/bugfix/index.rss/2007/05/08#hurrah_for_kwiki</link>
    <description>&lt;p&gt;

... and for
&lt;a href=&quot;//oubliette.alpha-geek.com/2003/10/28/hacking_at_kwiki_table_formatting&quot;&gt;Jeremy Smith&lt;/a&gt;.
Thanks to Jeremy's hack on top of Ingy's quickie wiki, we can now get proper
behavior inside of table cells.
&lt;/p&gt;


&lt;p&gt;
In a nutshell, Kwiki didn't handle things like &lt;em&gt;italics&lt;/em&gt; inside of a table.
This should fix it.  Previous posts that used the stock Kwiki should be fixed
now.
&lt;/p&gt;


&lt;p&gt;
Now, to remedy blockquotes ...
&lt;/p&gt;


&lt;p&gt;
$Id: hurrah_for_kwiki.txt 857 2007-05-09 17:10:14Z rlucas $

&lt;/p&gt;
</description>
  </item>
  <item>
    <title>Installing RMagick on OS X with Fink</title>
    <link>http://rlucas.net/blog/bugfix/index.rss/2007/03/29#rmagick_on_osx_with_fink</link>
    <description>&lt;p&gt;

&lt;b&gt;Hold on: I'm not sure that the below works right.  Don't use it yet.&lt;/b&gt;
&lt;/p&gt;


&lt;p&gt;
There are lots of instructions out there for installing RMagick, which 
is a graphics manipulation library used by many Ruby-istas for things like thumbnailing,
resizing, etc.  I wanted to use it for an internal database I'm building in Rails.
&lt;/p&gt;


&lt;p&gt;
Some of the sites offering instructions:
&lt;/p&gt;


&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;//rmagick.rubyforge.org/install-osx.html&quot;&gt;The RMagick site itself&lt;/a&gt;.  This one is tilted toward using Darwin Ports (the BSD-ish way to do third party package management on your mac; I prefer the Debian-ish &quot;Fink&quot;).
&lt;li&gt;&lt;a href=&quot;//hivelogic.com/narrative/articles/rmagick_os_x?status=301&quot;&gt;Hivelogic&lt;/a&gt;.  This one involves manual downloads of tarballs and &lt;tt&gt;configure; make; make install&lt;/tt&gt; type loving.  I don't like this way of going about it because you lose the package management features.
&lt;/ul&gt;
&lt;p&gt;

But nobody seemed to have a Fink-friendly way to do this.
&lt;/p&gt;


&lt;p&gt;
If you naively try to install with &lt;tt&gt;gem install rmagick&lt;/tt&gt;, you'll get
something like:
&lt;/p&gt;


&lt;p&gt;
&lt;tt&gt;configure: error: Can't install RMagick. Can't find libMagick or one of the dependent libraries.  Check the config.log file for more detailed information.&lt;/tt&gt;
&lt;/p&gt;


&lt;p&gt;
My solution:
&lt;/p&gt;


&lt;p&gt;
1. Install the needed dependencies from binaries using Fink.
2. Use &lt;tt&gt;gem install&lt;/tt&gt; to install RMagick (the Ruby bit) itself.
&lt;/p&gt;


&lt;p&gt;
The dependencies include (as best I can tell):
&lt;/p&gt;


&lt;p&gt;
&lt;tt&gt;freetype freetype-shlibs imagemagick imagemagick-dev imagemagick-shlibs ghostscript ghostscript-fonts gv libpng-shlibs libjpeg libjpeg-bin libjpeg-shlibs lcms lcms-bin lcms-shlibs libtiff libtiff-bin libtiff-shlibs &lt;/tt&gt;
&lt;/p&gt;


&lt;p&gt;
Therefore, you should probably be able to install simply by doing:
&lt;/p&gt;


&lt;p&gt;
&lt;tt&gt;sudo apt-get install freetype freetype-shlibs imagemagick imagemagick-dev imagemagick-shlibs ghostscript ghostscript-fonts gv libpng-shlibs libjpeg libjpeg-bin libjpeg-shlibs lcms lcms-bin lcms-shlibs libtiff libtiff-bin libtiff-shlibs &lt;/tt&gt;
&lt;/p&gt;


&lt;p&gt;
&lt;tt&gt;sudo gem install rmagick&lt;/tt&gt;
&lt;/p&gt;


&lt;p&gt;
(I realize that this is probably overkill and that you don't actually need all those packages above.  If you figure out the minimal subset, why don't
you post a similar blog entry of your own?)
&lt;/p&gt;


&lt;p&gt;
Good luck!
&lt;/p&gt;


&lt;p&gt;
$Id: rmagick_on_osx_with_fink.txt 863 2007-05-09 18:07:04Z rlucas $

&lt;/p&gt;
</description>
  </item>
  <item>
    <title>HOWTO: Subversion Export for Legal Discovery</title>
    <link>http://rlucas.net/blog/bugfix/index.rss/2007/02/07#howto_svn_export_for_legal_discovery</link>
    <description>&lt;p&gt;

The more interesting things you do in life, the more likely it is that some
jackass will sue you.  If this happens, you will probably be faced with giving
one or more sets of attorneys access to your electronic documents.
&lt;/p&gt;


&lt;p&gt;
If, like all right-thinking citizens, you store your documents in a Subversion
repository organized hierarchically by subject, you may find yourself needing
to provide access to not only the current version, but all previous versions,
of all documents on a particular subject.
&lt;/p&gt;


&lt;p&gt;
With CVS, you could just have made a copy of the relevant part of the
repository root, since the repository itself stores things in a directory
structure.
&lt;/p&gt;


&lt;p&gt;
But SVN has some nice features like renaming, symlinks, and binary diff, which
necessitates a more sophisticated repository structure.  You'll notice that if
you go to your repository root, there's no analog to what you see in CVS.
&lt;/p&gt;


&lt;p&gt;
If you don't want to give the lawyers your &lt;em&gt;whole&lt;/em&gt; SVN repository (and there's
no reason you should), then you need a way to drop out all of the revisions,
ever, for a particular directory and all subdirectories.
&lt;/p&gt;


&lt;p&gt;
Here's what worked for me (using Subversion on Cygwin on Win XP).
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;$ mkdir /cygdrive/c/temp/discovery
$ mkdir /cygdrive/c/temp/discovery/working_copy
$ mkdir /cygdrive/c/temp/discovery/repository
$ cd doc/all_stuff/
$ cp -par doc/all_stuff/target /cygdrive/c/temp/discovery/working_copy
$ svn up -rHEAD target_subject
$ svn log target_subject &amp;gt; /cygdrive/c/temp/discovery/repository/log

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
Now, look through the log for all of the revisions mentioned.  For me they
were mercifully few; you may need to do a touch more scripting if you have
e.g. hundreds of revisions (think &quot;| grep '^r'&quot;).
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;$  for i in 1 49 103 106 107 112 HEAD
&amp;gt; do svn up -r$i target_subject
&amp;gt; cp -par target_subject/ /cygdrive/c/temp/discovery/repository/r$i
&amp;gt; done
$ 

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
This gives a nice, clean structure with your current working copy (including
uncommitted changes) in one directory, and all revisions up to that one in
another directory, along with the svn log of comments on all commits.  This
should satisfy all but the most KY-equipped of legal eagles.
&lt;/p&gt;


&lt;p&gt;
$Id: howto_svn_export_for_legal_discovery.txt 800 2007-02-07 22:58:07Z rlucas $

&lt;/p&gt;
</description>
  </item>
  <item>
    <title>Curses::UI Escape key bindings are slow; here's why.</title>
    <link>http://rlucas.net/blog/bugfix/index.rss/2006/09/14#curses_ui_escape_is_slow</link>
    <description>&lt;p&gt;

I am throwing together a quick Curses (console / terminal) based UI for a
database here, prior to putting (or hiring someone to put!) a Web front-end
on it.  In keeping with my experience with &lt;a href=&quot;//elinks.or.cz/&quot;&gt;elinks&lt;/a&gt;, I
wanted the menubar activation key to be Escape.  However, it was running
slower than molasses in February -- it seemed to take a FULL SECOND before
the Esc key would register and focus / unfocus the menubar.
&lt;/p&gt;


&lt;p&gt;
Well, poking around a bit gave me the answer.  From man ncurses(3):
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;ESCDELAY
  Specifies the total time, in milliseconds, for which ncurses will
  await a character sequence, e.g., a function key.  The default
  value, 1000 milliseconds, is enough for most uses.  However, it is
  made a variable to accommodate unusual applications.&quot;

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
Duh.  It was taking &lt;em&gt;exactly&lt;/em&gt; a full second.  
&lt;/p&gt;


&lt;p&gt;
$Id: curses_ui_escape_is_slow.txt 802 2007-02-10 21:18:35Z rlucas $

&lt;/p&gt;
</description>
  </item>
  <item>
    <title>A Rational Scheme for Medical Laboratory Results</title>
    <link>http://rlucas.net/blog/bugfix/index.rss/2006/08/20#rational_medical_lab_result_scheme</link>
    <description>&lt;p&gt;

Medical laboratory results these days are a hodgepodge of numbers on various
scales and with various units.  For example, the
&lt;a href=&quot;//www.merck.com/mrkshared/mmanual/tables/296tb2d.jsp&quot;&gt;Merck Manual&lt;/a&gt;
lists various laboratory test normal ranges and their units:
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;Hematocrit: Male 41-50%, Female 35-46%
Hemoglobin: Male 13.8-17.2 g/dL, Female 12.0-15.6 g/dL
...
Sodium: 135-146 mmol/L

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
These &quot;normal ranges&quot; can be sort of misleading.  If your value is
numerically half of the lower-end of the hematocrit range, for example (say,
20%), you would be sick but still alive.  However, if you have only half the
normal range of sodium concentration (say, 70 mmol/L), you'd be dead.
&lt;/p&gt;


&lt;p&gt;
This is crappy.  It imposes a high cognitive load on doctors by requiring
them to know a variety of &quot;normal&quot; ranges, it makes lab results opaque to
patients and the uninitiated, and it has a &quot;hidden memorization cost&quot; of
knowing the implications of going outside the normal range (such as the
difference between having half the normal measurement for hematocrit vs.
sodium, above).
&lt;/p&gt;


&lt;p&gt;
I propose a replacement scheme for all scalar laboratory values (at least
those in the main test batteries, like the chem-N and CBCs).  In my scheme,
all &quot;unit&quot; lab results are replaced (realistically, augmented) by &quot;rational&quot;
values.  Rational values are normalized at 100 for the center of the range.
The &quot;normal range&quot; is represented by the range 90-110.  The values associated
with roughly 50% mortality are set at 50-150.  The ranges 80-120, 70-130, and
60-140 will be pegged at some statistics-based measurement, either based upon
standard deviation or upon increased chances of negative outcomes, whichever
an appropriate standards body decides best (there are some labs for which it
might not make sense to have it be standard deviation-based, others for which
it would).  
&lt;/p&gt;


&lt;p&gt;
The correspondence of &quot;unit&quot; to &quot;rational&quot; measurements is not necessarily
linear; the formulae to determine this will be decided per-test, reviewed
annually by the standards body, and published as an appendix to standard
references and on the Web.
&lt;/p&gt;


&lt;p&gt;
The &quot;core rational&quot; lab values are those which are unadjusted for average
adults.  &quot;Adjusted rational&quot; lab values are adjusted for sex and body mass.
&quot;Peds adjusted rational&quot; values are adjusted as above but with age ranges.
&lt;/p&gt;


&lt;p&gt;
All lab reports will show these values on the summary page; &quot;unit&quot;
measurements will be provided as well (they will doubtless remain indispensable
for certain purposes).  Color-coding would be straightforward: green for +/-
10, yellow for +&lt;em&gt;- 20, orange for +&lt;/em&gt;- 30, and red for +/- 40.
&lt;/p&gt;


&lt;p&gt;
This will become an ever more crucial part of diagnosis as we move toward
greater automation (e.g. field lab-testing machines that paramedics could
carry) and de-skilling of the medical profession (nurse practitioners,
paramedics, self-administered care and monitoring, etc.).  It also becomes a
key part of the understanding required for personal medical choice as we move
the economics of health care toward a (partial) patient-pays model.
&lt;/p&gt;


&lt;p&gt;
If someone wants to give me a grant for a year of my time with a couple of
assistants, I'll go ahead and set this up.  Drop me an email -
&lt;a href=&quot;mailto:rlucas@tercent.com&quot;&gt;rlucas@tercent.com&lt;/a&gt;.
&lt;/p&gt;


&lt;p&gt;
$Id: rational_medical_lab_result_scheme.txt 706 2006-08-20 22:07:54Z rlucas $

&lt;/p&gt;
</description>
  </item>
  <item>
    <title>Linux Software RAID and GRUB - Recovering From a Failure</title>
    <link>http://rlucas.net/blog/bugfix/index.rss/2006/08/18#linux_software_raid_and_grub</link>
    <description>&lt;p&gt;

A couple of weeks ago, I had the bright idea to move an internal server here
at &lt;a href=&quot;//www.voyagercapital.com/&quot;&gt;Voyager&lt;/a&gt; from my office into a data room.
I issued the customary &lt;tt&gt;sudo shutdown now&lt;/tt&gt; and proceeded to move the box.
&lt;/p&gt;


&lt;p&gt;
I was dismayed not to see it boot right back up afterwards.  Ouch!  I had
specifically configured it with software RAID because the hard drives in the
old spare box were a bit dodgy.  Turns out that was a good idea, since one of
the drives had failed (apparently the one that had the GRUB bootloader
appropriately loaded on it).
&lt;/p&gt;


&lt;p&gt;
I was faced with two 20 Gig HDDs, only one of which worked exactly right, and
a computer which failed to boot off the remaining HDD.  A quick trip to
&lt;a href=&quot;//www.ubid.com/&quot;&gt;uBid&lt;/a&gt; and $70 later, I had two 60 Gig drives ready to
use (20 Gigs are darn near impossible to find).  I knew enough about
partitions and whatnot to get this much done:
&lt;/p&gt;


&lt;p&gt;
- Got a bootable rescue CD with a good set of utils (PLD Linux) downloaded 
and burned (it's good to have one of these handy, rather than trying to burn them
as-needed -- see below under &quot;Tricky stuff&quot; for my unfortunate experiences
with that).
&lt;/p&gt;


&lt;p&gt;
- Trial-and-errored the two old HDDs to find which one was failing.  Removed
the bad one and replaced with New HDD #1.
&lt;/p&gt;


&lt;p&gt;
- Used &lt;tt&gt;cfdisk&lt;/tt&gt;, the curses-based fdisk, to read the exact size and type of
the good RAID partition from Old HDD.  Used that information to create an
identical physical partition at the beginning of New HDD #1, including the
same (Linux Software RAID) partition type.
&lt;/p&gt;


&lt;p&gt;
- Used &lt;tt&gt;dd&lt;/tt&gt;, the bit-for-bit copier, to copy the verbatim entire partition
from the Old HDD's main partition, &lt;tt&gt;/dev/hda1&lt;/tt&gt;, to the New HDD #1's
identically situated partition, &lt;tt&gt;/dev/hdc1&lt;/tt&gt;, 
&lt;em&gt;both of which were unmounted at the time&lt;/em&gt;.
&lt;/p&gt;


&lt;p&gt;
- Swapped out the Old HDD with New #2, and repeated the last couple steps to
make a new partition on New #2 and copy New #1's first partition to it.
&lt;/p&gt;


&lt;p&gt;
- Used &lt;tt&gt;mdadm --assemble&lt;/tt&gt; to put the two identical RAID partitions --
&lt;tt&gt;/dev/hda1&lt;/tt&gt; and &lt;tt&gt;/dev/hdc1&lt;/tt&gt; -- back together into a RAID array and let it
re-sync them until &lt;tt&gt;mdadm&lt;/tt&gt; reported them to be in good health.
&lt;/p&gt;


&lt;p&gt;
- Used GRUB to re-install the MBR on both HDDs.  This was a damn sight harder
than it sounds (see below).
&lt;/p&gt;


&lt;p&gt;
All in all, it was a far cry from sliding a replacement hot-swap SCSI into a
nice hardware-based array -- but at $70, a fraction of the cost, though hardly
timely (my use of this server is as a document archive, web proxy, cron-job
runner, and general workhorse for background processing and speculative
projects for automated information-gathering tasks -- none of which are
mission-critical for us at Voyager).
&lt;/p&gt;


&lt;p&gt;
Tricky stuff:
&lt;/p&gt;


&lt;p&gt;
- Windows XP apparently doesn't come with ANY ability to burn ISOs.  WTF,
Microsoft?  Operating system ISOs are just about the &lt;em&gt;only&lt;/em&gt; legal thing I have
ever wanted to burn to a CD, and that's the &lt;em&gt;one&lt;/em&gt; thing you won't support?
(Well, duh, really.)
&lt;/p&gt;


&lt;p&gt;
- The latest Knoppix (5.0?) just plain barfed.  It may have been the speed at
which the dodgy ISO burning software I downloaded burned it (errors?).  In any
case, burned about an hour of my life trying different &quot;nousb&quot; and similar
switches to no avail.
&lt;/p&gt;


&lt;p&gt;
- &lt;a href=&quot;//www.pld-linux.org/&quot;&gt;PLD Linux&lt;/a&gt;'s rescue disk was small and booted
perfectly (though I took care to burn it at a low speed).
&lt;/p&gt;


&lt;p&gt;
- BLACK MAGICK: When booting from the rescue disk, to get &lt;tt&gt;mdadm&lt;/tt&gt; to
appropriately deal with the raid, there weren't any &lt;tt&gt;md&lt;/tt&gt; devices in &lt;tt&gt;/dev&lt;/tt&gt;
on which I could mount the RAID.  I needed a couple of times to create the
node &lt;tt&gt;/dev/md0&lt;/tt&gt; by issuing the commands:
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;mknod /dev/md0 b 9 0

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
Which, as I understand it, is &quot;make node &lt;tt&gt;/dev/md0&lt;/tt&gt;, type block, numerical type
#9 (the magic number for RAID?), and the 0th such block.&quot;  Then, since
&lt;tt&gt;mdadm&lt;/tt&gt; refused to automatically find and mount the drives for &lt;tt&gt;/dev/md0&lt;/tt&gt;, I
had to find the UUID for the RAID volume thus:
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;mdadm --examine --scan

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
And then copy the UUID (thanks, &lt;a href=&quot;//www.gnu.org/software/screen/&quot;&gt;GNU Screen&lt;/a&gt;!)
into the command:
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;mdadm /dev/md0 --assemble --uuid=&amp;lt;WHATEVER&amp;gt;

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
- Getting GRUB installed on the hard drives was, in the end, easier than I
thought but was rocky due to the complexity of the issues involved and me not
understanding them fully.
&lt;/p&gt;


&lt;p&gt;
If you search for &quot;software raid grub&quot; you'll find a number of web pages that
more or less get you there with what you need to know.
&lt;/p&gt;


&lt;p&gt;
For me to get GRUB to work, I did the following.
&lt;/p&gt;


&lt;p&gt;
- First, I had the &lt;tt&gt;/dev/md0&lt;/tt&gt; partition (the &quot;RAID partition&quot;) holding my
&lt;tt&gt;/&lt;/tt&gt; (root) partition,
with NO separate &lt;tt&gt;/boot&lt;/tt&gt; partition.  That means I had to make each of
&lt;tt&gt;/dev/hda1&lt;/tt&gt; and &lt;tt&gt;/dev/hdc1&lt;/tt&gt; (the &quot;RAID constituents&quot;) bootable.  Much of
what you read follows the old advice of having a separate &lt;tt&gt;/&lt;/tt&gt; and &lt;tt&gt;/boot&lt;/tt&gt;,
which I did not have.
&lt;/p&gt;


&lt;p&gt;
- Second, I had to boot from the rescue CD, get the RAID partition assembled,
mount it, and &lt;tt&gt;chroot&lt;/tt&gt; into the mount point of the RAID partition.  Like:
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;mknod /dev/md0 b 9 0
mdadm /dev/md0 --assemble --uuid=&amp;lt;WHATEVER&amp;gt;
mkdir /tmp/md0
mount /dev/md0 /tmp/md0
cd /tmp/md0
chroot .

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
Note that since the partition names and numbers were the same on my New #1
and #2 drives as they were on the old ones (hd[ac]1), there's no problem
with the old legacy &lt;tt&gt;/etc/mdadm/mdadm.conf&lt;/tt&gt; and it can tell the kernel how
to assemble and mount the RAID partition (important for below).
&lt;/p&gt;


&lt;p&gt;
- Then, once &lt;tt&gt;chroot&lt;/tt&gt;'ed into the RAID partition, I ran run-time GRUB
(&quot;run-time GRUB&quot; being when you run &lt;tt&gt;grub&lt;/tt&gt; as root on an already booted
machine for purposes of installing stuff or whatnot; this is opposed to
&quot;boot-time GRUB&quot; which looks pretty damn similar but is what is run off of
the master boot record -- MBR -- of a bootable partition onto which GRUB has
been installed) off of there, which used the existing Ubuntu &lt;tt&gt;menu.lst&lt;/tt&gt; file.
For some reason, that file ended up binary and corrupted.  Therefore, I had to
scrap it and come up with a new one.  Here's the meat of my new &lt;tt&gt;menu.lst&lt;/tt&gt;:
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;# Boot automatically after 15 secs.
timeout 15

# By default, boot the first entry.
default 0

# Fallback to the second entry.
fallback 1

# For booting Linux
title  Linux
root (hd0,0)
kernel /vmlinuz root=/dev/md0
initrd /initrd.img

# For booting Linux
title  Linux
root (hd1,0)
kernel /vmlinuz root=/dev/md0
initrd /initrd.img

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
- Using that menu.lst, the commands I entered &lt;em&gt;in the GRUB shell&lt;/em&gt; were as follows:
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;device (hd0) /dev/hda
root (hd0,0)
setup (hd0)
device (hd0) /dev/hdc
root (hd0,0)
setup (hd0)

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
The rationale behind this is that the first three lines install the current
&lt;tt&gt;menu.lst&lt;/tt&gt; (that is, whichever one it finds in &lt;tt&gt;/boot/grub/menu.lst&lt;/tt&gt;)  onto
the MBR of &lt;tt&gt;/dev/hda&lt;/tt&gt;, the first bootable HDD, and the second three lines
install onto the MBR of &lt;tt&gt;/dev/hdc&lt;/tt&gt;, the &lt;em&gt;second&lt;/em&gt; HDD, but fake out the
installation there of GRUB 
&lt;em&gt;to act as though it's on the first, bootable hdd (hd0)&lt;/em&gt;.
&lt;/p&gt;


&lt;p&gt;
Do you get it?  After chrooting, I fired up run-time GRUB, which automatically
looks in its current &lt;em&gt;boot/grub&lt;/em&gt; for &lt;tt&gt;menu.lst&lt;/tt&gt;.  I told it to put MBRs on both
&lt;tt&gt;/dev/hda&lt;/tt&gt; and &lt;tt&gt;/dev/hdc&lt;/tt&gt; to make boot-time GRUB behave as specified in
the &lt;tt&gt;menu.lst&lt;/tt&gt;. The &lt;tt&gt;menu.lst&lt;/tt&gt; lines say &quot;use hd0,0 (e.g. &lt;tt&gt;hda1&lt;/tt&gt;) as the root
directory, find the kernel (&lt;tt&gt;vmlinuz&lt;/tt&gt;) and &lt;tt&gt;initrd&lt;/tt&gt; there, and once the kernel get loaded,
tell it to use &lt;tt&gt;/dev/md0&lt;/tt&gt; as the &lt;em&gt;real&lt;/em&gt; root directory, which it can do
because it reads &lt;tt&gt;/etc/mdadm/mdadm.conf&lt;/tt&gt; or &lt;tt&gt;/etc/mdadm.conf&lt;/tt&gt; to figure out
its &lt;tt&gt;md&lt;/tt&gt; devices.  
&lt;/p&gt;


&lt;p&gt;
What puzzled me at first
was, &quot;how does the kernel get loaded when the root is &lt;tt&gt;/dev/md0&lt;/tt&gt; and you
obviously must run &lt;tt&gt;mdadm&lt;/tt&gt; in order to assemble and mount &lt;tt&gt;/dev/md0&lt;/tt&gt;?&quot;
The answer is that when you do the
installation commands listed above, it tells the boot-time GRUB to act as
though &lt;tt&gt;(hd0,0)&lt;/tt&gt; (AKA &lt;tt&gt;/dev/hda1&lt;/tt&gt; or &lt;tt&gt;/dev/hdc1&lt;/tt&gt;, depending on whether the BIOS
points to &lt;tt&gt;hda&lt;/tt&gt; or &lt;tt&gt;hdc&lt;/tt&gt; for booting) is its root directory.  So, boot-time GRUB, all
the way up through the loading of the kernel, treats &lt;tt&gt;/dev/hda1&lt;/tt&gt; (or &lt;tt&gt;hdc1&lt;/tt&gt;) as its
root, and only at the stage where the kernel is loaded enough to check
&lt;tt&gt;mdadm.conf&lt;/tt&gt; and run &lt;tt&gt;mdadm&lt;/tt&gt; does it then do a little &quot;&lt;tt&gt;chroot&lt;/tt&gt;&quot; of its
own.  If I've got this completely wrong, please [&lt;a href=&quot;mailto:rlucas@tercent.com&quot;&gt;rlucas@tercent.com&lt;/a&gt; email me]
and tell me I'm a bonehead (and include a link to your, more informed,
writeup).
&lt;/p&gt;


&lt;p&gt;
There's an elegance to the whole Linux software RAID thing, but it took a darn
long time to comprehend.
&lt;/p&gt;


&lt;p&gt;
$Id: linux_software_raid_and_grub.txt 698 2006-08-18 18:23:03Z rlucas $

&lt;/p&gt;
</description>
  </item>
  <item>
    <title>Broken Quoting of Spaces in Table Names in Ruby's ActiveRecord</title>
    <link>http://rlucas.net/blog/bugfix/index.rss/2006/07/21#ruby_active_record_sql_server_quoting_spaces_in_table_name</link>
    <description>&lt;p&gt;

Two-part posting. 
&lt;/p&gt;


&lt;p&gt;
1. The hot-shit developer boys at &lt;a href=&quot;http://dev.rubyonrails.org&quot;&gt;http://dev.rubyonrails.org&lt;/a&gt; apparently use
Python (Trac) for their bug-tracking system, and for extra chuckles, 
&lt;em&gt;it's broken.&lt;/em&gt;  
&lt;/p&gt;


&lt;p&gt;
From &lt;a href=&quot;http://dev.rubyonrails.org/newticket#preview&quot;&gt;http://dev.rubyonrails.org/newticket#preview&lt;/a&gt;
&lt;/p&gt;


&lt;p&gt;
(removed a Python stack trace that came down to a NOT NULL constraint
violation in the underlying database -- the error message was messing up the
blog formatting software.)
&lt;/p&gt;


&lt;p&gt;
Not the most helpful when I'm trying to post a bug report!
&lt;/p&gt;


&lt;p&gt;
2. So, I'm posting by bug report below.  Essentially, having spaces in your
table names throws a major monkey wrench in the &quot;convention over configuration&quot;
mantra of Ruby on Rails.
&lt;/p&gt;


&lt;p&gt;
I might fix this, if I can find the time (the lack thereof being why, in the
first place, Rails seemed so appealing).  If so, I will post a patch.
&lt;/p&gt;


&lt;p&gt;
---
&lt;/p&gt;


&lt;p&gt;
Legacy apps being built to SQL Server databases may find spaces in table names.  These can be addressed superficially by a:
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;set_table_name '&quot;Spacey Table&quot;'

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
or
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;set_table_name '[Spacey Table]'

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
This approach makes parent classes behave properly when directly interpolating table_name into a string, avoiding such errors as:
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;Invalid object name 'Company'.: SELECT count(*) AS count_all FROM Spacey Table 

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
HOWEVER, pre-escaping the table names in this way breaks the SQLServer
ConnectionAdapter's ability to get info out of SQL Server, as in
sqlserver_adapter.rb line 246 (line breaks added):
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;sql = &quot;SELECT COLUMN_NAME as ColName, COLUMN_DEFAULT as DefaultValue, 
DATA_TYPE as ColType, IS_NULLABLE As IsNullable, 
COL_LENGTH('#{table_name}', COLUMN_NAME) as Length, 
COLUMNPROPERTY(OBJECT_ID('#{table_name}'), COLUMN_NAME, 'IsIdentity') 
as IsIdentity, NUMERIC_SCALE as Scale 
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '#{table_name}'&quot;

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
As you can see, here it will try to match 'Spacey Table' = '[Spacey Table]'  for the brackets case (or '&quot;Spacey Table&quot;' for double quotes).
&lt;/p&gt;


&lt;p&gt;
Also, get_table_name(sql) will have trouble with this.
&lt;/p&gt;


&lt;p&gt;
To make this work without breaking encapsulation will probably require using an escaped table_name and then selectively unescaping it for the SQL Server-specific uses.
&lt;/p&gt;


&lt;p&gt;
All in all, MSFT's behavior is fairly satanic on this; see below for a link describing syntax and escaping.  Note that the only backwards-compatible solution is to SET QUOTED_IDENTIFIER ON and then use &quot;This Table&quot;.&quot;This Column&quot; notation, in order not to run up against problems with SQL Server &amp;lt; 6.5.
&lt;/p&gt;


&lt;p&gt;
&lt;a href=&quot;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/acdata/ac_8_con_03_89rn.asp&quot;&gt;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/acdata/ac_8_con_03_89rn.asp&lt;/a&gt;
&lt;/p&gt;


&lt;p&gt;
$Id: ruby_active_record_sql_server_quoting_spaces_in_table_name.txt 773 2007-01-16 18:14:05Z rlucas $

&lt;/p&gt;
</description>
  </item>
  <item>
    <title>Fixing a package remove failure on Debian (or Ubuntu) when dpkg-divert barfs.</title>
    <link>http://rlucas.net/blog/bugfix/index.rss/2006/06/18#debian_ubuntu_dpkg_apt-get_removal_failure</link>
    <description>&lt;p&gt;
2006-06-18
Randall Lucas
&lt;/p&gt;


&lt;p&gt;
If you get stuck with a half-uninstalled (technically &quot;half-installed;&quot; the
debian dpkg system is an optimist, I guess) package that barfs on running its
postrm (post-removal) script with something like:
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;&quot;dpkg-divert: mismatch on divert-to ...&quot;

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
This can sometimes be fixed, or at least made to shut up, by finding the
appropriate line in /var/lib/dpkg/info/PACKAGE.postrm and editing it to
reflect the right filenames for the dpkg-divert remove line.
&lt;/p&gt;


&lt;p&gt;
If you really need to get down and dirty (like, if the removal of a
non-critical package is stuck halfway and that is stopping you from doing an
installation of a really necessary package), you could just comment out that
whole bit with the goal of getting the postrm script to return success (0).
&lt;/p&gt;


&lt;p&gt;
Of course, if you're running any important services, you shouldn't be using
&quot;unstable&quot; or Ubuntu; just run Debian stable so you can sleep at night.
&lt;/p&gt;


&lt;p&gt;
$Id: debian_ubuntu_dpkg_apt-get_removal_failure.txt 625 2006-06-18 18:35:15Z rlucas $

&lt;/p&gt;
</description>
  </item>
  <item>
    <title>FIX: Ubuntu Dapper upgrade breaks CUPS printing; reinstall fixes it.</title>
    <link>http://rlucas.net/blog/bugfix/index.rss/2006/06/11#ubuntu_dapper_cups_printing_reinstall</link>
    <description>&lt;p&gt;
2006-06-11
Randall Lucas
&lt;/p&gt;


&lt;p&gt;
Upon upgrading my Ubuntu installation to Dapper using a simple:
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;sudo vim /etc/apt/sources.list

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
to add the Dapper repositories, and then 
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;sudo apt-get update
sudo apt-get dist-upgrade

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
I discovered that my printing no longer worked.  I just previously been
printing (and sharing my printer with a Windows / Mac mixed environment) just
fine from my HP multifunction printer.
&lt;/p&gt;


&lt;p&gt;
Among other errors, I kept receiving a note in my logs to the effect of:
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;cupsdAuthorize: Local authentication certificate not found!

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
I looked around and found what appeared to be a certficate in
/etc/cups/certs but that didn't change anything.  In frustration, I tried
simply reinstalling cupsys with:
&lt;/p&gt;


&lt;blockquote&gt;&lt;pre&gt;sudo apt-get remove cupsys
sudo apt-get install cupsys

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
To my surprise, after doing this and reconfiguring the printer, everything
worked OK again.  My theory is that the upgrade did not upgrade the
certificate (or clobbered an old one, thereby breaking it), and that
reinstalling caused a fresh cert to take effect.
&lt;/p&gt;


&lt;p&gt;
This may not be your solution; there were other, more serious problems with
CUPS in Dapper, as detailed here: &lt;a href=&quot;https://launchpad.net/distros/ubuntu/+source/cupsys/+bug/45099&quot;&gt;https://launchpad.net/distros/ubuntu/+source/cupsys/+bug/45099&lt;/a&gt;
&lt;/p&gt;


&lt;p&gt;
$Id: ubuntu_dapper_cups_printing_reinstall.txt 620 2006-06-16 00:18:05Z rlucas $

&lt;/p&gt;
</description>
  </item>
  </channel>
</rss>