Thu 17 July 2008
Rotoscope Cannonball Productions Meticulous Boboroshi & Kynz

masthead image

boboroshi.com - fitter. happier. more 70s wallpaper.

Amy and I have been accepted to a new thing at SXSWi coming up in March in Austin, TX. It’s called a “Core Conversation” and we’ll be holding one on our concept deemed “Career Rev 342: Dabble Dabble, Toil and Kick Ass”. The basic premise revolves around a lot of what Amy and I have been through: broad, multi-faceted learning, generally out of the classroom, and lots of nose to the grindstone. It’s also a discussion about how mutliple facets improve team interactions (as opposed to specialists who don’t understand each other’s specialties).

We don’t have any details yet, but we’ll update you as we move towards March.

DHH posted about the new version of Ruby on Rails that is currently a preview release. The exciting things are just the simplification of a lot of things, especially Migrations. Also, a lot of the acts_as functionality is being extracted to plugins. Lighter, faster, and more streamlined.

Also, one of the elements of RESTful that was implemented with the semicolon functions has been changed back to slashes, which seems much more logical and proper anyway.

Looking forward to the final release.

Sometimes things just happen in a way that is exactly what you asked for, with just really odd timing. You might get a white Christmas on Dec 26th (happened two years ago). You might ask yourself “where is my beautiful house?” You might get… uh… Well, you know what I mean.

So things just started kicking like Bruce Lee. Honor by August’s schedule is taking off, we’re going to be playing the Viper Room in LA in September, and we’re on the road pretty heavy this fall. We’re also doing some showcases for various labels. And I can’t be on the road as much as I am and really run a creative department at a physical location.

So I’m going to be going back to the world of working for the self. I’ve teamed up with Amy Hoy to rock the world of UI and User Experience. And we’re doing it in snarky style as Hyphenated People. You could say we’re dabblers, or ADD or just confused, but really, we just love learning.

Amy rocked out a sexy site complete with Easter Egg heaven:

Oh yeah!

So, we’re doing some really cool stuff for a guy that was just on Conan O’Brien amongst other people. Lots of exciting cool projects and I get to sink my teeth back into Ruby while working from the van and rocking out.

So, last year on my birthday, I joined a band. This year I quit my job and got a food processor. It’s a quarter-life crisis people. Watch out!

The incomparable Amy Hoy and I are pitching a panel for SXSW this year about being a dabbler. We’re both pretty much ADD dabblers, but this is actually a prepared presentation, not a five person Q&A session gone wrong.

We’ll be chatting about things like

  • constant learning,
  • why it’s good to have a guitar next to your desk,
  • pushing your team members into renaissance-man land,
  • and some good “Now Everyone Hug” motivation.

Amy will be recording and I will then spend four weeks “EQing and Mastering” it in ProTools, by which time she will have just put it out anyway, forcing me to resort to releasing the Criterion Collection edition. Of course, no one will notice any significant difference. :D

So, yeah, vote early. Vote Often.

Trace with Overlay! YAY!

(This article is part two in a multi-part series on design process, which started with my article on Why?!)

For those of you who have seen Chasing Amy you’re aware of the famous line delivered by Jason Lee: “Tracer? Your Mother’s a tracer!!!” This follows taunting by a comic book fan that he’s not really doing anything creative.

The taunter was totally wrong.

Towards A New Paradigm

I went to Architecture school. Not information architecture, but the “we make buildings and stuff” variety. One of the big tenets of the program I attended was that one should not be using a computer unless they already knew how to do the traditional technique. The computer is simply a digital version of the drawing tool or a different tool that needs to be integrated into a set of traditional tools. How can you draw in a computer if you don’t know how to draw in the first place?

The rationale behind this is easy. Computers are finite, sketching is representational. When in CAD, it’s a very precise line length, angle, color, etc. Paper can be as simple as a parti diagram (just showing the basic line strokes of a design) or can be super shaded and detailed. But regardless, at the end of the day, it is not finite. It is a representation of an idea.

