Moving my iPhone to a new Macbook

December 29th, 2008

I don’t know if I got lucky, but I was just able to sync my iPhone with my new Macbook Pro with no warnings whatsoever about transferring purchases or making a copy of the iPhone’s backup directory and doing a full restore. iTunes simply copied a couple of new apps I had purchased on the iPhone over to my Macbook and it said “Sync Complete.” That’s it!

I have had a couple different iPods in the past and each time I moved one to a new computer I had to wipe it out and start over. I was expecting/dreading to do the same here. The only thing I did which I hadn’t done in the past was to copy the entire ~/Music/iTunes directory from my old Macbook to the new one before connecting the iPhone. Starting up iTunes after that showed all my original playlists just as they were on the old notebook. I plugged in the iPhone and only received one notice asking if I wanted to share diagnostic information with Apple (I said yes). So this was definitely the first time this copy of iTunes had seen this iPhone, but everything worked out okay.

Site redesign and new engine

December 28th, 2008

All two of my regular readers may have noticed a pretty big change on Friday—a complete redesign of the site! I went back to my typographic roots and was heavily inspired by The Elements of Typographic Style by Robert Bringhurst. Highly recommended as a great overview and history of typography and the written/printed word in general. The site looks best in Adobe Caslon Pro but you’re probably seeing it in Georgia. Not ideal, but better than Arial.

A change you probably didn’t notice was my switch from Mephisto to Jekyll as my blogging engine. Jekyll was written by my friend Tom in Ruby. It’s very different than your normal blogging engine—there’s no admin, no templates and it’s not a hosted solution. You create your posts as individual files, optionally marked up with Textile or Markdown, and point an executable at them. It takes those files, formats them and outputs your site as static html files. Upload these to your server and you’re done! Jekyll has no concept of comments (yet) so I plugged in the simple comment system by Disqus.

I’ve got a handy little script that builds the site with Jekyll and then publishes to my server via rsync, all in one short command called rtc. Add something like the following to your .bash_profile (pretend it’s all on one line). These options will make more sense once you take a look at the Jekyll readme):

alias rtc="echo 'Building...' && ~/Sites/rtc/jekyll/bin/jekyll \
--pygments ~/Sites/rtc/raw ~/Sites/rtc/site && echo 'Pushing...' \
&& rsync -avz --delete ~/Sites/rtc/site/ rob@myserver.com:/var/www/rtc/"

I’m still working on the design, but it’s a start.

Client Side Includes via Javascript

October 21st, 2008

Lots of the little prototype and sample sites I create at work are not backed by an app server—they’re just a series of html/CSS/JS files that show, for example, how a text field should swap to an editable state when clicked on.

The problem is that I lose the benefit of including common parts of the page via something like Rails’s render method. You want to include the same header across all of your pages, but if you copy/paste that header into five different templates, then have to make one small change…you get the idea.

The other day I thought about the old server side include technology that most web servers support. I wanted to do something similar, but on the client side. I assumed that a standard Ajax call via XMLHTTPRequest wouldn’t work from the local file system (since it actually uses http to get your file) but turns out it works just fine! Found a snippet online and modified a bit:

function include(url,id) {
  var req = false;
  // For Safari, Firefox, and other non-MS browsers
  if (window.XMLHttpRequest) {
    try {
      req = new XMLHttpRequest();
    } catch (e) {
      req = false;
    }
  } else if (window.ActiveXObject) {
    // For Internet Explorer on Windows
    try {
      req = new ActiveXObject("Msxml2.XMLHTTP");
    } catch (e) {
      try {
        req = new ActiveXObject("Microsoft.XMLHTTP");
      } catch (e) {
        req = false;
      }
    }
  }
  if (req) {
    // send out the response
    req.open('GET', url, false); req.send(null);
    // if the optional 'id' element is present, insert returned text into it, otherwise write to the page wherever it was called
    document.getElementById(id) ? document.getElementById(id).innerHTML = req.responseText : document.write(req.responseText);
  } else {
    document.write('This browser does not support XMLHTTPRequest objects which are required for this page to work');
  }
}

Stick that in your <head> and then to include another file somewhere just make a call like so:

<script type="text/javascript">include('header.html')</script>

By default this will write the included file wherever you put the include call. If you want to target it to a specific element just pass that element’s id as a second parameter:

<div id="header_container"></div>
<script type="text/javascript">include('header.html','header_container')</script>

Make sure the call to include() goes after you have created the element that’s going to contain it, as above, otherwise the element won’t exist in the dom yet and nothing will happen.

