Quick Look preview from the command line

September 10th, 2008

(This post is only for Mac folks, and only the ones that spend time in the terminal at that. Everyone else can safely ignore this.)

As you may already know, you can open a file from the command line using the “open” command. The file will be opened using the default application for the file type. For example, running “open spreadsheet.xls” will open that file in Numbers or Excel, and running “open” on a directory will open that directory in a new Finder window. Think of it as a double click from the command line.

However, while working in the terminal today, I found myself wanting to open a spreadsheet using Quick Look just to get a single value. There’s a command called “qlmanage” that allows you to open the Quick Look preview of a file using the -p option. To make it more convenient, I created a short executable shell script called “ql” and put it in a directory that’s in my $PATH:


#!/bin/sh

# Display the Quick Look preview for the given file.

if [ -z "$1" ] ; then
  echo "Usage: ql ”
  exit 1
fi

exec qlmanage -p $1 2> /dev/null

Now I can preview a spreadsheet (or any file) from the command line using “ql spreadsheet.xls”. To close the preview, just hit Ctrl-C.


Giving from the top

August 1st, 2008

1% For The Planet is a group of companies that have pledged to donate 1% of their annual sales to nonprofit environmental organizations. By donating a fixed portion of their “top line”, these companies are committed to giving through thick and thin.

They’ve just released a new promotional video that they’re showing during Jack Johnson’s world tour. I love Tyler Stableford’s photography, and the soundtrack is great too (Matt Costa):