Take this story from my college interning days. I was working for a small design/build shop in Newport News and I had the opportunity to design sketch a small addition. I came up with two different ideas and the owner asked me to present them to the client. So I drove over and sat down at the table with them in their house and showed them what we had come up with. They weren’t sold on either completely and did a typical client move: “We like this from A and that from B.” Okay. I whipped out a role of trace and drew that with them right there and asked “something like this?” They were ecstatic and joined into the creative process and I left the house with a finalized design.

This works very well for web work, whether it is within a team or with a client, this rapid sketch process gets everyone to a shared understanding (and buy-in) very quickly.

Sketching for Web

Currently, when one starts designing a product (web app) or web site, most will start with either a database model in Visio or OmniGraffle (if they are a programmer) or a look/feel comp in Photoshop, Fireworks, or Illustrator (if they tend to the design mentality). These are far too detailed approaches when you know not what you are trying to accomplish. So let’s go with that age old addage of everything you need to know you learned in Kindergarten.

This is what is so great about this approach. EVERYONE on the team: Designer, programmer, client, business owner, investor, heck, even your accountant, can all be part of this process. It can happen on a white board, post-it notes, an easel, printer paper, a sketchbook, and even pen tablet systems (but again, computer wants things precise).

This isn’t a new idea. Jakob Neilsen sang the praises of paper prototyping in 2003:

With a paper prototype, you can user test early design ideas at an extremely low cost. Doing so lets you fix usability problems before you waste money implementing something that doesn’t work.

Ryan Singer, of 37Signals, also uses an extremely high-level paper prototyping system (which he discusses in Getting Real). They even scribble the text and then jump straight into HTML, using a graphics program only to create needed graphics. This obviously doesn’t work for everyone, but the core concept is simple: get the idea of the interaction that occurs designed very simply. Then start plugging and chugging it into your framework.

So, we have a theoretical system, paper prototyping, that allows us to get ideas developed quickly. But why should you use trace paper?

Why Trace?

When an architect is designing a building, trace comes in handy. First off, revisions. Floor plans change. Secondly, repetition. There are core elements that stay the same, such as the exterior walls and stairwells, but individual floors have different elements. Trace facilitates rapid copying of elements from other already completed layouts.

Now let’s apply that to a website.

The global elements, such as a header, a footer, navigation, and the basic framework (e.g. two vs three column) typically stay the same. The body content changes.

In real world practice, we used the trace process on two sites recently: CityCliq’s redesign and the initial design for Gourmet Library. In both cases, a large amount of high level design was accomplished very quickly by using trace paper. Once we kicked into a flow, a new page could be completed in 15 to 30 minutes. With CityCliq, we were doing product design/redesign and finished 24 wireframes in two relatively relaxed days at their offices in Jacksonville, FL.

Scan and upload to our Basecamp account? Bam.

“But I Can Do That in [Visio|OmniGraffle|Illustrator|Indesign] Faster!”

Well, in a production sense of making edits, etc. sure you could. But it’s the wrong tool. You’re trying to imply pixel perfection to an idea. You are spending time on the wrong thing (how things exactly line up) versus the important idea of what that page or that piece of interaction is. You get the important user experience information on paper and discuss how things flow. Then you can start dialing down into other tools. I personally go from paper to Photoshop. Ryan Singer at 37Signals goes from paper to HTML (or so he did when I attended the Getting Real workshop in Chicago in 2005).

So break out an index card, a post-it note, a roll of trace, a sketchbook, or a sketch-a-doodle even. As Michael Buffington twittered as I finished this article: paper prototyping turns out to be a lot like Kindergarten.

Let’s break out the finger paints.

Further Reading

Jakob Nielsen’s Alertbox on Paper Prototyping
Paper Prototyping (The website to accompany the book)

Supplies

12" x 150ft. Creme Trace paper
Staedtler Lumocolor Pens (I prefer the 318-9 Black Fine point)

So some of you may have seen Amy’s quasi-announcement about our new SupaSecretProject™ on which we have been working a little bit lately. In building the logo, I realized that some of the simple things in Photoshop are not so easy to find for people who haven’t been using it as a tool of mass procrastination since 1996. So I figured it was time for a step-by-step tutorial on how I built the Pimp My Rails logo.

We’re going to create something like this:

Final Pimp My Rails logo design

Fonts

