Trouble dragging Apps between displays in OS X

Imagine my joy when the company owner decided (for reasons that I care not to divulge here) to swap his year old MacBook Pro for my nearly two year old Dell X1! I hadn’t been using the Dell since I also had a year old MacBook (white) and although I was giving up 20GB of storage to upgrade from the MB to the MBP I jumped at the offer.

54 minutes after firing up Migration Assistant I was in business and loving the MBP goodness NOTE: I had just upgraded the MBP for the owner from Tiger to Leopard by means of a fresh install. So there wasn’t a lot of cruft on the drive that needed cleaning up once I deleted his user account.

All was well until I got around to hooking the MBP up to my second display. I am in the habit of using my ViewSonic VX715 for my work screen since it sits above my laptop, and leaving social apps like Adium, NatsuLion, and Skype open on the laptop display. However, I was no longer able to drag Safari, TextMate, etc. to the upper display although I could drag all the social apps there. Bizarre!

I posted this “annoyance” on Twitter and then the solution came to me immediately. All my “work” apps were too wide to fit the VX715’s default resolution of 1024X768. DOH! Adjusting the monitor’s resolution via System preferences freed my apps to move wherever I choose. I am a bit annoyed though that OS X apparently does not permit “over-sized” app windows move between displays since it is certainly possible to make an app window wider than any single screen. Nonetheless, mystery solved.

Software Testing

To many of you this information will come as no surprise, but I’ve searched (perhaps not hard enough) for succinct definitions of the various “types” of software development tests and I recently found these which I have paraphrased. Unfortunately, I do not now recall the source from which I derived these notes. If you believe you are the original author, please contact me and I will add proper attribution if your information appears familiar.

NOTE: I have ordered the tests (I believe) from most granular to least where such adjectives apply.

Software Testing:

  • Unit - Do the smallest “units” of code work?
  • Functional - Do the logical groupings of code work?
  • Integration - Do the all the functional pieces fit together?
  • Acceptance - Does the code do what the customer wants?
  • Regression - Does the code still work?

How I Learned to Stop Worrying and Love my Mac

As I am want to do, I became involved in an exchange on Twitter with the lovely and talented Cal Evans concerning his thoughts about forsaking his current OS/hardware choice and going Mac instead. While this seemed like a slam dunk to me, one person’s experience seemed to be giving him pause. With Twitter’s 140 character limit, there was no way for me to do justice to a very positive experience I had with Apple customer service. So, I thought I would recount the story here for posterity.

One of my current employers, Amphora Research, purchased me a PowerBook in 2005 which served me faithfully for a couple of years, until the hard drive died. Conditioned as I was to sweat such events by years of Windows and Linux use, I was not looking forward to the road to recovery ahead. I was no “spring chicken” and had been religiously backing up the PB using SuperDuper. Nonetheless, I was apprehensive as I headed to the local Apple Store to see what the geniuses could do for me. We had purchased Apple Care for the PB. So I was hoping for minimal hassle.

Upon arrival at the Genius Bar, without an appointment (you could still do that in 2007), I was greeted by a very knowledgeable genius (redundant as that may sound) who, after listening to my sad story, asked me to be patient while he checked to see what hardware they had available. As it turned out, all they had was an 80GB drive in stock but my PB came with only a 60GB drive installed. Prepared to be disappointed, I was very pleasantly surprised when the the genius asked if I would mind the extra 20GB of storage. When I asked how much the extra 20GB would cost me I was once more pleasantly surprised when he told me there was no additional cost! He asked me if I had all my data backed up which I assured him I did, and he informed me that he would need to keep the bad drive which was no concern to me. Giving Apple one more chance to disappoint me, I asked when the laptop would be ready to pick-up. “Give me a half an hour” he said, and one strawberry smoothie later I was walking out of the Kenwood Towne Centre with a juicy little upgrade but anticipating a day or two of OS and application re-installation.

I recalled the Apple genius telling me restoring the drive would be a snap when I told him I had backed up the drive using SuperDuper. He could not have been more correct. Here is the entire restore process (windows and Linux users may want to turn away at this point!):

  • Attach the SuperDuper back-up volume to the PB.
  • Reboot the system and hold the Option key down during the restart.
  • Select the back-up volume as the boot volume.
  • Launch SuperDuper and copy the contents of the back-up volume to the internal hard drive.
  • Reboot.

No OS re-install. No application re-install. Simply go back to work! It don’t get no better than this.

