Adding “contrib” Extensions to MacPorts PostgreSQL

PostgreSQL is my database of choice. The main reason is that a standard distribution comes with just about everything one could ask for in a free RDBMS, and if what you want isn’t already installed, it’s often in the “contrib” directory. In particular, now that I’m doing a lot of iOS development, and location awareness is a big part of mobile apps, it’s useful to be able to work with coordinates. PostgreSQL does this using the cube data type and earthdistance functions, both in “contrib”. Read More

Automatic Subversion Revision Stamping for iPhone Projects

Early during development of a new iPhone OS application, I discovered that App Store submissions must use a strict format for the CFBundleVersion key in the Info.plist file. It can only be numbers and dots. This left me a little frustrated with how to version pre-1.0 releases to testers. I didn’t want to use an open-source style “0.9” and yet it wasn’t 1.0. What I really wanted was “1.0 b1” or similar.

I stumbled on Daniel Jalkut’s post about automatically stamping the Subversion revision into Info.plist and thought that might be a good way to go. I also created a new key in Info.plist, LYSApplicationDisplayVersion, that I use as a human-friendly version string, which is where I get my preferred “1.0 b1” form. CFBundleVersion now takes the form of major.minor.revision, where major and minor are the important parts of the human-friendly version (“1.0”) and revision is the Subversion revision number that produced the binary.

I like this method because it solves one problem raised by commenters on Daniel’s post. Because the Subversion revision is the third component, it doesn’t matter that r3999 is a mature 1.2 point release and r4000 is a risky pre-2.0 alpha for testers. Those versions end up 1.2.3999 and 2.0.4000 and it’s clear that they are from two different branches of development. For iPhone Ad Hoc distribution, iTunes also parses the version properly and knows that 1.0.100 is newer than 1.0.95.

Here is the script to paste into your custom script build phase:

# Xcode auto-versioning script for Subversion
# by Axel Andersson, modified by Daniel Jalkut to add
# "--revision HEAD" to the svn info line, which allows
# the latest revision to always be used.
 
use strict;
 
die "$0: Must be run from Xcode" unless $ENV{"BUILT_PRODUCTS_DIR"};
 
# Get the current subversion revision number and use it to set the CFBundleVersion value
my $REV = `/usr/bin/svnversion -n ./`;
my $INFO = "$ENV{BUILT_PRODUCTS_DIR}/$ENV{WRAPPER_NAME}/Info.plist";
 
my $version = $REV;
 
# (Match the last group of digits and optional letter M/S/P):
 
# ugly yet functional (barely) regex by Daniel Jalkut:
#$version =~ s/([\d]*:)(\d+[M|S]*).*/$2/;
 
# better yet still functional regex via Kevin "Regex Nerd" Ballard
($version =~ m/(\d+)([MSP]*)$/) && ($version = $1);
 
die "$0: No Subversion revision found" unless $version;
die "$0: Modified, switched or partial working copy, you sure about that?" if $2 && ($ENV{"BUILD_STYLE"} eq "Ad Hoc" || $ENV{"BUILD_STYLE"} eq "App Store");
 
open(FH, "plutil -convert xml1 \"$INFO\" -o - |") or die "$0: $INFO: $!";
my $info = join("", <FH>);
close(FH);
 
$info =~ s/([\t ]+<key>CFBundleVersion<\/key>\n[\t ]+<string>\d+\.\d+).*?(<\/string>)/$1.$version$2/;
 
open(FH, "| plutil -convert binary1 - -o \"$INFO\"") or die "$0: $INFO: $!";
print FH $info;
close(FH);

There are a couple of other changes to this script for Subversion 1.5 and later, and for iPhone OS targets.

The first is that the regular expression allows for a trailing P in the Subversion revision. This signals a working copy from a sparse checkout, which I never use and therefore may be a problem. I have the script fail if any letter is appended to the revision when the BUILD_STYLE is “Ad Hoc” or “App Store”, which are two new configurations, cloned from Release, that I use for Ad Hoc and App Store distribution, respectively. Especially for modified working copies: I never want to accidentally hand out a build made from a modified working copy. Should the day come that I really do, I can comment this line out, make the build, and uncomment it again.