Want to use Prototype to access something in an iframe?

October 9th, 2008

At work I’m putting together a prototype that lets you live-preview style changes on a webpage (similar to Wufoo’s Theme Builder). I wanted to split a page and have your styles/themes in the top half and a preview of the site in the bottom half. Rather than try to recreate the entire site in a special “preview” mode I wanted to just show the actual site and use Javascript to change styles on the fly. A good ol’ iframe to the rescue!

You can target a document in an iframe and access it’s DOM assuming that both the container page and iframed page are both coming from the same domain. Otherwise you’ve got a security problem. The problem is that, by default, the awesome Prototype library can’t access anything in the iframe (at least not by using the familiar, standard Prototype syntax like $()).

After a little searching I found a code snippet someone put online in Prototype’s Google Group page and it works great! It adds the $() method to iframe Elements so they can call $() on themselves and search inside for a matching object (iframes respond to a call to the .contentWindow property [returns the file that’s loaded in the iframe] which is how this code determines what Elements on the page are iframes).

To implement simply include this code somewhere after your prototype.js include:

Element.addMethods('iframe', {
document: function(element) {
  element = $(element);
  if (element.contentWindow)
      return element.contentWindow.document;
  else if (element.contentDocument)
      return element.contentDocument;
  else
      return null;
},
$: function(element, frameElement) { 
  element = $(element);
  var frameDocument = element.document();
  if (arguments.length > 2) {
      for (var i = 1, frameElements = [], length = arguments.length; i < length; i++)
          frameElements.push(element.$(arguments[i]));
      return frameElements;
  }
  if (Object.isString(frameElement))
      frameElement = frameDocument.getElementById(frameElement);
  return frameElement || element;
}
});

And let’s say your page looks something like:

-- index.html
<html>
...
<iframe id="my_frame" src="contents.html" />
...
</html>

-- contents.html
<html>
...
<h1 id="logo">Hello World Industries</h1>
...
</html>

And the usage is thusly (this goes in index.html):

var iframe = $('my_frame');
var the_logo = iframe.$('logo');

Now the_logo contains a standard Prototype Element for the logo inside the iframe!

Bonus Need to target the body itself?

var iframe = $('my_frame');
var iframe_body = iframe.document().body;
iframe_body.setStyle({backgroundColor:'#990000'});   // set the background to dark red

Convert a MySQL database to a SQLite3 database

October 8th, 2008

I wanted to convert a MySQL database to a SQLite3 database the other day. I did some searching and found a good script on the SQLite3 site . It didn’t quite work for me, but it was close (left a bunch of random MySQL “set” statements everywhere and used MySQL’s default multiple insert syntax). After some tweaking I got it to create the file without errors. Here’s my version for anyone that needs to do the same thing (requires mysqldump and perl be installed on your system):

#!/bin/sh

if [ "x$1" == "x" ]; then
  echo "Usage: $0 &lt;dbname&gt;" 
  exit
fi

if [ -e "$1.db" ]; then
  echo "$1.db already exists.  I will overwrite it in 15 seconds if you do not press CTRL-C." 
  COUNT=15
  while [ $COUNT -gt 0 ]; do
    echo "$COUNT" 
    sleep 1
    COUNT=$((COUNT - 1))
  done
  rm $1.db
fi