Shortly thereafter, my boss bought me a new MacBook which required service six months after its purchase that necessitated a week long stay at a local Apple service provider, ComputerDNA. What was I going to do without my Mac for a week? Keep on working! I booted a Mac Mini we used for pair programming from the SuperDuper back-up volume and composed and saved documents to the back-up volume as if it were the internal drive. Once my MB was returned, I restored the back-up copy to the internal drive of MB and all my new work was there waiting for me. There were no hardware issues booting the back-up created on my MacBook on the Mini, or booting the back-up updated on the Mini and restored to the MacBook.

I’ve been using Macs for ten years and as my OS of choice for four years now. When I “need” Windows or Linux I fire up VMware Fusion but I’m always relieved to return to OS X. When was the last time you were pleasantly surprised by your operating system?

PS: Just so you don’t think I’m too much of an Apple/OS X fanboy, FileVault SUCKS!!!

Hello world!

I will never write an “enterprise” software application; web-based or otherwise. Thus, BIG design makes little sense in my world. I’m a “scratch your own itch” developer. The problems that most interest me are closest at hand and, frankly, “traditional” software design practices would be wasted solving such problems. As the days, weeks, months, and (God willing) years pass, you will find more information here pertaining to the latter and less about the former.

I was first exposed to Agile Software Development when my employer at the time began hosting the monthly Cincinnati eXtreme Programmers (or “XP-Cinci”, now known as the “Agile Round Table”) meetings. Having worked 17 years in various non-IT roles for a large, commercial airline, I had had enough of BIG.

My formative years as a developer were influenced heavily by fellow XP-Cinci members like Jim Weirich, Mark Windholtz, and Joe O’Brien. Each of these guys, and many others, has a wealth of BIG design experience and yet each has found Agile means more productive, rewarding, and, dare I say it, fun to use not only on their own software projects but those, large and small, that they produce for profit.

So sit back, step away from that Gantt chart, and have fun!

Quick & Painless PDF Watermark

For my part-time gig I needed an elegent way to nudge an absent minded customer of his past due account balance. I typically invoice via an emailed PDF which I thought would be cool because one day I could create a “second notice” version by placing an appropriate watermark behind the original invoice. That at least was the plan…

Well, after months of forgetting to play with this idea, or playing with it on and off, I stumbled upon this. Now, thanks to Colin, and especially the creator(s) of pdftk the process of creating my second notice invoices is a simple as this:

pdftk invoice.pdf background notice.pdf output notice_invoice.pdf

What’s even better is that pdftk is available for Linux, OS X, FreeBSD, Solaris, and Windoze.

Ruby Code Camp

Greetings from Ruby Code Camp in Columbus, OH and thanks to the Columbus Ruby Brigade for spreading the word and to all the sponsors, especially Agile Consulting and EdgeCase. Here’s what I’ve learned…

Beside many other brilliant things he said, Rob Stevenson demonstrated the
following (figurative - not literal) gem that will display all methods to which an
object will respond:

>> 1.methods.each { |i| printf "Method name: %s\n", i.to_s }
Method name: %
Method name: inspect
Method name: <<
Method name: singleton_method_added
Method name: &
Method name: clone
Method name: >>
Method name: method
Method name: round
Method name: rpower
Method name: public_methods
...

As Rob Biedenharn was setting up for the next session he had the contents
of his .irbrc file which among other things contained the following:

IRB.conf[:PROMPT_MODE] = :SIMPLE
IRB.conf[:AUTO_INDENT] = true
require 'rubygems'
def clear
  system "clear"
end
alias :cls :clear

Setting the irb prompt to simple removes everything but the two
“greater than” characters. The auto indent feature indents your
input automatically (duh!) according to Ruby code conventions which is
something Jim Weirich apparently didn’t know and although I would love to be
able to tell folks that I taught Jim something about Ruby i only learned it
by googling it two minutes prior to showing Jim. Since I use rubygems a lot
I add those in by default, and since I like to keep my screen clean so I
stole, eh…, I mean re-used Rob’s “clean” method setting an alias for called
“cls”. I combined this knowledge to create the following means to output a
sorted list of all methods to which a given object will respond:

def pretty_methods obj
  obj.methods.sort.each { |i| printf "%s\n", i.to_s }
end

alias :pm :pretty_methods

During the second hour of Ruby Introduction taught by Ron McCamish and coded by Rob Biedenharn I learned a new thing or three as the case may be about quickly getting at regular expression match data:

irb
>> b = /v(olly)?ball/
=> /v(olly)?ball/
>> str = "My vollyball is Tachikara"
=> "My vollyball is Tachikara"
>> str =~ b
=> 3
>> $`
=> "My "
>> $&
=> "vollyball"
>> $'
=> " is Tachikara"

Finally, I learned that I need to better understand closures, the difference between “detect” and “select”, and that I will never be able to code as well as Jim Weirich.

Mac OS X, Ruby, CGI without Rails

In the midst of my Rails based Web development I was tasked with the creation of a simple, one page Web form. I knew it would be a snap to write given my background in PHP and the broad support for PHP in OS X but I decided to “teach myself” how I could do the same thing in Ruby without the crutch of Rails.

The first step was to create the Web form with static HTML which took about 15 minutes, start to finish. I configured the form action to point to my Ruby script that would simply echo “Thanks!”.

Clicking the “Submit” button on my form produced the “Opening form_handler.rb” window (Windows readers your mileage may vary from this point forward) meaning that Apache did not know what to do with files with “.rb” extensions. A quick visit to /etc/httpd/httpd.conf to add the following line beneath the other AddHandler options did the trick.

AddHandler cgi-script .rb

After restarting Apache, and clicking the “Submit” button again I was greeted with a 500 error. A peek at /var/log/httpd/error_log revealed the following:

Options ExecCGI is off in this directory: /Users/sjobs/Sites/cgi-bin/form_handler.rb

That’s easy enough to fix. Placing a .htaccess file containing the following line resolved that issue:

Options ExecCGI

Finally, with no special modification to Apache included out-of-the-box with OS X except those changes noted above my Ruby CGI script was performing as expected. Total time invested: 30 minutes. Not bad. The basic script, which just chunks out the form values and some other stuff appears below. An excellent reference to Ruby’s CGI library is, of course, located in RDoc.

#!/usr/bin/env ruby
require 'cgi'

cgi = CGI.new("html4")
params = cgi.params

cgi.out() do
  cgi.html() do
    cgi.head{ cgi.title{"TITLE"} } +
    cgi.body() do
      cgi.pre() do
        CGI::escapeHTML(
          "params: " + cgi.params.inspect + "\n" +
          "cookies: " + cgi.cookies.inspect + "\n" +
          ENV.collect() do |key, value|
            key + " --> " + value + "\n"
          end.join("")
        )
      end
    end
  end
end

Just Missed Me - Chapter Two

The “Rails” components of the website were completed in about 20 minutes and consist of nothing more than a form which provides the user a means to supply a date and returns an appropriate (some would argue) list of the deceased.

After quite a bit of experimentation and refactoring I have refined the script which parses Wikipedia’s Persondata from the XML dump to the following:

#!/usr/bin/env ruby

require 'ParseDate'

fp = "/Users/sjobs/data/enwiki-20061130-pages-articles.xml"
page_start = /\
/
page_end = /\<\/page\>/
has_persondata = /\{\{Persondata/
regex_name = /\|NAME=(.*)/
regex_page_title = /\(.*)\<\/title\>/
regex_page_id = /\(.*)\<\/id\>/
regex_date_death = /\|DATE OF DEATH=(.*)/

def cleanse data
  wiki_marks = /\[\[|\]\]|\{\{|\}\}/
  clean = data.strip.gsub(wiki_marks, '')
  clean.gsub(/'/, "\\\\'")
end

def process_date date
  if !date.nil?
    date = ParseDate.parsedate(date)
    if !date[0].nil? and !date[1].nil? and !date[2].nil?
      sprintf("%04d-%02d-%02d", date[0], date[1], date[2])
    else
      nil
    end
  end
end

File.exists? fp and File.readable? fp
File.open(fp, "r") do |file|
  i = 0
  concat = false
  page_text = ''
  while line = file.gets
    if !page_start.match(line).nil? or concat
      concat = true
      page_text = page_text + line
      if !page_end.match(line).nil?
        if !has_persondata.match(page_text).nil?
          i = i + 1
          date_death = regex_date_death.match(page_text)[1] unless ↵
              regex_date_death.match(page_text).nil?
          name = regex_name.match(page_text)[1] unless ↵
              regex_name.match(page_text).nil?
          page_title = regex_page_title.match(page_text)[1] unless ↵
              regex_page_title.match(page_text).nil?
          page_id = regex_page_id.match(page_text)[1] unless ↵
              regex_page_id.match(page_text).nil?
          date_of_death = process_date(cleanse(date_death))
          if !date_of_death.nil?
            puts "- !ruby/object:Person"
            puts "  attributes:"
            puts "    date_of_death: " + date_of_death unless date_of_death.nil?
            puts "    name: " + cleanse(name) unless name.nil?
            puts "    page_title: " + cleanse(page_title) unless page_title.nil?
            puts "    page_id: " + cleanse(page_id) unless page_id.nil?
            puts "    id: " + i.to_s
          end
        end
        concat = false
        page_text = ''
      end
    end
  end
end

Much of the data I was parsing is no longer being collected as I am re-evaluating the schema since much of the data within the Wikipedia database is void of any consistent form (as expected).

The keen observer will note that this script generates YaML which I import painlessly via Geoffrey Grosenbach’s ar_fixtures plugin for Rails.

The next problem to solve is the parse the free-form date to be entered by the user. I had this working using Ruby’s ParseDate but I’m unable to reliably create a date that will then be feed to MySQL or generate a nil value. I am passing the output from ParseDate’s sole method, parsedate, to the new method of Ruby’s Date class but after working for a while the method is now returning an “invalid date” error. More later…

Just Missed Me - Chapter One

OK, need proof that I’m a nuby? How’s this for proof?

#!/usr/bin/env ruby

fp = "/Users/sjobs/data/enwiki-20061130-pages-articles.xml"
page_start = /\
/
page_end = /\<\/page\>/
has_persondata = /\{\{Persondata/
regex_name = /\|NAME=(.*)/
regex_alter_names = /\|ALTERNATIVE NAMES=(.*)/
regex_description = /\|SHORT DESCRIPTION=(.*)/
regex_page_title = /\(.*)\<\/title\>/
regex_page_id = /\(.*)\<\/id\>/
regex_date_birth = /\|DATE OF BIRTH=(.*)/
regex_place_birth = /\|PLACE OF BIRTH=(.*)/
regex_date_death = /\|DATE OF DEATH=(.*)/
regex_place_death = /\|PLACE OF DEATH=(.*)/
regex_revision_timestamp = ↵
   /\.*\(.*)\<\/timestamp\>.*\<\/revision\>/m

File.exists? fp and File.readable? fp
File.open(fp, "r") do |file|
  concat = false
  page_text = ''
  while line = file.gets
    if !page_start.match(line).nil? or concat
      concat = true
      page_text = page_text + line
      if !page_end.match(line).nil?
        if !has_persondata.match(page_text).nil?
          name = regex_name.match(page_text)[1] unless ↵
            regex_name.match(page_text).nil?
          alternative_names = regex_alter_names.match(page_text)[1] unless ↵
            regex_alter_names.match(page_text).nil?
          description = regex_description.match(page_text)[1] unless ↵
            regex_description.match(page_text).nil?
          page_title = regex_page_title.match(page_text)[11] unless ↵
            regex_page_title.match(page_text).nil?
          page_id = regex_page_id.match(page_text)[1] unless ↵
            regex_page_id.match(page_text).nil?
          date_birth = regex_date_birth.match(page_text)[1] unless ↵
            regex_date_birth.match(page_text).nil?
          place_birth = regex_place_birth.match(page_text)[1] unless ↵
            regex_place_birth.match(page_text).nil?
          date_death = regex_date_death.match(page_text)[1] unless ↵
            regex_date_death.match(page_text).nil?
          place_death = regex_place_death.match(page_text)[1] unless ↵
            regex_place_death.match(page_text).nil?
          revision_timestamp = regex_revision_timestamp.match(page_text)[1] unless ↵
            regex_revision_timestamp.match(page_text).nil?
        end
        concat = false
        page_text = ''
      end
    end
  end
end

I decided that STX would require too significant an investment in time and while I may integrate hpricot at some point the solution above seems sufficient for the moment.

I have yet to begin importing any of the data into the database. I’ll want to format the data consistently and remove the wiki specific mark-up. Feel free to rip the code apart and please do make suggestions. I am after all a nuby.

Just Missed Me - Chapter Zero

I became interested in hpricot while experimenting during the creation of a prospecting system for my employer. Driving home from work one day I hatched an idea for a website that would employ hpricot to pull its data from Wikipedia’s Persondata.

Due to the extremely large size of the associated data file I soon determined that an hpricot-based solution would not scale. Digging a bit on Wikipedia I discovered STX which appears to be a more promising means of proceeding. I’ll keep you posted.