Old Parallel (LPT) Printers and Mac OS X

I have an HP LaserJet 5P that has been in the family for over 15 years and is still kicking butt. Today I wanted to get it to work on my Apple Macbook Pro laptops without having to fork out a ton of cash for a print server device.

I purchased a USB to Parallel adapter, which OS X naturally couldn’t use see. To get around this issue, I ran the CUPS Gutenprint installer and the usbtb installer. The base installer installs the print drivers maintained by Gutenprint and usbtb installs the core component that supports USB printers. On Leopard (OS X 10.5) the installation step that searches for printers gave me an error message about not being able to find any printers, but I just continued, and when asked whether to copy or create a new queue, I naturally opted to create a new one. On Snow Leopard (10.6) A printer called “Unknown Unknown” was found and I wasn’t prompted about copying or creating a new queue. Both installations appeared to work. However, on both flavors of OS X, I went to System Preferences... > Print & Fax and ensured the printer was named what I wanted and set to use the HP LaserJet 5P – CUPS+Gutenprint v5.2.5 driver.

Gotta’ love open source software! (If I remember correctly, Richard Stallman was trying to fix a printer driver when he created the idea of “free software”–now known as open source–because the driver was closed-source and wasn’t working.)

UPDATE: If you need to share your printer with Windows machines, this article from Apple does the trick.

Our Code Is in 15% of Rails Applications (Roughly)

New Relic just posted some basic statistics on the Rails applications they monitor. They include lists of the top Ruby gems and top Rails plugins installed for each application they monitor. Patrick and I were delighted to discover that our ActiveMerchant code contribution is installed with 15% of Rails applications. We wrote the code for SandwichBoard and Patrick continues to improve upon it for LivingSocial Daily Deals.

Whether or not those 15% are actually using our code for Authorize.Net ARB or CIM credit card charging is unclear; but, it’s cool to know your code is installed with that many applications.

Ruby Method to Block (Lambda)

In Ruby on Rails development, I have been known to use symbol to proc. Recently, I needed to re-use a method as a block.

Here’s a contrived example of what I was doing:

Group.all.sort {|a,b| a.name <=> b.name}

However, I wanted to re-use this sort and ended-up refactoring it to:

def group_sort(a, b)
  a.name <=> b.name
end
Group.all.sort {|a,b| group_sort(a, b)}

Although this allowed me to re-use my sorting mechanism just fine, it seemed verbose. I was able to be succinct by using a lambda like so:

group_sort = lambda{|a,b| a.name <=> b.name}
Group.all.sort &group_sort

(Using a lambda may be obvious to Ruby pros, but I’m not there yet.)

Testing Rails Exception Notification in Production

Every Ruby on Rails project I have been involved in has used the Exception Notification gem. It sends you an email with very helpful debugging information whenever your application breaks in the real world. However, I’ve seen people fail to ensure that it actually works in their production environments–not when they first launch their site, but weeks and months afterward when it really matters. If your production environment changes, your application may fail, but you might not get an email about it because that which broke might have affected email sending. And you’ll think everything is honky-dory. Make sure you have something like this in your application and that you test it periodically to ensure you’re getting exception notification emails.

In config/routes.rb:

  map.connect 'test_exception_notifier', :controller => 'application', :action => 'test_exception_notifier'

In app/controllers/application_controller.rb:

  def test_exception_notifier
    raise 'This is a test. This is only a test.'
  end

I also recommend adding this to a periodic test script and your deploy script so you don’t have to remember to test it.

Importing a Contacts CSV into Gmail and BitPim Correctly

Snowmageddon was the perfect excuse for me to initiate my migration over to Google Gmail and play with Google Voice.

I had to start by exporting and merging my contacts out of an LG EnV via BitPim, Microsoft Windows XP Address Book, and Microsoft Hotmail Contacts. The export to comma-separated values (CSV) in each application was straightforward. The merging I did manually in Microsoft Excel because Address Book and Hotmail stick to the human-readable Mobile Phone, Home Phone, Office Phone, but BitPim spits-out primary, secondary, and tertiary phone numbers as numbers_number, numbers_type three times over. As for email addresses and email types, Address Book and Hotmail do the primary, secondary, tertiary dance, while BitPim limits it to primary and secondary email addresses and types.

