Idol Hands:
Days in the Life of an Alpha Geek

Corey Ehmke’s home on the web since 1996, IdolHands.com features an alpha-geek blog covering topics in Mac OS X, software and web development (mainly Cocoa and Ruby on Rails), electronics, robotics, and other stuff important in the life of a technologist and tinkerer.

Bizarre BBEdit 9 bug

Posted by Corey Ehmke on September 5th, 2008 in Development, Ruby on Rails | Permanent Link
Tags:

After upgrading to BBEdit 9, I’ve happily left TextMate behind and returned to my favorite bare-bones IDE for Rails development. (I’m planning to share some tips on this topic this weekend.)

I just came across a very strange bug that crashes BBEdit, and thought I’d share a workaround in case someone else has this problem. The bug report has already been filed.

Operating environment:
BBEdit version 9.0 (1320) of Wed, 27 Aug 2008
Mac OS X 10.5.4 Build 9E17

To reproduce:

  • Create a new file
  • Set its type to Ruby using the menu at the bottom of the window
  • Type (not paste) the following, exactly as you see it here:

    "tag-#

BBEdit will now invoke the spinning beach ball of death, start consuming massive CPU cycles, and never recover. Note that I have text completion triggers turned OFF, so that’s probably not the problem.

The workaround for this is (and any similar string that brings this on) is open the Scratchpad window (Window -> Show Scratchpad), type your string in there, and paste it back into your Ruby file.

I should point out that a couple of minor issues aside, I’m incredibly happy with this upgrade. And given my history with Bare Bones, I expect fixes to be forthcoming quickly.

Rewriting Kafka

Posted by Corey Ehmke on August 29th, 2008 in Personal | Permanent Link
Tags:

While cleaning up one of my old machines, I came across this little artifact.

My challenge was to re-write the opening paragraph of Franz Kafka’s The Metamorphosis as it may have been penned by other writers. So without further ado…


The Metamorphosis by H.P. Lovecraft

My name is Gregor Samsa, and if the world discovers this manuscript, then perhaps it can save others from the fate that even now confounds my reason and leaves me gibbering at the edge of sanity. One morning not long ago I awoke from troubled dreams filled with the otherworldly ululations of strange voices and the insistent piping of flutes from the swirling chaos at the very center of the universe, and found myself in my bed, horribly changed– dare I say it?– into an unspeakable, sanity-blasting form. I lay on what seemed to be an armour-like back, and as I lifted my head a little I could just see the brown, non-Euclidean curve of my brown belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment. My multitudinous legs, pitifully gaunt compared with the unnaturally bloated shape of the rest of my new and terrible form, waved about helplessly as I looked on in abject horror.


The Metamorphosis by Ernest Hemingway

It was morning. Gregor Samsa awoke. He had been transformed in his bed into a cockroach. He lay on his back. He could see his brown belly, domed and divided into stiff arches. The bedding barely covered it. His legs waved.


The Metamorphosis by Walt Whitman

I sing the body carapacious;
The sprawl and fullness of its shell,
Stiff domed arches engirth my belly, and I engirth them;
They will not let me off my back until I embrace them, accept them,
And discorrupt them, and charge them full with the charge of the Soul.

The expression of the face defies description;
But the expression of a man made a bug appears not only in his antennae;
It is in his many legs also, it is in the joints of his carapace,
It is in his crawl, the carriage of his thorax, the flex of his abdomen–
The bedsheets do not cover it;
The strong, thin legs he has strike through the bedding;
To see him conveys as much as seeing a cockroach, maybe more;
You linger to see him on his back, waving his legs at you.

O my Body! I dare not desert the likes of you in other men and women, nor the likes of parts of you;
Head, neck, hair, ears, eyes, mouth, tongue, lips, teeth, nose, cheeks, forehead, chin;
And not head, thorax, abdomen, carapace, mandibles, antennae, compound eyes!


The Metamorphosis by E. Allen Poe

Mr. S___ was in one of his fits — how else shall I term them? — of enthusiasm. His brother Gregor had in his sleep transformed into an unknown bivalve, and, more than this, he had been hunted down and secured; he was now clearly visible as a scarabaeus which was believed to be totally new, but in respect to which S___ wished to have my opinion on the morrow.