First thing anyone needs is some good fonts. Since “Pimp My Rails” is an obvious play on MTV’s Pimp My Ride television program, some mild semblance in a visual sense was desired. Xzibit was unavailable as a spokesperson, so the graphic elements were going to have to do.

I had a few fonts I had purchased for various projects, one of which was Letterhead Fonts Ballpark Script which has some awesome swashes too. We had purchased it for use at OnTap a few years back. This would be perfect for the “Rails” word. Then something fun but not too cartoony was needed for the “Pimp My”, as I didn’t want so much scripty that it just didn’t work well. So bring in House Industries Holiday Sans. We’re ready to rock.

Don’t you love these highly technical terms? “Cartoony” and “Scripty” and what not? Yeah. Precision in visual communication, that’s right! Enough babling. Let’s start Photochoping!

Photoshop Magic

So we start with a nice simple screen, in this case, 500×375 pixels. You don’t need a screen grab of a blank Photoshop screen. You can imagine that one. So let’s start with the Ballpark Script and write “Rails”.

Step one

Okay, we’re on our way. Let’s get a sexy swash going underneath it. I used the “i” character for this particular swash.

Step two

And we say in Kool-Aid Man style: “OH YEAH!” But we have miles to go before we sleep young padawan. The Logo is missing half the words. So we’ll add them and give them a little curvature with the arc text tool. +22% vertical should do it. And let’s drop it in House Holiday Sans.

Step three

Sexy. So now we need to make this “pop,” as the obnoxious client would say. In order to do that we’re going to start playing with layer effects. Let’s get a colored background so we can see what we’re doing. You can achieve this by creating a new solid color layer or using the paint bucket on the background. I prefer the former method because it’s easier to change later on in the process.

Step four

Excellent. Now let’s give this a mega stroke. Since we have three text layers, let’s simplify things. Group them together, duplicate the folder, and flatten the two layers that make up “Rails” into one layer. We will now apply styles to “Pimp My” and “Rails” with a swoosh independently. Put a stroke on each layer and size to taste:

Step five

Now let’s add a gradient overlay as well. On this I had the “Pimp My” overlay stay close to the main red that is the darkest part of the “Rails” gradient.

Step six

Hmm. Still looks kind of flat. Let’s fake some depth with a bevel.

Step seven

gives us…

Step seven result

We could call it a day here. But this needs some more excitement doesn’t it? So what can we do? Starbursts! Everyone loves starbursts! Now these aren’t too difficult to make in Photoshop. Create a new image, let’s say roughly 1000px x 375px. Make a vertical 20px black stripe on one edge of it. Duplicate it and set it next to the other one and then invert it to white. You should have something like this:

Step eight

Now with snap involved, we can use the drag and copy (Apple – Option – Click) to rapidly fill up the whole thing. Make sure you end on the opposite of what you started with. Crop to taste.

Step nine

Now it has come the time that we make this a rockin radial explosion of pixel sexiness. Filter -> Distort -> Polar Coordinates is going to be the tool that accomplishes this.

Step ten

So hit “Rectangular to Polar” and watch it go! You can try this with regular pictures, but you typically end up in a somewhat Alice in Wonderland kind of world. And that’s not always good.

Step eleven

Now you can adjust your settings to get various feelings of compression on certain axes, etc. That’s your call. But we’re going to take this back to the main file and paste it in there.

Step twelve

That’s a little stark. We also know that we want to create some illusion of depth, so let’s make a radial gradient to help with that.

Step thirteen

Okay, so here’s the trickery. Select the layer of the starburst and apply a layer mask. Paste the radial gradient into the layer mask (you might need to invert it for the proper effect). Finally, set the layer transfer mode to “Overlay” and the opacity down to about 10%. Make sure it’s behind the text, but over the red background.

Step fourteen

Lookin good. On the original screen capture on Amy’s site, I had used a photoshop brush and basically dirtied it up a lot to make it look a little vintage. This version removes that.

Let’s reinforce the depth aspect and add a drop shadow to the text. Duplicate the text group and rasterize the whole group to one layer. Apply a drop shadow.

Step fifteen

Add cheesy tag line to taste:

Step sixteen

There you go. Your Rails, Pimped.