The second is that iPhone projects convert Info.plist to the binary plist format in the application bundle. In order to extract the existing CFBundleVersion key, it must be converted back to XML. When writing the plist back out, it is again converted to binary. Both of these steps use plutil, which is part of the Developer Tools.

Ruby, Threads and RubyCocoa

If you’re a Rails developer working on Mac OS X 10.6, you may have seen this message:

Ruby threads cannot be used in RubyCocoa without patches to the Ruby interpreter

It is caused by a plug-in or gem requiring osx/cocoa, frequently attachment_fu. AttachmentFu can use CoreImage as an image processor instead of calling out to an image manipulation library such as ImageMagick or GD2.

The warning is harmless, but it can be very noisy. To disable it, you can simply remove CoreImage from AttachmentFu’s list of image processors by creating a new file in config/initializers. Its contents should be this one line:

Technoweenie::AttachmentFu.default_processors.delete('CoreImage')

Image resize operations will now use one of the other image processors, which you can install from MacPorts. I never deploy to a Mac OS X server for production, and I prefer to run as much of the same code as possible in development, so this isn’t a problem for me.

Remember HTTP Password in Mobile Safari

In iPhone OS 3.0, Apple allowed Mobile Safari to save usernames and passwords in web forms. Unfortunately, Safari does not offer to do the same thing for HTTP Basic and Digest authentication. I’ve become fond of using HTTP authentication because it is very easy to set up, either in your Apache virtual host configuration or within a Rails application. There are many times that a full-fledged user database is unnecessary for a simple administration back-end.

There is a work-around, though it does mean storing your user and password in plaintext in your device’s bookmarks. HTTP allows you to supply authentication credentials as part of the URL, in the form http://username:password@example.com/.

Use content_for to Put Markup In Its Place

Here is a useful trick for ensuring that you keep your partial templates well organized without sacrificing page-load times or duplicating your layouts unnecessarily.

You can use content_for to capture some markup, but have it emitted into the page from somewhere else.

Two places this is immediately useful: adding additional tags inside <head> and placing in-line Javascript near </body>, while keeping the code itself right next to the DOM elements it works upon.

content_for works by capturing whatever appears inside the block and storing it for later use. You emit whatever is stored using yield. What’s more, content_for doesn’t clobber the previous captured text if you use it more than once with the same key.

Say you have a fancy Javascript control that replaces a standard <select> element in forms. You can do this in your partials:

<select ...>
  <option>...</option>
  <option>...</option>
  ...
</select>
<% content_for :body_close do %>
  <script type="text/javascript">
    // code that does something with that <select>
  </script>
<% end >

And then in your layout, just before the </body>:

<%= yield :body_close %>

Because most browsers will run in-line Javascript upon encountering it, this would delay the execution of the code until all of the page content was loaded, making your page appear to load faster.

What’s more, if that fancy Javascript control also requires a CSS file, but you don’t want to require the browser to fetch it on all of the other pages that don’t need it, you can conditionally add it to <head> by defining another content_for key that accumulates additional markup to go there:

<% content_for :head do %>
  <%= stylesheet_link_tag 'fancy_control' %>
<% end %>

And in your layout:

<head>
  ...
  <%= yield :head %>
</head>

This is also useful for keeping per-page markup like <title> and meta tags in the template and out of your controller.

IE + Rails Javascript Caching Gotcha

Rails supports a simple method of asset bundling with javascript_include_tag by way of the :cache option:

<%= javascript_include_tag 'first', 'second', 'third', :cache => true %>

There’s a gotcha hiding here that you may not find until you deploy to production and visit your site in IE.

Admittedly, this is a bug, but if you happen to have a second javascript_include_tag with the :cache argument in the same page, IE will choke on lots of the script, telling you “object doesn’t support this property or method,” among other things.

The problem is that Rails can’t resolve multiple tags using the same value for :cache, and it emits two <script> tags referencing the same Javascript file. IE gets confused by the second one (perhaps loading it twice?). Every other browser I’ve used handles it fine.

The solution: either don’t use :cache more than once or make sure you use explicit, unique bundle names instead of just true.

