At Linden Lab, we took a brief look at Ruby in 2006. Some Rails code had snuck into deployment and as we were digging into refactoring back end communications, Ruby and Rails came up as an option. At the time, I remember thinking that Ruby had a comfortable syntax and was as easy as Perl for whipping out quick-and-dirty tasks. Early performance testing was not encouraging and that first production piece of Rails code had issues, however, so Ruby and Rails got lumped together in the collective Linden hive mind as Bad Technology(tm).
Thus, when Peter decided we were going to build on Ruby and Rails, it gave me pause. Of course, since Peter was going to run engineering, it was his call. Plus, James Currier and his team at Ooga Labs were happy building on it.
So, Ruby it was.
The last six months at EMI have been a blur of learning the music business, adapting to working within a large company, and building a technology team. In making initial hires, I realized that my lack of Ruby expertise was hurting my ability to interview candidates. I had been through the pickaxe book, and various bits of data analysis code had moved from Perl to Ruby, but I hadn't built anything of substance. So, over the holidays I took on a chunkier side project. Details to come in a later post, but in building it a bunch of useful Ruby lessons emerged.
First, if you know other programming languages and want to bump your brain into Ruby context, read "Design Patterns in Ruby." Best Ruby book I've yet read and its intro to Ruby chapter is a superb intro to the language.
Second, embrace behavior driven development, rspec, and rcov. BDD takes things a step up from unit testing. If you're an old time C coder, you probably are used to whipping your design out in broad comments and then coding the elements in. BDD changes this from writing comments to writing user stories and then your unit tests as you go. Hard to describe how addictive this style of coding is until you've done it, but it explains the evangelical nature of its adopters because it's fun! At a mental impasse? Write a few more stories. Haven't had your first cup of coffee yet? Sketch in the class structure to pass early tests and add a few more stories. A few minutes before the end of the day? Bump your code coverage to 100% on a file that currently is at 70%. Note that none of this applies universally to Ruby, nor did Ruby invent any of this. What Ruby does give you is a fairly easy to install and use framework of tools.
Third, if you're on a Mac, use Growl and ZenTest and then configure reporting. What this does is to automatically rerun your tests every time you change a file and then report the results via growl. You can even have the Doom marine tell you how you're doing! It's all about reducing the development process to small, bite-sized chunks, with the added hook of continuous feedback.
Fourth, I've already talked about git and github for source code control. Having lived in the CVS/Subversion world for so long, git continues to impress. Super fast, flexible, and integrates well with TextMate.
Finally, we've started having movie time at lunch and watching the Pragmatic Programmers series on Metaprogramming. Very useful, without the "look how clever my code is" aspect that seems to permeate a lot of the online discussions.
Monday, January 12, 2009
changing views
Saturday, December 06, 2008
some media learnings
I have a lot of computers and media floating around at home and last weekend it was once again time to build some tools to better manage them. Wrote some Ruby and used rb-appscript to bend iTunes to my will. Along the way learned a few lessons:
First, ASTranslate is teh shizznitz. It takes a pile of AppleScript and spits out working rb-appscript. Since I really wanted to minimize the amount of AppleScript I needed to learn -- and wanted to be able to work my magic on headless machines, this worked quite well. Let's say you want to take a Quicktime reference movie, insert it into iTunes, and then trick iTunes into managing it like a TV show:
episode = app('iTunes').add(MacTypes::Alias.path("#{path}/#{name}"))
if episode
episode.video_kind.set(:TV_show)
episode.show.set(name)
episode.episode_number.set(episode_num)
episode.season_number.set(season_num)
end
Want to search TV shows?
app('iTunes').user_playlists["TV Shows"]. \
tracks[(its.name.contains(searchname))].get
Easy peasy. ASTranslate running next to Apple's Apple Script editor and Doug's amazing repository of Apple Scripts made it easy to dig through this stuff.
Second, reference movies. If you use Perian (you do have Perian installed, right?), Quicktime and Front Row will play all kinds of movie types. However, iTunes won't load them. Reference movies are snippets of XML that allow you to work around this:
def create_reference_movie(dir, name, season, destdir)
def raw_urlencode(str) # need to escape reference name
str.gsub(/[^a-zA-Z0-9_\.\-\/]/n) {|s| sprintf('%%%02x', s[0]) }
end
File.open("#{destdir}/#{refname}", "w") do |file|
file.puts("<?xml version=\"1.0\"?>")
file.puts("<?quicktime type=\"application/x-quicktime-media-link\"?>")
file.puts("<embed src=\"file:#{raw_urlencode("#{dir}/#{name}")}\" />")
end
end
That's right, three lines of XML that you can create -- by hand, even -- to let you drag drop odd formats into iTunes.
Third, a gotcha which makes all of this less cool. Even though iTunes can share and stream video, it turns out that it will not do this for reference movies. Boo!
Fourth, this is well known within the Ruby community, but multibyte string support in 1.8 is weak. Lost a few hours this afternoon to a bug that was obvious once the "oh, strings aren't UTF-8 yet!" thought hit me.
Thanksgiving was mostly about cooking but it was fun to get a bit of coding time in!