Now most of you are probably reading the title of this post saying “what in the hell is Athayde talking about?” Well, it’s complicated. But it’s an error that Justin and I have both hit and I keep forgetting to write down how to fix it. So I’m writing it down.

It was a relatively quiet Saturday night, and I was working on cleaning and recovering with some nice Knob Creek and Code Coke when suddenly, a shot rang out, a door slammed, the maid screamed! Suddenly, a pirate ship appeared on the horizon! Justin posted to Twitter that he was fighting with rMagick on Athena (our main production server). So I offered to help. Diving in we hit this error:

Fatal error 'Spinlock called when not threaded.' at line 83 in file /usr/src/lib/libpthread/thread/thr_spinlock.c (errno = 2)

Hmm. Looked familiar. Hit this before, we have. So I began to dig around. Upgraded ImageMagick to 6.3.3. Nope. rMagick from source! Nope. “But yay for new software,” I said jovially. Hankins was not amused. He found some google fu that started to point us in the right direction. Eventually we found out what it was.

Libraries compiled against other libraries that conflicted with each other and refused to play nice. For those of you who are looking for the fix, here it is. You need to create and hack /etc/libmap.conf to say this:

# /etc/libmap.conf
#
# candidate     mapping
#
libpthread.so.1         libpthread.so.1 # everything uses 'libpthread'
libpthread.so           libpthread.so

libc_r.so.5             libpthread.so.1 # everything that uses libc_r
libc_r.so               libpthread.so   # now uses libpthread too!

And then the rmagick make and make install commands ran perfectly fine. And everyone was happy.

The young intern sat by himself in one corner of the coffee shop. he had learned about medicine, but more importantly, he had learned something about life.

Here’s some stuff I’ve found or re-read in the last few weeks that I just want to put out there.

Understanding the Rails Initialization Process: Part I | Rick’s write up lets you see how things load up, which can help identify where some of those hiccups occur in your Rails app.

Understanding Ruby Symbols | Moving into Ruby from PHP is a bit of a jump, and took me some getting used to Ruby’s symbols and how they are used in the grand scheme of things. Kevin Clark’s article on this is great.

Using the Sphinx Search Engine in Ruby on Rails | Sphinx is a full-text search engine that integrates with SQL databases. And it appears to be the bomb.

MySQL Proxy | Jan Kneschke put out this new tool that allows you to make requests via a proxy (and therefore alter or inject the query or fix bugs on the fly). Eventually he will be building in load balancing to the proxy.

Chad Fowler’s Talk on Quick & Clean | Chad’s talk from the UK on Quick & Clean, or “well-factored Rails” code.

Meticulous has numerous servers online. This site happens to reside on our rails development server named “Cuba”. It’s on the development server because I can try things out without taking down our main production boxen (Athena & Hercules). Athena’s been around for a while and was stuck on Apache 1.3.x. We had some rails apps we had recently deployed that were just not cutting it with mod_fastcgi on the server, and we decided to upgrade the server in one fell swoop to give us the new hotness.

Our install list included:
  • Apache 2.2.4
  • PHP5
  • PHP5 Extentions
  • mod_fastcgi
  • smarty
  • Subversion
  • Ruby 1.8.5
  • Ruby Gems, Rails, Mongrel, Mongrel_cluster, Capistrano, etc etc.

The install process was simple enough but the depencies bug hit us hard.


root@athena# cd www/apache22
root@athena# make install clean
===>  Installing for apache-2.2.4

===>  apache-2.2.4 conflicts with installed package(s): 
      apache-1.3.33_1

      They install files into the same place.
      Please remove them first with pkg_delete(1).
*** Error code 1

Stop in /usr/ports/www/apache22.
root@athena# pkg_delete
pkg_delete: missing package name(s)
usage: pkg_delete [-dDfGinrvxX] [-p prefix] pkg-name ...
       pkg_delete -a [flags]