Xcode User Defaults

Xcode as a development environment matches my working style fairly well, but there are two things about it that have bothered me. The first is a warning when I try to undo edits across a file save event. Since I have Xcode set up to save all files before a build, this happens often when I try an experiment and don’t like it.

The second is code completion for language constructs such as if statements. Xcode wants to do this:

if (condition) {
}

While I used this style a long time ago, today I want the opening brace on its own line:

if (condition)
{
}

No amount of digging in the preferences will provide a way to change these behaviors, however there is a lot of customizability hidden in the Xcode User Defaults. My two issues are solved quite easily:

$ defaults write com.apple.Xcode XCShowUndoPastSaveWarning NO
$ defaults write com.apple.Xcode XCCodeSenseFormattingOptions -dict BlockSeparator "\n"
What Happened to Programming

Last week, Mike Taylor posed the question “whatever happened to programming?” (also see his followup). I think part of the answer is simply “it’s grown up.”

Programming, either as a hobby or a career, has only been around for a little less than 70 years. (The first was the Colossus, built and used by the British during World War II to read encrypted German messages.) This is very young when compared to other scientific fields: agriculture, construction, various engineering disciplines, etc.

I won’t disagree that building the very fundamental parts of a new application from scratch can be very enjoyable. Perhaps not printf(3), but certainly other parts. The problem is bug rates, though: any seasoned software developer knows that writing less code means less bugs. If high-quality libraries are available that provide 80% of the functionality of your new application, you will likely end up with a better product, in less time, than if you chose to write the entire thing yourself.

Consider the sorry state we’d be in if:

All farmers experimented with their own methods of weed and pest control (organic or not), instead of using techniques proven to work in the past. Our agriculture industry probably couldn’t meet the population’s demand for food.

Architects and builders “winged it” when building new homes and office buildings. Bugs in that industry would likely mean structural failure. Who would want to live in those houses?

How about automakers? It’s one thing to build a kit car as a hobby, it’s quite another to tinker with your designs when you’re producing cars on a massive scale for general use (just ask Toyota).

It may not be as glamorous, but if our collective bug count goes down and the software industry ships better products that don’t require constant patching, I can’t help but consider this a very good thing.

Bash Substitutes for “seq” and Simple “sed” Expressions

There are two things I find myself doing from the shell just infrequently enough that I can’t remember the exact syntax. The first is generating a sequence and the second is repeated string transformation.

“seq” is a little GNU utility that generates sequences of numbers. I used to find this installed automatically by many Linux distributions, but lately (on Debian and Ubuntu, at least) it’s missing and I haven’t been sufficiently motivated to find it. No need: Bash has something good enough built in.

To generate the numbers from 1 to 10, inclusive:

$ echo {1..10}
1 2 3 4 5 6 7 8 9 10

The second thing is repeated string transformations, for example renaming a set of files to use a different file extension. This used to mean re-reading the sed(1) man page yet again and doing the transformation in a backtick expression. Again, no need: Bash can do this itself:

$ for f in a.foo b.foo c.foo; do echo $f ${f/%foo/bar}; done
a.foo a.bar
b.foo b.bar
c.foo c.bar

The syntax is ${parameter/pattern/replacement}. pattern only replaces the first match, unless it starts with /, in which case it replaces all matches. It can also start with # to force a match at the beginning of the string or % to match at the end.

Take a look at “Parameter Expansion” in the Bash manual for several other useful operations.

On the Pain of Developing for Facebook

I’m in the last stages of building a site that integrates with Facebook. It includes a Facebook Connect component and a separate Facebook iframe application. In the hopes that some of my experience will help someone else out there, I will share some of my suffering and how I worked through it.

This is a Rails 2.3 application, using the Facebooker gem, version 1.0.54.

Safari, iframes, and cookies.

Chances are high you’ve found this page via search, and that you are desperate to find a solution to allow your Rails sessions to carry over from page #1 of your iframe application to page #2 and beyond. Will Henderson has a solution when your Rails application uses the ActiveRecord session store, but new Rails applications use the cookie store. There is no session to retrieve from the database; passing a row ID with links doesn’t help.