“And why not to-night?” I asked, rubbing my hands over the blaze, and wishing the whole tribe of scarabaei at the devil.

“Ah, if I had only known you were here!” said S___, “but it’s so long since I saw you; and how could I foresee that you would pay me a visit this very night of all others? As I was coming home I met Lieutenant Gentarme from the fort, and, very foolishly, I lent him the bug– that is to say, my brother; so it will be impossible for you to see him until the morning. Stay here to-night, and I will send down for him at sunrise. He is become the loveliest thing in creation!”


The Metamorphosis by Kahlil Gibran

And a man said, “Speak to us of metamorphosis.”

And he answered saying:

You would know what it is like to awaken, transformed, from a troubled dream.

You would gaze with compound eyes on the naked curve of your brown belly.

You would touch with your antennae the slight bedding that barely hides your form.

You would kick with your many legs and free yourself from the prone position you find yourself in.

But let there be no helpless waving and fearful scurrying from the light.

For like the soul, the insect is a creature boundless and beautiful.

Say not, “I have metamorphosized into a bug,” but rather, “The bug has metamorphosized into me.”

For the soul walks upon all paths, whether on two legs or six.


I don’t remember what initially inspired this, but I’m pretty sure that a combination of alcohol and IRC were involved.

Update: I submitted this to McSweeney’s and got a very nice rejection letter:

This is fun, but I’m afraid we’re not going to use it. We ran a piece about Kafka and another about Lovecraft not too long ago and we’re not quite ready to return to them. Thanks for giving us a shot, nonetheless.

I haven’t attempted to submit anything non-technical for publication since I was a teen, because I don’t handle rejection well, but hopefully I’m old enough now to deal with it. I’m going to try again sometime. For real.

BBEdit 9 and Subversion 1.5

Posted by Corey Ehmke on August 29th, 2008 in Development, Technology | Permanent Link
Tags: , , ,

About a month ago, I replaced my old SVN GUI client (svnX) with the excellent Versions SVN client from Pico. I won’t rave about it now; check it out for yourself and bask in the goodness.

One of the unfortunate side-effects of using Versions, however, was that after the mandatory upgrade of SVN from 1.4 (OS X default) to 1.5, BBEdit’s SVN support was broken. I kept getting the message “svn: This client is too old to work with working copy“. Grr.

I looked around in BBEdit’s preferences and even .plist files, to no avail. This morning I even filed a bug report with Bare Bones. Turns out that that was premature… BBEdit was doing the right thing all the time, using the system’s SVN. The problem was that I had multiple versions of SVN installed.

From the command line:

Cerberus:bin bantik$ which svn
/usr/local/bin/svn
Cerberus:bin bantik$ svn --version
svn, version 1.5.1 (r32289)
   compiled Jul 25 2008, 12:47:20
...

As expected. However, this was less than expected:

Cerberus:bin bantik$ find / -name "svn" -print | grep svn
/opt/subversion/bin/svn
/usr/bin/svn
/usr/local/bin/svn

OK, but maybe some of those are links?

Cerberus:bin bantik$ ls -al /opt/subversion/bin/svn
-rwxrwxr-x  1 admin  admin  788520 Jul 25 14:05 /opt/subversion/bin/svn
Cerberus:bin bantik$ ls -al /usr/bin/svn
lrwxr-xr-x  1 root  wheel  23 Jul 13 09:41 /usr/bin/svn
Cerberus:bin bantik$ ls -al /usr/local/bin/svn
lrwxr-xr-x  1 root  wheel  23 Aug  3 19:39 /usr/local/bin/svn
       -> /opt/subversion/bin/svn

Aha! I’ve got an old version of SVN at /usr/bin. So let’s replace that with a symbolic link to the new version:

Cerberus:bin bantik$ sudo rm /usr/bin/svn
Cerberus:bin bantik$ sudo ln -s /opt/subversion/bin/svn /usr/bin/svn

That should do it. I restarted BBEdit just to make sure, and now, like magic, Subversion integration works again.

Getting to know acts_as_versioned

Posted by Corey Ehmke on August 27th, 2008 in Ruby on Rails | Permanent Link