root@athena# apachectl stop
/usr/local/sbin/apachectl stop: httpd stopped
root@athena# pkg_delete apache-1.3.33_1
pkg_delete: package 'apache-1.3.33_1' is required by these other packages
and may not be deinstalled:
mod_gzip-1.3.26.1a
smarty-2.6.7
php4-bz2-4.3.10_2
php4-ctype-4.3.10_2
php4-gd-4.3.10_2
php4-gettext-4.3.10_2
pecl-imagick-0.9.11_1
php4-mysql-4.3.10_2
php4-overload-4.3.10_2
php4-pcre-4.3.10_2
php4-posix-4.3.10_2
php4-session-4.3.10_2
php4-tokenizer-4.3.10_2
php4-xml-4.3.10_2
php4-zlib-4.3.10_2
php4-extensions-1.0
mod_php4-4.3.10_2,1
mod_ruby-1.2.4

Basically, we had to delete those packages in reverse-dependency order and then do Apache, PHP5, the PHP5 extensions, etc. following.

Virtual Host Love

One of the biggest benefits of Apache 2 is the Includes directory in /usr/local/etc/apache2. This directory has individual files setup for each Virtual host on the system. We have something over 160 virtual hosts on our main production box, and they were all listed in the Apache 1.3 httpd.conf file.

Justin flexed his ruby muscles and came up with a script that took the Virtual Hosts area of the httpd.conf file and parsed them into individual files.


# Parsing code at the bottom.
data = '

{Your VirtualHost config here}

'

WRITE_DIR = "/full/path/to/where/you/want/these/saved" 

ary = data.split("</VirtualHost>")

# TESTING
#=begin
ary.each do |x|
  site_name = x.match(/(ServerName)(\s)(\w.*)/)
  site_name = site_name.to_s.gsub(/(ServerName)(\s)(\w.*)$/, '\3') + ".conf" 
  site_name = site_name.gsub(" ", "").gsub("\t","")   # Strip out whitespaces
  puts site_name
end
#=end

ary.each do |x|
  # Strip out the multiple line breaks
  site_conf = x.gsub("\n\n", "")  

  # Add back in the </virtualhost> closer (which gets omitted with strip)
  site_conf += "\</VirtualHost>" 

  # Find the ServerName ... line
  site_name = x.match(/(ServerName)(\s)(\w.*)/)

  # Remove apache ServerName ... code, leaving domain name. Append .conf to the name for writing.
  site_name = site_name.to_s.gsub(/(ServerName)(\s)(\w.*)$/, '\3') + ".conf" 

  # Strip out any whitespaces in the name
  filename = site_name.gsub(" ", "").gsub("\t","")

#  puts filename    # testing
#  puts site_conf   # testing

  if File.exists?(WRITE_DIR + filename)
    puts "\nEXISTS: " + site_name
  end

  the_file = File.new(WRITE_DIR + filename, "w")
    the_file << site_conf
  the_file.close

end

This created 164 files with domainname.ext.conf as the file name. There were a few places where extra white space caused lines to jump onto other lines, but in general it was quite efficient and saved us hours of manual labor copying and pasting the config.

So now it’s time to get mongrel proxies running for all the rails sites. And deal with the nancies.org boards issues that are sure to come up. And get mod_deflate running. The fun never ends!

UPDATE Looks like it’s all happy. A few “best practices” cleanup things we need to do on various sites, but all in all, not bad. Now, to migrate the DNS and email servers.

In the long arc of web design, sites change. Over the years, they are redesigned, reimplemented, ripped apart, and reassembled. In doing this, content, typically, can be lost to the ether. We all know that missing content is simply “not a good thing” and should be avoided.

Inbound links to a site generally come from two main places:

  1. Google/Yahoo/MSN/Search Engines
  2. Links on other pages (e.g. blogs, articles, directories).

The search engines crawl regularly and keep themselves up to date. If they can find your content they will. If you tell them it’s moved permanently, they’ll update their records. Articles and other sites, however, usually won’t. I haven’t checked old outbound links on this site and I doubt many other people do either. In order to keep the end user searching through google and clicking on links from external sites happy, we need to employ some URL redirection to keep the old links pointing to the content with which they are associated.

We want to use 301 redirects.

What is a 301 redirect?

A 301 redirect refers to the HTTP protocol status code delivered by the web server. A 301 is similar to the most famous status code: 404. A 404 is “page not found”. A 301 says “this resource has been permanently moved and here is the new address. Simple.

Redirects are achieved by using the mod_rewrite Apache extention. The semantics of writing rewrite directives can be quite mind boggling to the novice user as evident by the documentation for mod_rewrite