/usr/local/mysql/bin/mysqldump -u root --compact --compatible=ansi --default-character-set=binary --extended-insert=false $1 |
grep -v ' KEY "' |
grep -v ' UNIQUE KEY "' |
grep -v ' PRIMARY KEY ' |
sed 's/^SET.*;//g' |
sed 's/ UNSIGNED / /g' |
sed 's/ auto_increment/ primary key autoincrement/g' |
sed 's/ smallint([0-9]*) / integer /g' |
sed 's/ tinyint([0-9]*) / integer /g' |
sed 's/ int([0-9]*) / integer /g' |
sed 's/ enum([^)]*) / varchar(255) /g' |
sed 's/ on update [^,]*//g' |
sed "s/\\\'/''/g" |                                                                                    # convert MySQL escaped apostrophes to SQLite   \' =&gt; ''
sed 's/\\\"/"/g' |                                                                                    # convert escaped double quotes into regular quotes
sed 's/\\\n/\n/g' |
sed 's/\\r//g' |
perl -e 'local $/;$_=&lt;&gt;;s/,\n\)/\n\)/gs;print "begin;\n";print;print "commit;\n"' |
perl -pe '
if (/^(INSERT.+?)\(/) {
  $a=$1;
  s/\\'\''/'\'\''/g;
  s/\\n/\n/g;
  s/\),\(/\);\n$a\(/g;
}
' &gt; $1.sql
cat $1.sql | sqlite3 $1.sqlite3 &gt; $1.err
ERRORS=`cat $1.err | wc -l`
if [ $ERRORS == 0 ]; then
  echo "Conversion completed without error. Output file: $1.sqlite3" 
  rm $1.sql
  rm $1.err
else
  echo "There were errors during conversion.  Please review $1.err and $1.sql for details." 
fi

Update, 11/3/08 Updated the script above. Fixed a couple issues with newlines and lowercasing everything also lowercased the actual values in the tables! For some reason I had convinced myself it was only lowercasing the table and column names… There is still an issue where apostrophes are turned into weird characters, seemingly UTF-8. This might just be a simple matter of telling mysqldump to use latin instead of utf-8 encoding? I haven’t played around with it, but if anyone figures it out please let me know.

Wedding and Honeymoon Photos

October 8th, 2008

Well, streaming the ceremony didn’t quite work. We couldn’t really get an internet connection on the beach so we had to fall back to Plan B—just get married the old fashioned way. But we did get plenty of photos!

Wedding
(These are the few taken with my iPhone during the ceremony, I’ll have the official ones from the photographer up soon.)

Honeymoon in Maui
(We took about 1,500 photos between the two of us! Don’t worry, these are just the highlights.)

I'm getting married today!

September 27th, 2008

Yep, I’m getting married today! Aimee DePietro is my bride and we’re in love. We first met in January of last year (thanks Match.com!) and things just keep getting better and better.

We’re going to try and stream the wedding from the beach at 5:30pm pacific time. If you want to come and watch live on UStream.tv

If there’s no wi-fi (the beach is fairly close to the hotel) then we have a backup plan. My best man (Tom Werner of github fame) has an aircard for his laptop and we’ll use that instead. Not sure how great the quality will be, but better than nothing!

Wish us luck!

Aimee and Rob

What did I work on this week? A script for Adobe Bridge

September 15th, 2008

At my job I have a regular Friday review of everything I’ve worked on for the past week. Friday afternoon I print out a couple copies of all my Photoshop comps and meet with the bigwigs.

Adobe Bridge is a very quick way to preview images, view metadata, add keywords, etc. Bridge has the concept of a “collection” which is basically a smart filter. You do a find, filter the images you want to see, then save that filter for use later. Last Friday I created a filter to show me all the Photoshop files that had been modified on or after that Monday. Perfect—this is exactly what I worked on this week. But what happens next Friday? I need to delete the existing collection and recreate it. Seems like there should be an easier way…

Bridge saves the collection as a file in whatever directory you’d like. I opened that file in a text editor in the hopes it was just a simple list of plain text attributes. I was in luck:

<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
<collection version='200' target='bridge%3Afs%3Afile%3A%2F%2F%2FUsers%2Frob%2FDocuments%2FWork' specification='version%3D2%26conjunction%3Dand%26field1%3Dmimetype%26op1%3Dequals%26value1%3Dapplication%2Fphotoshop%26field2%3Ddatemodified%26op2%3DgreaterThanOrEqual%26value2%3D2008-09-08%26scope1%3Drecursive%26scope2%3DincludeNonIndexed'></collection>

Just a simple xml doc that lists the filters, awesome! Now just replace the date and I’m good to go. Sounds like a job for cron cron will periodically run a task and do “something” on your system. In my case I want to recreate that xml every Monday morning, setting the date to that day, and saving back to the collection file. A little research and here’s how to output the date in the format this xml file needs:

date +%Y-%m-%d

Now I just need a script file that puts that date into the xml and writes the result out to a text file. That looks like:

#!/bin/bash
echo "<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>\
<collection version='200' target='bridge%3Afs%3Afile%3A%2F%2F%2FUsers%2Frob%2FDocuments%2FWork' specification='version%3D2%26conjunction%3Dand%26field1%3Dmimetype%26op1%3Dequals%26value1%3Dapplication%2Fphotoshop%26field2%3Ddatemodified%26op2%3DgreaterThanOrEqual%26value2%3D$(date +%Y-%m-%d)%26scope1%3Drecursive%26scope2%3DincludeNonIndexed'></collection>" > /Users/rob/Documents/Work/This\ Week.collection

The first line tells the system to run this in the bash shell. The second line takes the text and writes it to the terminal. Note that the date command near the end is surrounded with $() so that it runs inline and returns the result. The very end of that line looks like this:

> /Users/rob/Documents/Work/This\ Week.collection

This takes the string that was just output to the terminal and puts it into a file named “This Week.collection” in the same directory as the rest of my comps (overwriting any file with the same name). I save the script in my home directory.

The last step is to run this script every Monday. I add a new line to my crontab:

30    12    *    *    1    rob    /Users/rob/bridge_collection.sh

This says to run the script I just created at 12:30, every Monday of the week. I’m running it in the middle of the day to make sure that I’m here and the computer isn’t sleeping. Done! Now I can keep track of everything I’ve worked on during the week with one click in Bridge.

Weird ruby error - undefined method 'require_gem'

September 2nd, 2008

Really just posting this for future Googling of this error. (Just jump to the last two paragraphs if all you care about is my solution and not any of these symptoms.)

I was working on a new app (more on that soon) and getting ready to push to my production server. When I tried to load the database schema to get it ready I got the following error:

/usr/local/bin/rake:17: undefined method `require_gem' for main:Object (NoMethodError)

I figured that deep inside the massive stack of what whatever files rake was including there was some esoteric error, probably dude to different gem versions. The production server had an older version of gem so I updated that. No go. Checked the rake gem and both production and development had the same version (0.8.1). Searched online and there were other people listing this error, but no solution that helped me.

This morning I figured I would just manually create the database and see if the app worked, and it did. Not ideal, but it worked. Now came them time to start the application (two instances of mongrel balanced by Apache) and damn it, the same error! Only this time it was in the mongrel_rails executable:

/usr/local/bin/mongrel_rails:17: undefined method `require_gem' for main:Object (NoMethodError)

What the hell?? So I looked at the mongrel_rails executable:

#!/usr/local/bin/ruby
#
# This file was generated by RubyGems.
#
# The application 'mongrel' is installed as part of a gem, and
# this file is here to facilitate running it. 
#

require 'rubygems'
version = "&gt; 0" 
if ARGV.size &gt; 0 &#38;&#38; ARGV[0][0]==95 &#38;&#38; ARGV[0][-1]==95
  if Gem::Version.correct?(ARGV[0][1..-2])
    version = ARGV[0][1..-2] 
    ARGV.shift
  end
end
require_gem 'mongrel', version
load 'mongrel_rails' 

Sure enough, line 17 has the require_gem method call. What does that same file look like on development?

#!/usr/local/bin/ruby
#
# This file was generated by RubyGems.
#
# The application 'mongrel' is installed as part of a gem, and
# this file is here to facilitate running it.
#

require 'rubygems'

version = "&gt;= 0" 

if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
  version = $1
  ARGV.shift
end

gem 'mongrel', version
load 'mongrel_rails'

Pretty different. Checked on mongrel versions and the production server had an older one (1.0.1 versus 1.1.4). So I sudo gem update mongrel and I’m back in business—my app loads. But I still couldn’t rake my database to life…

I go back and look at the source of /usr/local/bin/rake and sure enough it’s different on my dev machine and production (pretty much the same differences as the mongrel_rails script). But rake is already up-to-date…what gives? Maybe there’s some secret gem command to update the script for rake, but I don’t know it. I just copied the rake executable from dev to production and everything was perfect! rake db:schema:load RAILS_ENV=production ran like a charm.

No idea why these scripts changed (maybe when rubygems 1.0 was released?) and why there was no process to update these scripts that depended on them…if anyone knows, please leave a comment and share!

Launch! Alfred - A Rails app for monitoring other Rails apps

June 19th, 2008

I finally made Alfred official! In my current position as UI Architect I’m always putting together little HTML or dynamic prototypes and mockups. For me the quickest way to do this has been with Rails. As I started getting three, four, five apps that I needed to keep running in order for others in the company to play with, I found that starting and stopping these apps (and keep tracking of which port they were running on, whether they were already running, etc.) got to be a huge chore.

So I wrote on more Rails app called Alfred. Alfred (named after Batman’s faithful butler) watches over your Rails apps, let’s you know if they’re running or not, and gives you one central place to start, restart and stop them. It’s been very handy at work and I couldn’t live without it now.

Alfred screenshot

It still needs quite a bit of work (it has no idea what to do in the case of an error with your app or how to gracefully recover from it) but that’s coming soon enough! I also plan on adding a public view so that you can give out the link to others if they want to check out one of your prototypes, but don’t want them having access to start/stop, new project creation, etc.

Head over to github and check out the README for instructions on getting a copy and installing. Since this is an open source project everyone out there is welcome to contribute and improve with features that they themselves find handy.