After having a cleaned-up contacts list, I was ready to charge forward. However, to my dismay, the Gmail Contacts CSV importer prefers a different format. It wants primary, secondary, and tertiary phone number and phone number type columns and primary and secondary email and email type columns, but the type column data is different depending on what sort of data a record has. So, while Home may work for one record, another record requires * Home. Mind-blowing.

With inspiration from others who have walked a similar path, I decided to write a simple Ruby script to convert contacts from a human-readable CSV format into something Google Contacts likes.

The format of the input CSV is as follows (you might as well throw these column headers into your input CSV as well):

First Name,Last Name,Home Email,Work Email,Mobile Phone,Home Phone,Work Phone

The output CSV matches what Google likes.

And here is the script:

# Simple CSV to Gmail Contacts CSV
# by Ian Lotinsky (https://ianlotinsky.com/)
# Released under the MIT License (http://en.wikipedia.org/wiki/MIT_License)

# Run like
#   ruby gmailcsv.rb my_contacts.csv > import_into_gmail.csv

require 'rubygems'
require 'fastercsv'
if ARGV.size != 1
  puts "USAGE: #{__FILE__} <original csv>"
  puts "  First Name,Last Name,Home Email,Work Email,Mobile Phone,Home Phone,Work Phone"
  exit
end

puts "Name,Given Name,Additional Name,Family Name,Yomi Name,Given Name Yomi,Additional Name Yomi,Family Name Yomi,Name Prefix,Name Suffix,Initials,Nickname,Short Name,Maiden Name,Birthday,Gender,Location,Billing Information,Directory Server,Mileage,Occupation,Hobby,Sensitivity,Priority,Subject,Notes,Group Membership,E-mail 1 - Type,E-mail 1 - Value,E-mail 2 - Type,E-mail 2 - Value,Phone 1 - Type,Phone 1 - Value,Phone 2 - Type,Phone 2 - Value,Phone 3 - Type,Phone 3 - Value"

FasterCSV.foreach(ARGV[0], :headers => :first_row) do |row|
  full_name = "#{row.field("First Name")} #{row.field("Last Name")}".strip
  puts "#{full_name},#{row.field("First Name")},,#{row.field("Last Name")},,,,,,,,,,,,,,,,,,,,,,,* My Contacts,* Home,#{row.field("Home Email")},* Work,#{row.field("Work Email")},* Mobile,#{row.field("Mobile Phone")},Home,#{row.field("Home Phone")},Work,#{row.field("Work Phone")},"
end

And because I wanted to be able to sync my contacts between Google and my phone in the future, I tried to write a script to transform a Google Contacts output CSV into a CSV that BitPim likes. But, alas, Google’s export CSV is inconsistent at best, so I wrote a script to go again from human-readable but this time to BitPim CSV:

# Simple CSV to BitPim Contacts CSV
# by Ian Lotinsky (https://ianlotinsky.com/)
# Released under the MIT License (http://en.wikipedia.org/wiki/MIT_License)

# Run like
#   ruby bitpimcsv.rb my_contacts.csv > import_into_bitpim.csv

require 'rubygems'
require 'fastercsv'
if ARGV.size != 1
  puts "USAGE: #{__FILE__} "
  puts "  First Name,Last Name,Home Email,Work Email,Mobile Phone,Home Phone,Work Phone"
  exit
end

puts "names_title,names_first,names_middle,names_last,names_full,names_nickname,numbers_number,numbers_type,numbers_speeddial,numbers_number,numbers_type,numbers_speeddial,numbers_number,numbers_type,numbers_speeddial,emails_email,emails_type,emails_email,emails_type,categories_category"

FasterCSV.foreach(ARGV[0], :headers => :first_row) do |row|
  full_name = "#{row.field("First Name")} #{row.field("Last Name")}".strip
  puts ",#{row.field("First Name")},,#{row.field("Last Name")},#{full_name},,#{row.field("Mobile Phone")},#{"cell" unless row.field("Mobile Phone").nil?},,#{row.field("Home Phone")},#{"home" unless row.field("Home Phone").nil?},,#{row.field("Work Phone")},#{"office" unless row.field("Work Phone").nil?},,#{row.field("Home Email")},,#{row.field("Work Email")},,"
end

And of course, after I got this all working, I remembered that there is a Google Contacts API that I should have tried playing around with.

I hope this saves people from the frustration I experienced and the time I wasted because of bad CSV importers and exporters. If you have an suggestions for improvement, please leave a comment.