I’ve been using Rick Olson’s acts_as_versioned Rails plugin on a project and recently ran into some thngs that I thought might be worth sharing.

In general, acts_as_versioned behaves well and integration has gone smoothly. The object that we wanted to version is called SurveyContent. We created a database table called survey_content_versions with the same columns and data types as survey_contents, plus id (key) and survey_content_id (foreign key to the versioned object). After adding :acts_as_versioned to the class definition for SurveyContent, every save of a SurveyContent object that has changes results in a new survey_content_version entry in the database.

Making acts_as_versioned play nicely with acts_as_state_machine

acts_as_versioned provides methods for things like .revert_to, .latest, and .previous, which is really nice. But we ran into trouble on a few fronts, particularly since SurveyContent also uses acts_as_state_machine. Users can request changes to their associated survey content, but these changes are subject to administrative approval, so we basically care about two versions of a SurveyContent instance: the approved version, and the latest version. Since we have distinct states defined for acts_as_state_machine, we’re used to calling foo.approved? to see if an object is in the “approved” state. Unfortunately, these convenience methods are not available on our survey_content_version object.

We ended up adding the methods to our version by creating anonymous mix-ins in SurveyContent:

class SurveyContent < ActiveRecord::Base
...
  acts_as_versioned do
    def approved?
    	self.status == "approved"
    end
    ...
  end

No real magic here– the documentation for the plugin provided the tip– but hopefully this will be of use to someone else.

Cloning a version

There was another situation in which we needed to act on an actual instance of a different version of SurveyContent, while keeping the existing instance intact. In that case, we opted to clone:

def approved_version
  if @approved_version.nil? && self.survey_content
    _last_approved = self.survey_content.versions.reverse.detect
      {|v| v.status == "approved"}
    unless _last_approved.nil?
      @approved_survey_content = SurveyContent.new
      _temp = _last_approved.attributes
      _temp.delete('survey_content_id')
      @approved_survey_content.attributes = _temp
    end
  end
  @approved_survey_content
end

Maybe a little ham-fisted, but it got the job done. Note that we had to drop the survey_content_id from the attributes, as SurveyContent has no such field.

acts_as_versioned and serialized attributes

The last problem we ran into had to do with the fact that one of the attributes on our versioned object was serialized. Out of the box, acts_as_versioned ended up converting it to a string. Luckily, some Google mining later, we found the solution.

First, we added some code to acts_as_versioned.rb:

def acts_as_versioned(options = {}, &extension)
...
    # Preserve serialized attributes
    self.serialized_attributes().each do |key, value|
      versioned_class.serialize key, value
    end

  end

end

module ActMethods
...

Then, we added another method to our anonymous mix-in on SurveyContent:

class SurveyContent < ActiveRecord::Base
...
  acts_as_versioned do
    def after_initialize
      self.data ||= Hash.new
    end

    ...
    def approved?

(Note that in the snippet above, data is the name of our attribute.)

One last problem with serialization that we ran into was that acts_as_versioned was not detecting changes when we did a merge operation on our serialized attribute. To ensure that a save took place, we had to call will_change!:

def survey_content_date=( survey_content_params )
  self.survey_content.data_will_change!
  ...

Again, substitute the name of your object’s parameter for data.

Go version something!

If you’re looking for the plugin, be sure to download acts_as_versioned from github and not Rick’s site– he’s moved from SVN to Git, and github has the latest version.

Three Decades of Corey

Posted by Corey Ehmke on August 24th, 2008 in Personal | Permanent Link

I recently discovered a treasure trove of yearbook photos that look remarkably like me. Take a look, and ask yourself how this came about: Clever Flash application, time machine, or incredibly strong genetics? You decide. (Hint: check out yearbookyourself.com and prepare to lose an hour.)

Corey in 1956

1956

Corey in 1958

1958

Corey in 1960

1960

Corey in 1964

1964

Corey in 1970

1970

Corey in 1974

1974

Corey in 1988

1988


The 70’s were definitely not a good time for me. As for that 1988 photo… well, it does look pretty accurate, actually. I graduated high school in 1989, and that’s pretty much how I looked back then. My hair was a little longer, and I was definitely not in a sweater-over-collared-shirt combination; but still, quite close.