Since our first day in business, West Arete Computing has been proud to be a member of 1% For The Planet (we’re member #97). It’s great knowing that every project that we’ve ever worked on has resulted in more funding for some of our favorite nonprofit environmental organizations.

It’s been a privilege knowing the people at 1% For The Planet for the past few years. You’ll never find a more driven, energetic, fascinating group of people. It’s been thrilling to watch how much the movement has taken off recently — there are more than 900 member companies now.

Keep your eye out for the 1% For The Planet logo. I keep on finding it in places that I didn’t expect. It’s great to see it on things that you’ve been buying for years.

It’s also great to go to work each day knowing that part of that effort goes towards keeping central Pennsylvania beautiful.

1% For The Planet logo


Stratamodel in Niger

February 16th, 2008

Tom Bell of Stratamodel is an exploration geologist. He travels around the world looking for valuable minerals. He’s just wrapping up a several-week expedition to the desert in Niger to look for uranium. This guy has an incredible job.

Tom gave me a ring a few days before leaving for his trip to see if we could put together a quick program for his laptop. He had a set of barometers/thermometers that connected to the USB port on his Windows laptop, and he wanted us to write some software to read the data from the devices and record it. He also wanted to ensure that it could all run unattended, and that it would maximize battery life. We also had to be 100% sure that the program would work properly, since he would hardly have any outside contact once he entered the desert.

Using the specifications from the manufacturer, we put together a Ruby program to talk to the devices and record the data (we used the ruby-serialport gem, if you’re wondering how). Getting the timing right with the devices was the only tricky part — they were very picky about how much time elapsed between sending and receiving each character, and between sending a command and retrieving the response.

To save power, we set up the code and data on a flash drive so it wouldn’t use the hard drive. We then set up a power scheme that would keep the computer running, but would shut down the hard drive, display, and allow the machine to keep running with the lid closed (essential for keeping out dust and sand).

All in all, we had everything developed, tested, and installed in about 24 hours.

After hearing about what his trip was going to entail, we also set up a blog for him to write about his experiences. He’s been writing some great stories and taking a lot of amazing pictures. I’m really struck by how similar some of the desert pictures are to the ones from the Mars rovers!

I highly recommend checking out the Stratamodel blog. Also be sure to check out the Stratamodel photo stream on flickr. Great material. Have a great trip Tom!


Exploring Ruby class methods

February 15th, 2008

I decided that I needed to learn more about all the different ways to declare and use Ruby class methods, so I wrote a 10-line example script to try a couple things out. Two hours later, it had expanded to almost 300 lines (including lots of comments) as I tried to demonstrate and explain every way that I could think of to declare and use class methods.

Take a look, download the code, open it in your editor, and run it (Apple-R in TextMate). Mess around with it.

Did I miss anything? Did I get anything wrong? Post your comments and questions in the comments below.


Anti-specs: Using RSpec to document the bad in addition to the good

December 13th, 2007

Sometimes we purposely write code that has bugs that we don’t intend to fix.

I know that sounds terrible, but consider the following example. We were recently writing a class to parse a known set of data that didn’t include any whitespace between tokens. Our one-time class worked great for this particular data set, and we didn’t anticipate having to use it on another data set. However, if you were to pass it similar data that did have whitespace between tokens, then you wouldn’t get the desired output.

We could have spent a bunch of time expanding the class to handle whitespace properly, but we quickly realized that this would have doubled the development time for the class, all for adding a feature that we weren’t going to use.

Instead, we added some anti-specs for the class that documented the undesirable behavior:


  describe "Unfortunately, #quote_nodes" do
    it "will preserve whitespace around each node" do
      quote_nodes(" snap , crackle ,( pop )").should == "' snap ',' crackle ',(' pop ')"
    end

    it "will quote whitespace as a node if it appears between delimiters" do
      quote_nodes(" , , ( ) ").should == "' ',' ',' '(' ')' '"
    end
  end

Note how instead of the usual RSpec phrasing, e.g. “#quote_nodes … should put single quotes around each node”, we start the context with “Unfortunately” to immediately tell the reader that this is undesirable behavior, and we use the word “will” instead of “should” to tell you that this isn’t what we would want in an ideal world, but it’s what we’re getting anyway. You wind up with spec docs that clearly document the good and the bad:


#quote_nodes:
- should put single quotes around each node
- should quote nested nodes too
- should only treat parentheses and commas as delimiters
- should preserve whitespace within nodes

Unfortunately, #quote_nodes:
- will preserve whitespace around each node
- will quote whitespace as a node if it's between delimiters

Down the road, we may wind up re-using this code in another application. If we need to fix the bad behavior, we can simply modify the specs to document the new desired behavior, and then add the additional code to properly handle whitespace and make the tests pass.

I didn’t see anyone else writing about this use of RSpec, but we’ve found it to be useful for these somewhat rare cases.

There’s no reason why you couldn’t do this with Test::Unit and have “anti-tests”, but I particuarly like the phrasing that you get to use with a BDD framework such as RSpec or shoulda.


Copying a large amount of data between disks

November 12th, 2007

We upgraded the disks on our backup server to create some much-needed space. When the new drive arrived, I had to reformat it and copy the entire contents of the old backup disk to the new one. I needed a way to transfer 250GB of small files, while preserving permissions and hard links. I tried three different methods of copying the data before finally succeeding.

This is on a Xen virtual server and memory is somewhat limited (256MB). Both rsync and restore took *way* too much memory. Rsync would have required many gigabytes of memory, and restore required at least a couple. Restore also required a large amount of temporary disk space (a couple gigabytes) for storing permissions and mode information. In the end, the good old tar command was the highest-performance method, consuming about 150MB of memory at its peak for the restore. The bash command line was:


  (cd /data && tar -c -p -f - .) | (cd /data2 && tar -x -p -f -)

Tar is dependent on the current directory for its context, so I used a subshell around each command to ensure that they were in the right directory. I could have used semicolons to separate the “cd” command from the “tar” command in each subshell, but then the “tar” would have proceeded whether or not the “cd” was successful (for example if I had made a typo in the directory name). This would be bad since a failed “cd” before a tar restore could result in all of those files being written and potentially intermingled with the wrong filesystem. Using “&&” to separate the commands ensures that the tar command only proceeds if the “cd” was successful.


New rails plugin: validate_request

July 26th, 2006

One thing that bothered me when I started using rails was that there wasn’t a built-in way to verify that your actions are getting the correct arguments. For example, in this typical action:


  def show
    @dog = Dog.find(params[:id])
  end

an exception is raised if the “id” parameter is omitted (e.g. /dog/show rather than /dog/show/5), and you get a rails application error by default. It seemed like there should be a way to declare that this action requires an “id” parameter of type integer, and provide a graceful way to recover if that constraint isn’t met.

Read the rest of this entry »


Deploying Mongrel behind Apache 2.0

July 25th, 2006

Most of the documentation and writings for mongrel require setting up mongrel with apache 2.2, so that you get the benefit of the mod_balanced_proxy module. However there are an awful lot of production machines out there running apache 2.0.

For small installations, it turns out that it can be quite sufficient to run a single mongrel daemon behind Apache 2.0 and plain old mod_proxy, all on one machine. No, you won’t get high concurrency, and you won’t be able to load balance across machines, but it’s an incredibly simple, stable setup that can have your rails app up and running without mucking around with upgrading your web server or installing foreign RPMs.

Read the rest of this entry »