I am fortunate that my iframe application has a splash screen, with only one useful link on it, to start the “real” application. I append every fb_sig parameter from the current request to the link. Once the user clicks that link, the iframe no longer falls under Safari’s 3rd party cookie policy, and so the next page can set cookies. Because all of the fb_sig parameters are there, Facebooker gives precedence to them, recreating the Facebook session without consulting cookies (which either don’t exist or are stale).

<%= link_to 'Start the app', params.merge(:action => :app) %>

Now, your app doesn’t always get these. When the application is first installed, you won’t get the fb_sig parameters. In this case, I force a redirect:

unless params[:fb_sig_ss]
  redirect_to "http://#{Facebooker.canvas_server_base}/#{Facebooker.facebooker_config['canvas_page_name']}/"
  return
end

However…

Facebooker’s Rack middleware trashes your params.

Facebooker includes a piece of Rack middleware that automatically validates the signature on fb_sig parameters, and aborts the request if the signature isn’t valid. This works great on the initial request, but fails on the second request, with exactly the same parameters.

The culprit is near the bottom of Facebook#call, in rack/facebook.rb, where it calls convert_parameters!. This method is trying to be helpful, turning things like Unix time_t into Ruby Time instances. If you are trying to pass these parameters along in a link, Time.to_s is not a Unix time_t, and so the signature validation will fail, and you’re screwed.

Pre-Rails 2.3, there is no Rack middleware, and signature validation happens in another part of the Facebooker gem, which does not trash the original params. It does the same conversion, but on a copy. As near as I can tell, calling convert_parameters! is unnecessary, and commenting it out solves my problem. When Safari loads page #2, Facebooker creates its session, which can be stored in the Rails session, using the cookie store.

Reconstituting a Facebook session in Flash.

The bulk of this iframe application is actually written in Flash. Every Facebook application has an App ID (essentially a public key) and a secret key. The secret key must never be allowed outside your organization or people can fake API requests from your application. Embedding your secret key in a Flash SWF is therefore not an option, because a SWF can be decompiled. Facebook’s solution to this is the session secret, passed as fb_sig_ss.

According to Adobe’s ActionScript 3.0 Client Library for Facebook API reference, one can use the FacebookSessionUtil class to recreate a session using only the public key and the session secret. This is not true. I have to pass in all of the fb_sig parameters to Flash in order to make it work. However you start your Flash content, FlashVars must include:

<%= params.collect { |k,v| "#{k}=#{v}" if k.starts_with?("fb_sig")}.compact.join("&") %>

A refreshed page lags a “logged-in” state change until refreshed a second time.

When a user logs out of Facebook and refreshes your Facebook Connect web site, it doesn’t reflect the user’s “logged-in” state change until another refresh. You can automate this and have the page refresh itself when necessary:

<% init_fb_connect 'XFBML', :app_settings => '{"reloadIfSessionStateChanged":true}' do %>
  FB.ensureInit(function() {
    FB.Connect.get_status().waitUntilReady(function(status) {
      switch (status) {
        case FB.ConnectState.connected:
          $$('.fbConnectLoggedIn').invoke('show');
          $$('.fbConnectLoggedOut').invoke('hide');
          break;
        case FB.ConnectState.appNotAuthorized:
        case FB.ConnectState.userNotLoggedIn:
          $$('.fbConnectLoggedIn').invoke('hide');
          $$('.fbConnectLoggedOut').invoke('show');
          break;
      }
    });
  });
<% end %>

There are actually two parts to this trick. First, :app_settings => '{"reloadIfSessionStateChanged":true}' triggers the automatic refresh.

Second, if you have some common part of your layout that switches on a user’s Facebook status, this precludes your use of page caching. For an otherwise static page, this is a real sacrifice. To work around this, I include both sets of mark-up, classed with either “fbConnectLoggedIn” or “fbConnectLoggedOut”, and invoke Prototype’s show() or hide() on them as part of the Facebook Connect initialization. As long as you are careful to use XFBML tags that don’t require actual values from a Facebook session (e.g. <fb:name uid="loggedinuser" ...>), this works very well.