Why 301 redirects?

When you redeploy a project with a new framework, a lot of old links that have google-fu disappear. People clicking on said links will get a 404 error and end up confused believing the content to have been destroyed. Sad web surfer. So, as a good web designer, you want to ensure that all of your old URLs point to their new counterparts.

“But what about meta header redirects?” you say.

Sure, that would work on a small scale, but they have been so abused by spammers in recent years that they will decimate your search engine ranking. Also, when you have over 1900 redirects (as I did when porting this site to Mephisto) you want to make sure that you can set something up that is

  1. Easy to manage
  2. Centralized
  3. Seamless and immediate to the end user.

And that’s what we’re going to setup here.

Why .htaccess doesn’t work properly

In setting up capistrano based on Coda Hale’s instructions you are actually telling Apache to send everything to the mongrel_cluster to handle requests before you reach .htaccess. For some reason, this allows certain requests to be handled (e.g. ones that were related to /feed worked, but /feed has a route associated with it), but it ignores others.

# Redirect all non-static requests to cluster
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ balancer://mongrel_cluster%{REQUEST_URI} [P,QSA,L]

That basically says “when the condition equals the site with any trailing URL, send that stringto the mongrel_cluster load balancer and let it deal with it.”

The Setup

First off, we need to turn on mod_rewrite for this site. It should be on in your .conf file since Rails uses rewrite to achieve basic routing, so look for the line that says

RewriteEngine On

If it is not present, your site probably doesn’t work at all and you have far larger problems than I can address here.

Second, we know we have a lot of these redirects, so we don’t want to muddy up our very nice apache config file with them inline. So let’s use the Include directive to tell Apache to pull the file wholesale and parse it at that point. Place this line immediately after the RewriteEngine On directive.

Include etc/apache22/Includes/boboroshi_rewrite.conf

I placed mine in the same directory as my main domain conf file. On Apache versions before 2, you will not see an Includes directory in /usr/local/etc/apache* so you would need to do this differently.

In this file, I placed a series of redirects that I typed up in an external text editor and uploaded to the server. Did you think I would type 1900 lines in nano or vi? Crazy! I digress…

The file looks something like this:

RewriteRule ^/log/index\.xml$ http://feeds.feedburner.com/boboroshi [R=301,L]
RewriteRule ^/index\.xml$ http://feeds.feedburner.com/boboroshi [R=301,L]
RewriteRule ^/index\.rdf$ http://feeds.feedburner.com/boboroshi [R=301,L]
RewriteRule ^/atom\.xml$ http://feeds.feedburner.com/boboroshi [R=301,L]
RewriteRule ^/rsd\.xml$ http://feeds.feedburner.com/boboroshi [R=301,L]

RewriteRule ^/bloggertrue\.mov$ http://versionsix.boboroshi.com/media/video/bloggertrue.mov [R=301,L]

RewriteRule ^/travel/vh1awards/$ http://versionsix.boboroshi.com/viewpoint/travelogue/vh1awards/ [R=301,L]
RewriteRule ^/travel/calinevada62001/$ http://versionsix.boboroshi.com/viewpoint/travelogue/calinevada62001/ [R=301,L]

RewriteRule ^/backlog/2006/11/just_like_starting_over\.php$ http://www.boboroshi.com/2006/11/28/just-like-starting-over [R=301,L]
RewriteRule ^/backlog/2006/10/myspace_data_modeling\.php$ http://www.boboroshi.com/2006/10/31/myspace-data-modeling [R=301,L]
RewriteRule ^/backlog/2006/10/the_killers_sams_town_springsteen_queen_and_deadwood\.php$ http://www.boboroshi.com/2006/10/8/the-killers-sams-town-springsteen-queen-and-deadwood [R=301,L]
RewriteRule ^/backlog/2006/10/photos_soft_complex_monopoli_cedars_at_the_black_cat\.php$ http://www.boboroshi.com/2006/10/7/photos-soft-complex-monopoli-cedars-at-the-black-cat [R=301,L]
RewriteRule ^/backlog/2006/10/the_periodic_spiral\.php$ http://www.boboroshi.com/2006/10/4/the-periodic-spiral [R=301,L]

[......]

What does that mean? Well looking at the mod_rewrite documentation we’re looking at some basic regular expressions. the ^ starts the string and the $ ends the string. Since a period is used to represent any character, you want to slash escape it by placing a backslash character (\) before any period that should be in the URL.

[R=301,L] the R says “force redirect” and apply a 301 status code. The “L” says “stop running through the rules now and load the page. This is good when we have 1900 entries. Once it finds the entry, it stops and gets the content to the client.

So, once you’ve got it written up, toss that file in the directory, restart apache, run cap restart from your deployment workstation, and you should be in business. And your old users will be very very happy that they don’t have to look at a cache page in Google.

In re-launching this site, I decided to use Capistrano to deploy. First off, I wanted to try it out. Second, I wanted to learn how to do proxy balancing with Mongrel and Mongrel_cluster. I followed the nifty instructions by Coda Hale and then hit a few bumps.

On FreeBSD, I had to change a line in the capistrano gem on my workstation because it was not recognizing [[ as test. I changed line 34 of base.rb to

if test ! -d #{configuration.release_path} ; then

Also, ensure that your user is part of the wheel group and wheel is allowed in the sudoers file in /usr/local/etc/sudoers

Anyhow. Another thing checked off. Time to move on to the next item on the never ending GSD™ list.

In migrating out of MovableType I had to leave the [dark miserable depressing] world of PHP behind. So I had to rewrite some scripts in Ruby. One of said scripts is a piece of code that selects an entry from an array and returns it to the body of the code so that you can have an area that updates pretty quickly.

This was one of the first things I learned to do in PHP (thanks to Waldo patience and direction). That code was pretty simple, but not very readable or elegant:

<?php

// called by
// <?php echo $contents[$random_key]["text"]; ?>
// <?php echo $contents[$random_key]["image"]; ?>

// Gimme a number, any number

srand ((float) microtime() * 10000000);

// Define the array

$contents[0][image] = '...';
$contents[0][text] = '...';
...

// Choose your poison

$random_key = array_rand($contents);

?>

Not very elegant. It works, but it’s just nasty. In Ruby it’s pretty straight forward and I figured someone else learning ruby might be able to learn from this:

#! /usr/bin/env ruby

class RandomImage

  PHOTOS = [ # Define the array of photos. Maybe eventually do this with YAML
    #  Image Name                  Caption
    [ '930lights.jpg',             'Caption' ],
    [ 'arlingtonclouds.jpg',       'Caption' ],
        ... # Repeat 24 times
    ]

  def show_random_image
    # Select the array entry
    @photo = PHOTOS[rand(24)]

    # Give some local variables
    filename = @photo[0]
    caption = @photo[1]

    # Echo statement definitions
    random_image_call = "<img src=\"media/images/design/masthead/#{filename}\" alt=\"masthead image\" height=\"250\" width=\"725\" border=\"0\" />" 
    random_image_caption = "#{caption}" 
  end
end

You have an array defined. To get to an entry in the array you would type @photo[n] to get to the filename or caption you’d add the second level of access @photo[n][0]. Since we want the caption to match the photo, we only want to run rand once. Put that into a variable, and then operate on that variable.

Muy sexy.

Things to do in the future

  1. Make this a Mephisto plugin
  2. Use YAML instead of an inline array
  3. Get rich off the proceeds

Okay, so two out of three wouldn’t be bad.

I’ve used MovableType for a LONG time. This site has been a conglomeration of hacks of PHP and Movable Type backend trickery. It’s not that I do not love MovableType. I do. It’s incredibly powerful at some things. But it’s just started to fall under its own weight. Finally, I’m moving on.

I’m moving to Mephisto – A nifty lightweight blog engine written by Rick Olson. Rick is part of the Ruby on Rails core team and a great programmer whose plugins have made the production pipeline a reality.

As for why the change? Why now? I wanted to go for less. I always had massive sections of the site that I never updated on the old boboroshi. I wanted something nice and easy that I could extend on my own writing some simple Ruby code.

The downside is that there is no Movable Type to Mephisto converter right now. So I had to use Typo (another Ruby on Rails blog engine) to bridge the gap. Yes I could have written a conversion script. But I’m tired.

I lost 4 articles and 10 comments somewhere going to Typo. But I don’t know which ones those are. Alas. The deed is done. So from now on, we’ll be riding on rails with Mr. Mephisto.

For those of you attempting to play along at home, you will run into one issue where some commenter author_ips are empty. Simple way to fix this is before running your Mephisto conversion script, open up a mysql shell and do

UPDATE ip WITH "10.1.1.1" IN contents WHERE ip = "";

I think that’s right. Oh well, it’ll tell you if it’s wrong.

You might have also noticed that I cleaned up the design and added a lot more images to the header rotation. The old site was starting to look a bit bland, but I didn’t want to redo it completely. So this is how you get it. Refreshed, yet familiar.

Delicious like apples.

In April 2004, Kory Juul and I had an idea for a production pipeline that didn’t suck. We discussed the pipelines that we’d seen over the years doing film effects and architectural rendering and said to each other, “There must be a better way!” We went off in search of the better way and discovered some cool concepts and came up with a framework for our pipeline. And then, in between all the work, we started coding.

After more than two years of dabbling and thinking and hitting some decent code complete milestones (and learning Ruby On Rails in the process), I’ve decided to kill the existing code base and start over. The more we used it, the more we realized that the existing system just didn’t work quite right.

We realized that the core of the application was about elements. An element being the smallest unit in a facility. Any digital asset such as a Maya file, a texture map, motion capture data, and the like. The core of how the application needed to work led us to think about how an element is born and moves through the system. Everything revolves around the element and what various people in myriad departments do with it. In my first stab, I had thought more about the project and less about the element and the shot.

Also, in the last two years, Rails has come a very long way from a small beta framework to the now-release-candidate-grade-version 1.2. We’ve got Mongrel and Components have gone the way of the Dodo. The framework has moved towards a RESTful approach. It’s delicious.

We’ve also become a bit more experienced in how we think a pipeline should run. Finishing The Sandbox and working on a commercial for Microsoft and some shots for a major studio feature gave us some new insight.

The interface won’t change much, but the back end will change immensely. We’re going RESTful. We’re utilizing Test Driven Development (I hate writing tests, but love them later in development). We’re focusing more on a great Digital Asset Manager than a hacked up project management application.

And it’s not too shabby. In two evenings I have a basic core with working, tested code. I’ve got realistic sprints with defined user stories. And hopefully, by NAB, we’ll have a good working prototype to show off.

Just like starting over.

Routing in Rails is an implementation of rewriting that maps controllers to addresses besides the active record default. Basically, it allows you to have any URL point anywhere inside your application. While working on Koji, the production pipeline, I began to hit a wall trying to make a directory structured style URL. Something like this:

http://koji.prodpipe.com/projects/the_sandbox/OPN/101/

That would be Shot 101 in the OPN sequence in the project The Sandbox. Seemingly easy enough, but not understanding the way the methods worked was driving me crazy. So here’s a quick rundown of how it works. I wrote this before Rails went 1.1 final, so there might be more effective ways to do this that I haven’t refactored for yet.

You create a route (named or not, i happened to name this one):

# in config/routes.rb

map.shot_pg 'projects/:shortname/:acronym/:number',

So, that takes three symbols, :shortname (which belongs to the project model), :acronym (which belongs to the sequence model), and :number (which belongs to the shot model). The relationship is already established, with project having many sequences, and sequences having many shots. These are defined in the models directory:

# project.rb
has_many :sequences

# sequence.rb
belongs_to :project
has_many :shots

#shot.rb
belongs_to :sequence

There are only a few lines to add to the method in the controller, the first two defining the project and sequence calls that happen and the @shot variable including the parent and child elements that are referenced in the views.

def show_by_number
  @project = Project.find_by_shortname(params[:shortname])
  @sequence = Sequence.find_by_acronym(params[:acronym])
  @shot = Shot.find_by_number(params[:number], 
rescue
  logger.error("Couldn't find Shot number #{params[:number]}")
  flash[:notice] = '<div id="flash" class="bad">That shot does not exist</div>'
  redirect_to(:action => 'list')
end  

Now, when you type in that URL above, you end up at the page.

Sexy!