Webmaster! Your Feed Informer account is inactive. Please login to re-activate this digest.
Mar 20 Now Using Pivotal Tracker

I’m switching from self-hosting Redmine to using Pivotal Tracker for issue tracking on my Open Source projects.

Switching to Pivotal Tracker

After running Redmine locally for a while, I’ve decided to switch to a hosted issue tracking service. I’ve moved all the open tickets on the onestepback.org Redmine app to my account on Pivotal Tracker.

Current Project Links

Here are the links to my current projects:

All the projects are marked public so you should be able to view the projects (and subscribe to an RSS feed) without actually signing up for anything.

Did I miss anything?

All the open tickets should be migrated to Pivotal Tracker. If you notice anything missing, let me know. Thanks.

Mar 20 What Are Metaclasses?

I seemed to have accidently started a twitter storm debate on metaclasses in Ruby. Somethings are just are to say in 140 characters. So here’s my take on the issue.

Singleton Class / Eigenclass / Metaclass … What?

Ruby has this concept of per-class methods. In other words, you can define a method on an object, rather than on its class. Such per-object methods are callable on that object only, and not any other object in the same class.

Implementation wise, these per-object methods are defined in an almost invisible class-like object called the “Singleton Class”. The singleton class injects itself into the object’s method lookup list immediately prior to the object’s class.

Some people object to the name “singleton class”, complaining that it is easily confused with the singleton pattern from the Gang of Four book. Other suggested names are “Eigenclass” and “Metaclass”.

I objected to the use of the name “metaclass” for the singleton class on the grounds that metaclass has a well understood meaning in non-Ruby circles, and that the singleton class is not a metaclass.

So, What’s a Metaclass?

According to wikipedia:

In object-oriented programming, a metaclass is a class whose instances are classes. Just as an ordinary class defines the behavior of certain objects, a metaclass defines the behavior of certain classes and their instances.

I get two things out of this: (1) instances of metaclasses are classes, and (2) the metaclass defines the behavior of a class.

So Singleton classes aren’t Metaclasses?

No, not according to the definition of metaclass.

In general, instances of singleton classes are regular objects, not classes. Singleton classes define the behavior of regular objects, not class objects.

But Everybody Calls them Metaclasses!

I can’t change what everybody calls them. But calling a dog a horse doesn’t make it a horse. I’m just pointing out that the common usage of the term metaclass is contrary to the definition of metaclass used outside the Ruby community.

Does Ruby have Metaclasses?

Yes … I mean no … well maybe.

Is there something that creates classes in Ruby? Yes, the class Class is used to create new classes. (e.g. Class.new). All classes are instances of Class.

Is there something that defines the behavior of classes? Yes, any class can have its own behavior by defining singleton methods. The singleton methods go into the singleton class of the class.

Ruby doesn’t have a single “thing” that is a full metaclass. The role of a metaclass is split between Class (to create new classes) and singleton classes of classes (to define class specific behavior).

So, Singleton Classes Are Metaclasses?

You weren’t listening. Not all singleton classes are metaclasses. Only singleton classes of classes are metaclasses. And then only weak, partial metaclasses.

Does it Matter What We Call Them?

In the long run, probably not. Most people seem happy to (incorrectly) call them metaclasses, and this post is unlikely to change that behavior. Shoot, it seems the Rails team has already immortalized the term.

However, if reading this post has helped you understand what real metaclasses are, then it was worthwhile.

Mar 20 Source Control Made Easy

“Have I mentioned today how much git rocks?” — One of my office mates

I hear that spontaneous outpouring of appreciation for git about once a day. Usually it is someone in the office who just finished a task that would have been difficult with any of the source control systems we had used previously. Git has really impacted our day to day development process, and that’s the sign of a powerful tool.

It wasn’t always like this. I remember when EdgeCase made a rather abrupt switchover from subversion to git. I had only been dabbling with git at the time, but the guys in charge of our code repositories said “Here, this is good stuff. We’re switching … Now.”

Let me tell you, it was a little rough for a few days. Eventually we figured it out. Although we love the tool now, the learning curve was a bit steep to climb.

About two months ago we were talking in the office about git and how to encourage people to adopt it. We talked abou the need for a gentle introduction to git that quickly gets the user over the learning curve quickly. That gave me the idea for the “Souce Control Made Easy” talk that teaches the concepts behind git by starting from scratch developing the ideas behind git one by one.

A Pragmatic Screen Cast

Mike Clark of the Pragmatic Studio contacted me about turning the talk into a screencast that could reach a wider audience than the normal conference-going crowd. I’m happy to say that Source Control Made Easy is now available from the Prags.

If you are thinking about adopting git, or have already started using git but are still at the awkward stage, then this screen cast is design for you. The Pragmatic Studio page has a link to a preview of the screen cast. I hope you check it out.

Mar 20 Using p4merge with Git

Git doesn’t come with a merge tool, but will gladly use third party tools…

The Git Debate

The reoccurring debate on switching from svn to git is going on again on the Ruby Core mailing list. Amoung the many objections to git is that it doesn’t come with a nice merge tool. Perforce was held up as an example of a tool that does merging right. Although I’m not a big fan of perforce in general, the merge tool in perforce was one of its two redeeming aspects.

Now You Can Have Your Cake and Eat it Too!

Although it is correct that git doesn’t come with a nice merge tool, it is quite happy to use any merge tool that you have on hand. And since Perforce’s merge tool is available free (from here), you can use p4merge with git.

Just add the following to your .gitconfig file in your home directory:

[merge]
    summary = true
    tool = "p4merge" 
[mergetool "p4merge"]
    cmd = /PATH/TO/p4merge \
            "$PWD/$BASE" \
                "$PWD/$LOCAL" \
                "$PWD/$REMOTE" \
                "$PWD/$MERGED" 
    keepBackup = false
        trustExitCode = false

Now, whenever git complains that a conflict must be resolved, just type:

   git mergetool

When you are done resolving the merge conflicts, save the result from p4merge and then quit the utility. If git has additional files that need conflict resolution, it will restart p4merge with the next file.

Enjoy.

Interested in (not) Hearing about Git?

I’m doing a talk that’s not about git at the Ohio, Indiana, Northern Kentucky PHP Users Group (yes indeed, that acronym is OINK-PUG) on September 17th. Although the talk is explicitly not about git, you will come away from the talk with a much deeper understanding on what goes on behind the curtains with using git.

If there are other local groups interested in not hearing about git, feel free to contact me.

Update (6/Sep/09)

Several people have mentioned that it is not obvious where to get the p4merge tool from the perforce page. Go to the Perforce downloads page and click on the proper platform choice under “The Perforce Visual Client” section. When you download “P4V: The Visual Client”, you will get both the P4V GUI application and the p4merge application.

Oops, Another Update (7/Sep/09)

I forgot that the shell script that runs p4merge is something you have to create yourself. Here’s mine:

#!/bin/sh
/Applications/p4merge.app/Contents/Resources/launchp4merge $*

There are more detais Andy McIntosh’s site

Mar 20 The Adhearsion Demo From Mountain West Ruby Conf

Try Jay’s demo at home.

Jay Phillip’s Adhearsion Demo at the Moutain West Ruby Conf

Jay Phillip’s talk at MWRC attempted to get the audience involved in actually running an Adhearsion demo on their own laptops. Unfortunately, the demo at MWRC was plagued with firewall and network problems, but eventually I was able to get it working. Here are the steps needed.

Go ahead, try this at home. It’s a lot of fun.

Step 1—Sign up for an Adhearsion account.

You can do that here: http://adhearsion.com/signup

You will need a skype account to complete the sign-up. After signing up, you should get an email with a link that you need to click before your account is activated. Go ahead and activate the account now.

Step 2—Install the Adhearsion Gem

Run:

   gem install adhearsion

I’m running the 0.8.2 version of the gem.

Step 3—Create an Adhearsion project

Run:

  ahn create project_name

Step 4—Enable the Sandbox

Run:

  cd project_name
  ahn enable component sandbox

Step 5—Edit Your Credentials

Edit the file: components/sandbox/sandbox.yml and update the username and password you used when you created the Adhearsion account in step 1.

Step 6—Create a Dial Plan for the Sandbox

Edit the dialplan.rb file to contain the following:

adhearsion {
  simon_game
}

sandbox {
  play "hello-world" 
}

The adhearsion section should alread be in the file. You will be adding the sandbox section.

Step 7—Star the Adhearsion Server

Run:

  cd ..
  ahn start project_name
You should see:
INFO ahn: Adhearsion initialized!

Errors at this stage might mean that your adhearsion account isn’t setup properly, you don’t have the right user name and password (in step 5), or that you have firewall issues preventing you from connecting to the Adhearsion server.

Step 8—Call The Sandbox

Using Skype, call the Skype user named sandbox.adhearsion.com. You should hear a hello world message.

Step 9—Change the Dial Plan

Just for fun, change the dialplan.rb file to contain:

adhearsion {
  simon_game
}

sandbox {
  play "hello-world" 
  play "tt-monkeys" 
}

(Add the tt-monkeys line to the sandbox dial plan).

Now call the sandbox again (skyping user sandbox.adhearsion.com) to hear the change in the dial plan. Monkeys FTW.

More Examples

Here’s a example of what can be done in a dial plan. I was just goofing around with my dial plan.

adhearsion {
  simon_game
}

sandbox {
  play "vm-enter-num-to-call" 
  digits = input 1, :timeout => 10.seconds
  case digits
  when '1'
    play "hello-world" 
  when '2'
    play "tt-monkeys" 
  when '3'
    play "what-are-you-wearing" 
  when '4'
    play 'conf-unmuted'
  when '5'
    play 'tt-weasels'
  when '6'
    play "pbx-invalidpark" 
  when '7'
    play "1000", "dollars" 
  when '8'
    play "followme/sorry" 
  when '9'
    simon_game
  when '0'
    play Time.now
  else
    play "demo-nomatch" 
  end
  sleep 1
  play "demo-thanks" 
}

See http://adhearsion.com/examples for more dialplan examples.

That’s It

Think about what you are doing. You are calling the Adhearsion server and controlling how that remote server responds by the adhearsion program running on your own local box. That is wild.

The adhearsion sandbox makes it easy to play around with telephony programming without any investment in the associated hardware.

I hope this demo encourages you to give Adhearsion a try.

Mar 20 You Are Invited

All Rails Conf 2009 speakers are invited to a special event.

Who?

Anyone speaking at RailsConf 2009

When?

Sunday, May 3, 4:00PM – 6:00PM
(The day before RailsConf 2009 officially begins)

Where?

Las Vegas Hilton in Pavilion 1

What?

Presentations for Presenters.

Why?

You’ve come all the way to Las Vegas to tell the world about your latest Ruby/Rails project or idea. You want to make sure that you really get your message across. So, how do you do that?

The Presentations for Presenters session will give you practical tips for improving your RailsConf presentation. We will cover all aspects of planning, preparing, creating and delivering your talk, so that your unique message will get across to your audience.

Plus we will have a lot of fun. Hope to see you there.

What do I need to do?

Start planning now to attend. Since this session is actually the day before RailsConf officially begins, make sure that your travel plans gets you there in time.

Mar 20 Presenting for Presenters

If you are speaking at RubyConf this year, we have a special opportunity for you.

Are You Speaking at RubyConf 2008?

If so, congratuations! And have we got a deal for you …

Wednesday evening, Nov 5, at 6:00 pm, (that’s the night before the conference) we are inviting all speakers to a special training session. I’m going to be sharing some ideas for putting together and delivering a good presentation.

After my talk, Patrick Ewing and Adam Keys are geared up to do some Powerpoint Karaoke with everyone there. I’m not even sure what Powerpoint Karaoke is, but it sounds like fun.

I hope to see everyone there.

Update (4/Nov/08)

I’ve talked to Adam today. He says that Patrick isn’t going to able to make RubyConf this year, but we will be ready to roll with Powerpoint Karaoke anyways.

Update (5/Nov/08)

It looks like the speakers training will be in the Olympic Room tonight. The Olympic Room is on the same floor as the registration desk. Go to the left past the elevators and turn right down that hall (or ask someone who looks like they know what they are doing).

Mar 20 Articles are Back!

I’ve received a lot of requests for my old articles …

The Article Section has been Restored

When I changed to my new hosting machine, I moved all my blog posts but didn’t move any of the articles. Of course I intended to move them eventually but never got around to it.

A lot of people have been asking for this article or that presentation, or pointing out that a number of old bookmarked links are no longer any good. So due to popular demand the Articles and Presentations section of onestepback.org is now restored.

Enjoy

Mar 20 Comments Are Now Enabled

I’ve gone without comments on this blog for a long time …

Comments via Disqus

I’ve gone through several commenting systems for this blog over time. First was the really cool TagSurf application that allowed commenting on about any web page on the internet arbitrary tags. Unfortunately, TagSurf died a (in the words of its creator) “well deserved” death.

Then I tried a wiki for comments. That worked pretty good (aside from spam issues), but setting up a new page for comments for each new post was just too much hassle.

Now I’m trying Disqus for comments. It only took an hour or so to integrate Disqus with my ancient blogging engine (anyone else still using Rublog?).

Kick the tires and see how it works. If you have feedback … well, just leave a comment.

I guess this means I’ll have to start writing some real content here so there will be something worth commenting on … let’s see if there is anything I feel like ranting about …

(Oh, and a hat tip to Ryan Briones for pointing out Disqus when I was ready to go out and implement something from scratch.)

Mar 20 RedMine For Rake

The is now a RedMine setup for Rake, FlexMock and Builder.

RedMine

As part of an effort to get better control of changes to the my open source projects, I’ve setup a RedMine issue tracking site for Rake, FlexMock and Builder. You can find it at http://onestepback.org/redmine.

Mar 13 A Purely Functional Tale of a Bridge, Compose of Hubris ...

My slides from my MountainWest RubyConf 2010 presentation (plus some addedl resource links) are here. [PDF, 13MB]

Mar 9 At least it's not a tramp stamp, Dame Commander

“I decided to get a tattoo because it was the most shocking thing I could think of doing… Now I’m utterly disgusted and shocked because it’s become completely mainstream, which is unacceptable to me.”

Helen Mirren ‘Disgusted’ by Her Drunken Tattoo

Incidentally, in the mediocre film 2010 Mirren plays a tough Russian cosmonaut with a bad perm. It’s basically the hottest thing I’ve ever seen.

Mar 7 There's a team deathmatch in my mouth, and everybody's invited

Next-generation video game cereals:

Kotaku ‘Shop Contest: Next-Gen Cereal System Edition Winners

Mar 5 A Technique for Creating a Talk

So, I’m giving a talk a week from today, about Hubris. I’ve been working out the key points and concepts I want to cover, but don’t have a final version. Just some notes and sketches.

However, I’ve been sort of running the talk through my head, imagining what I’ll say. It’s a useful technique, but it’s pretty intangible. I was thinking I should just write out the whole thing, as a one or more essays or blog posts, and go from there.

But I was curious about how long the talk might end up being. I have 30 minutes, and planned on four key topics or concepts, plus there’s some intro time as well. That makes for about 7 minutes a key concept. Hmm ….

About a year ago I gave a talk at an Ignite event. The rules are, you get 20 slides that auto-advance at 15-second intervals. Pretty terse.

My talk was to be a shorter version of my JRuby/Wii hacking presentation from MountainWest RubyConf 2009. That talk was planned for 30 minutes, but I think I ended up running through it in about 20.

To see what would fit into the shorter version, I decided to just wing it. I used my G1 voice recorder to record my impromptu presentation, seeing how well I could cover the material in my alloted five minutes.

Amazingly, my first take was timed just right. Maybe having slides to work with helped.

I then took my crude one-take version and refined it to match 20 slides (some pre-existing, many new to compress content). When I had something I liked, I rehearsed it about twenty times.

For my Hubris talk I thought I would try something similar. Instead of the G1 app, I set up Screenflow screencasting software on my Mac.

I had thought that I could, while inventing my talk, scribble out my slides. That I didn’t do; I ended up just describing slides and screen actions at different points while recording.

This time around the results were plain horrible. Apparently, refining an existing talk makes for a better ad-hoc presentation than working from a collection of notes and sketches. Go figure.

But this was a good thing. It made very clear that a) I really did need to think through the overall architecture of the talk, and b) carefully whittle down the material.

One reason my improv was such a mess was that, while covering this or that topic, I realized I was out of alloted time and needed to move on to the next key area. I needed up with a lot of unclear, where-is-this-going, new-here’s-something-new babbling.

On the bright side it was nice to know that lack of content was not going to be a problem.

My next step for today is to force myself to listen again to the whole rambling mess to see just where I stumbled, and to pick out the stray thoughts that apparently made sense on the spot.

I’ll then work out a better outline, and take another shot at winging it. I’ll use Screenflow again, and as the talk gets better I can start inserting slides or notes into the screencast.

What’s appealing about this technique is that it gives me an idea of how well I know the material, and helps develop a talk that should flow more naturally than if I were to just write it all out first.

If I have trouble describing something off the top of my head then I either need to bone up on it, or drop it from the talk. If a topic comes out sounding awkward or incomplete I’m better off rephrasing it or skipping it.

The slides should play better too, since they’ll be integrated into an organic piece instead of planned in some abstract setting.

The MountainWest talks will be recorded and made freely available, so you’ll be able to see how well my scheme works.

Mar 3 Counting down to MountainWest RubyConf

If you’ve not registered for next week’s MountainWest RubyConf you’re making a big mistake.

In addition to getting to see me give a talk on Hubris (subtitled A Purely Functional Tale of a Bridge, Composed of Hubris and Sharing and an Infinite List of Lazy Observations for your Evaluation, with an Inevitable Appearance by One or More Trolls), EngineYard is again sponsoring a Hackfest in their suite at the Hilton. Sweet!

Don’t be L7. You know you should be there.

Mar 3 A quick RVM rundown
(It so happens I'm presenting this at Dallas.rb tonight. Hopefully it can also be useful to those out in internetland too.)

RVM gives you three things:

First, let's install RVM:

Now, let's install some Rubies:

The other trick that RVM gives us is the ability to switch between different sets of installed gems:

Some other handy things to peruse:

I also promised you some extra sanity:

A couple other things RVM tastes great with:

Feb 27 City views

The Sandpit from Sam O'Hare on Vimeo.

Feb 22 Next steps for Monkeybars + Rawr

As of today I am the admin for the Monkeybars and Rawr projects

I’m taking over from Logan Barnett who has, without a doubt, done a fantastic job with these projects. (And of course big props to David Koontz as well. David and Logan have been the magicians behind Monkeybars and Rawr.)

My immediate plans:

The means not just going through the code, but getting more familiar with Kenai

These are forks of rawr and Monkeybars, created to make it easier for me to pursue certain design, packaging, and business goals. It worked well for me, but it’s less useful overall to have multiple projects that are kinda sorta the same.

I don’t want to impulsively just merge in the features that distinguish my forks, but I know that at least some of them have good use cases and should be made regular features.

However, I hope to get some feedback from current rawr and Monkeybars users to see how best to go about things.

It is quite likely that I will move things off of Kenai. I’ve never really liked the site; the mailing list has wonky navigation, and I’d prefer to just use github for the repo. Bug tracking is another matter. Github’s issue tracking is OK, but not terribly robust. Pivotal Tracker may be a better choice.

But there may be features or options in Kenai that I’m unaware of, especially regarding the integration of tools, so I need to do a bit of homework.

If you are a user of Monkeybars or Rawr let me know your thoughts on the Kenai services.

Feb 19 The imperfection of our tools

I enjoy a well-crafted application. I place a high value on attention to detail, have opinions on what design elements make an application work, and try to empathize with the users of applications I'm involved in creating. Applications with a good aesthetic, a few novel but effective design decisions, and sensible workflow find themselves in my Mac's dock. Those that don't, do not.

The applications I observe fellow creators using to create often don't fit into their environment. They don't fit into the native look-and-feel. They ignore important idioms. Their metaphors are imperfect, the conceptual edges left unfinished.

In part I notice this because as creators we tend to live in a few different applications, and time reveals most shortcomings. But in part, I notice this because the applications are in fact flawed. Flawed to the point, that you would think given my opening words, that I would refuse to use them. And indeed, I refuse to use many of the applications that others find completely acceptable for making the same kinds of things I do.

Increasingly, it seems the applications that people who create things live in offer a disjoint user experience. I'm thinking of visual people living in Photoshop or Illustrator or developers living in Emacs or Terminal.app. We use these applications because they best allow us to make what we want and get in our way only a little bit. But, it's a tenuous relationship at best.

What's this say about what we're doing and the boundaries that we operate along? Would we accept the same kinds of shortcomings in say, a calendar application or a clock widget, if those were central to our workflow? That is, is there something about the creative process that leads us to accept sub-perfect tools? Is it inevitable that someone seeking to make new things will find their tools imperfect? Is the quest for ever-more perfect tools part of how we grow as makers?

I hate closing with a bunch of questions, but this piece is but an imperfect tool for discovering an idea.

Ed. Closing could use some work.

Feb 13 Francis became the mayor of the produce aisle

Seen in the window of a C-Town grocery store. I’m not a foursquare user myself, but is there any point to this? Wouldn’t a grocery store be the most banal check-in ever?

Feb 12 Warning: politics

Embedded within the migraine that is American politics are some very interesting ideas. Economics, markets, ethics, freedom, equality, education, transportation, and security are all intriguing topics. Recently, I figured out that the headache comes not from people or trying to make the ideas work, but in politics. Getting a majority of the people to agree on anything is a giant pain of coordination. When you throw in fearmongering, power struggles, critically wounded media, and the fact most people would rather not think deeply about any of this you end up with the major downer that we face today.

All that said, here are some pithy one-liners about politics:

There, have I offended everyone?

Feb 11 Cognitive regulatory capture--all the way to the top?

I’m generally a fan, if not a full-throated one, of the Obama administration. I admire and respect his dedication to the issues and his attempts to stay substantive at the center of the chattering pundit maelstrom that is contemporary Washington. I’m willing to give him lots of leeway because he 1) inherited a horribly broken country from his predecessor and 2) has to govern a country where a substantial minority of its citizens are insane, and loudly so. And I don’t agree with every policy direction coming from his White House, but I generally trust that it’s coming from a team of smart, passionate people who are doing their best at the hardest jobs in the world.

But I’m sorry, this interview is fucking horrifying:

Obama Doesn't ‘Begrudge' Bonuses for Blankfein, Dimon

The president, speaking in an interview, said in response to a question that while $17 million is “an extraordinary amount of money” for Main Street, “there are some baseball players who are making more than that and don't get to the World Series either, so I'm shocked by that as well.”

“I know both those guys; they are very savvy businessmen,” Obama said in the interview yesterday in the Oval Office with Bloomberg BusinessWeek, which will appear on newsstands Friday. “I, like most of the American people, don't begrudge people success or wealth. That is part of the free-market system.”

If Obama actually believes those words, then we are really seriously fucked.

(Via naked capitalism)

Feb 4 Chatroulette: Occasionally funnier than some naked dude alone in his room

God bless the intrepid souls who go on to Chatroulette! to do video chat with totally random strangers. Without their brave explorations, we’d never get screenshots like these:

The 24 Best Chat Roulette Screenshots

Feb 3 Unleash

Feb 2 Your neighbors are going to love this one

A video game where you play by screaming:

Jan 29 "I forgot he was black tonight"

So apparently between Andrew Sullivan, James Fallows, and Ta-Nehisi Coates, I’m basically a full-on Atlantic fanboy now. TNC has a pretty great takedown of Chris Matthews saying that during the State of the Union, he forgot Obama was black. Does that say more about Obama, or about what Chris Matthews thinks it means to be black?

Around these parts, we’ve been known, from time to time, to chat about the NFL. We’ve also been known to chat about the intricacies of beer. If you hang around you’ll notice that there are no shortage of women in these discussions. Having read a particularly smart take on Brett Favre, or having received a good recommendations on a particular IPA, it would not be a compliment for me to say, “Wow, I forgot you were a woman.” Indeed, it would be pretty offensive.

The problems is three-fold. First, it takes my necessarily limited, and necessarily blinkered, experience with the fairer sex and builds it into a shibboleth of invented truth. Then it takes that invented truth as a fair standard by which I can measure one’s “woman-ness.” So if football and beer don’t fit into my standard, I stop seeing the person as a woman. Finally instead of admitting that my invented truth is the problem, I put the onus on the woman. Hence the claim “I forgot you were a woman,” as opposed to “I just realized my invented truth was wrong.”

Ditto for Chris Matthews. The “I forgot Obama was black” sentiment allows the speaker the comfort of accepting, even lauding, a black person without interrogating their invented truth.

Jan 27 A great society, ill-served by its government

James Fallows’ cover story in The Atlantic, How America Can Rise Again, is worth a read. He talks about the current round of historical declinism, and notes that in many measures the culture of the U.S. is still a strong asset:

The simplest measure of whether a culture is dominant is whether outsiders want to be part of it. At the height of the British Empire, colonial subjects from the Raj to Malaya to the Caribbean modeled themselves in part on Englishmen: Nehru and Lee Kuan Yew went to Cambridge, Gandhi, to University College, London. Ho Chi Minh wrote in French for magazines in Paris. These days the world is full of businesspeople, bureaucrats, and scientists who have trained in the United States.

Today's China attracts outsiders too, but in a particular way. Many go for business opportunities; or because of cultural fascination; or, as my wife and I did, to be on the scene where something truly exciting was under way. The Haidian area of Beijing, seat of its universities, is dotted with the faces of foreigners who have come to master the language and learn the system. But true immigrants? People who want their children and grandchildren to grow up within this system? Although I met many foreigners who hope to stay in China indefinitely, in three years I encountered only two people who aspired to citizenship in the People's Republic. From the physical rigors of a badly polluted and still-developing country, to the constraints on free expression and dissent, to the likely ongoing mediocrity of a university system that emphasizes volume of output over independence or excellence of research, the realities of China heavily limit the appeal of becoming Chinese. Because of its scale and internal diversity, China (like India) is a more racially open society than, say, Japan or Korea. But China has come nowhere near the feats of absorption and opportunity that make up much of America's story, and it is very difficult to imagine that it could do so—well, ever.

But Fallows is far less sanguine about the state of the federal government, noting that “one thing I've never heard in my time overseas is ‘I wish we had a Senate like yours.’” The government’s stability and continuity, he argues, as ironically part of why it is so subpar today:

The most charitable statement of the problem is that the American government is a victim of its own success. It has survived in more or less recognizable form over more than two centuries—long enough to become mismatched to the real circumstances of the nation…

Every system strives toward durability, but as with human aging, longevity has a cost. The late economist Mancur Olson laid out the consequences of institutional aging in his 1982 book, The Rise and Decline of Nations. Year by year, he said, special-interest groups inevitably take bite after tiny bite out of the total national wealth. They do so through tax breaks, special appropriations, what we now call legislative “earmarks,” and other favors that are all easier to initiate than to cut off. No single nibble is that dramatic or burdensome, but over the decades they threaten to convert any stable democracy into a big, inefficient, favor-ridden state. In 1994, Jonathan Rauch updated Olson's analysis and called this enfeebling pattern “demosclerosis,” in a book of that name. He defined the problem as “government's progressive loss of the ability to adapt,” a process “like hardening of the arteries, which builds up stealthily over many years.”

Fallows cites specific problems, not that novel to people who care about such things: The fact that Senate votes are absurdly nonproportional to population, the overuse of the filibuster, the stasis of gerrymandering on state and federal levels. I would add to that a massive top-down complexity. Democracy is not well-served when the country’s highest governing bodies routinely pass laws that are too long for any one person to read.

What I find disappointing in all this is that some of these problems routinely disadvantage the left, but the left by and large doesn’t have much to say about them. If Senate representation actually gave enough votes to people living in large cities, we would’ve passed health care reform by now. But the left also generally loves centralized government solutions, so I suppose that makes it hard to argue that the centralized government we have now is deeply flawed.

As for how to fix these massive structural problems: Fallows doesn’t seem to believe it can be fixed, just that we’ll muddle through. And maybe that’s realistic, but it’s also pretty depressing to contemplate. Personally, I’d be happy if people in the more populous states continued a modified version of Grover Norquist’s work, shrinking the federal government and working to supplant as many services as possible at the state and inter-state level. The goal would not be to drown the federal government in Grover’s bathtub, but simply to participate less in a federal government that takes a lot of their taxes and gives them way less votes than Wyoming. That could conceivably lead to some Constitutional amendments that might rejigger the Senate somehow. It’s a pipe dream, obviously. But given enough time, the rot in U.S. government could destroy what’s special about U.S. society, so it’s probably not a bad time for a little brainstorming.

Jan 19 Goodbye, gutbombs

Last March my wife and I joined a gym, started working out with a trainer, started trying to eat better, and thusly set out to improve our health. Amazingly, we've stuck with it (after two previous failed attempts in years past) and are both in much better shape than we've been in for quite some time.

One of my personal reasons for doing this was what I'd been hearing about the correlation between working out, eating better, and brain function. Lots of people who read way more into this than I do had been saying that if you eat better and exercise more, your brain will work better.

I've noticed this first hand. The day after my first serious run, my mind was in overdrive. I had lots of great ideas, I worked through them quickly, and I didn't procrastinate when it came to exploring or realizing them.

Today, I had the opposite experience. I went out for a rather large Tex-Mex lunch. Lots of starch. I got home and took a nap, as is often my wont. Usually I wake up ready to get back to work after my naps. But today was different. My brain was thoroughly sluggish. My body's energy was going towards digestion, not thought.

I guess this is something of a break-up letter for me. You see, I've long enjoyed the large, starchy lunch. But, I'm not sure I can put up with it anymore. If its a choice between starchy, tasty lunches and a high-functioning brain, I'm going to have to choose my brain.

Sorry, lunch-time gutbombs. We had a good run, but I'm going to have to quit you for a while.

Jan 9 Lymbyc Systym playing in Tempe, Jan 13

Even if they might not still be a local band, Lymbyc Systym make great noises. They’re playing in Tempe on January 13, at the Sail Inn. Well worth checking out.

Here’s a sampling of their stuff, via Grooveshark:

<object height='238' width='221'> <param></param> <param></param> <param></param> <param></param> <embed src='http://listen.grooveshark.com/widget.swf' height='238' width='221'></embed></object>
Dec 23 Give attribute_mapper a try

(For the impatient: skip directly to the `attribute_mapper` gem.)

In the past couple months, I've worked on two different projects that needed something like an enumeration, but in their data model. Given the ActiveRecord hammer, they opted to represent the enumeration as a has-many relationship and use a separate table to represent the actual enumeration values.

To a man with an ORM, everything looks like a model

So, their code ended up looking something like this:

class Post < ActiveRecord::Base
 
  belongs_to :status
 
end
 
class Status < ActiveRecord::Base
 
  has_many :tickets
 
end

From there, the statuses table is populated either from a migration or by seeding the data. Either way, they end up with something like this:

# Supposing statuses has a name column
Status.create(:name => 'draft')
Status.create(:name => 'reviewed')
Status.create(:name => 'published')

With that in place, they can fiddle with posts as such:

post.status = Status.find_by_name('draft')
post.status.name # => 'draft'

It gets the job done, sure. But, it adds a join to a lot of queries and abuses ActiveRecord. Luckily…

I happen to know of a better way

If what you really need is an enumeration, there's no reason to throw in another table. You can just store the enumeration values as integers in a database column and then map those back to human-friendly labels in your code.

Before I started at FiveRuns, Marcel Molina and Bruce Williams wrote a plugin that does just this. I extracted it and here we are. It's called attribute_mapper, and it goes a little something like this:

class Post < ActiveRecord::Base
  include AttributeMapper
 
  map_attribute :status, :to => {
    :draft => 1,
    :reviewed => 2,
    :published => 3
  }
end

See, no extra table, no need to populate the table, and no extra model. Now, fiddling with posts goes like this:

post.status = :draft
post.status # => :draft
post.read_attribute(:status) # => 1

Further, we can poke the enumeration directly like so:

Post.statuses # => { :draft => 1, :reviewed => 2, :published => 3 }
Post.statuses.keys # => [:draft, :reviewed, :published]

Pretty handy, friend.

Hey, that looks familiar

If you've read Advanced Rails Recipes, you may find this eerily familiar. In fact, recipe #61, “Look Up Constant Data Efficiently” tackles a similar problem. And in fact, I'm migrating a project away from that approach. Well, partially. I'm leaving two models in place where the “constant” model, Status in this case, has actual code on it; that sorta makes sense, though I'm hoping to find a better way.

But, if you don't need real behavior on your constants, attribute_mapper is ready to make your domain model slightly simpler.

Dec 9 Just For Fun

This year was my fourth RubyConf. I've always come away from RubyConf energized and inspired. But, I've yet to follow through on that in a way I found satisfying. I have a feeling I'm not alone in that camp.

This was the first year I've given a presentation at RubyConf. At first, I had intended to use this watershed-for-me opportunity to ask whether Ruby was still fun. There's been a number of “drama moments” since my first RubyConf; I thought it might be worth getting back to my early days of coding with Ruby, when I was exploring and having a great time turning my brain inside out.

As I started researching, it turned out that there are a lot of people having fun with Ruby. Some are doing things like writing games, making music or just tinkering with languages. Others are doing things that only some of us consider fun. Things like hacking on serious virtual machines, garbage collection, and asynchronous IO frameworks.

So, back to my talk. I saw my failure to harness the motivation what I'd seen at previous years at RubyConf as an opportunity to figure out ways to line up some tactics to make sure that after the conference, I was able to create awesome things, contribute them back to the community, and enjoy every minute of it.

Thus, I came up with a sort of “hierarchy of open source developer needs”. At the bottom is enjoyment; there's little sense doing open source work if you're not having fun. Once you're having fun, you probably want to figure out how to find more time for making codes. Once you're making more codes, you want to figure out how to get people interested in using your stuff. I've taken these three needs and identified several tactics that help me when I find myself in a rut or unable to produce. Call them patterns, practices, whatever; for me, they're just tricks I resort to when the code isn't flowing like I want to.

The talk I ended up with is equal parts highlighting people in the Ruby community that are having fun and highlight ways to enjoy making things and contributing it back to whatever community you happen to be part of. I hope that I avoided sounding too much like a productivity guru and kept it interesting for the super-technical RubyConf crowd.

If all of this sounds interesting you, grab the slides (which are slightly truncated, no thanks to Keynote) or watch the recording from the conference itself.


I wrote the proposal for this talk right after Why disappeared himself. His way of approaching code is what inspired me to write a talk about getting back to coding for fun. “Just for Fun” starts with a tribute to Why the Lucky Stiff. The sense of fun and playfulness that Why had is important to the Ruby community. I've tried to highlight some of his most interesting playful pieces. And in the end, I can't say “thanks” enough. Why has inspired me a lot and I'm glad I got to meet him, experience him and learn through his works.

Even if you don't take a look at my presentation, I strongly urge you to give a look at some of Why's works and let them inspire you. My favorites are Potion and Camping.


Some other things I mentioned in my talk as interesting or fun:

Dec 2 MountainWest RubyConf 2010

Planning is underway for yet another amazing edition of MountainWest RubyConf. MWRC 2010 will be held in Salt Lake City, UT, March 11 and 12, 2010.

Talk proposals are being accepted as well. Go here and submit yours.

Nov 30 Curated Awesome, the 2nd

The awesome Samson and Delilah, “Emilioooooo!”, Belushi and a skinny tie, contemplating the important stuff, The Rule of Least Power, step into the cypher, and Molly.

Nov 6 The World of Eric Torres

I had a great time last night at TinyArmy. Daniel Davis and Eric Torres gave their “Alter Egos” talk from Phoenix Design Week. Very good presentation, both in style and in content.

Much of what they said connected with what I know and have heard about running a small, self-funded start up. Managing work; rejecting jobs that don’t further your true goals; dedicating time; not neglecting your family. Good stuff.

A real treat, though, were the slides, which featured a mixture of art by Daniel and Eric. I’m well familiar with Daniel’s art, but for whatever reasons did not know Eric’s work.

The World of Rynaga makes use of crisp lines and repeated shapes, plus striking color schemes, to create a cohesive universe.

Great work you should be paying attention to.

Oct 28 The Kindle’s sweet spot

Given all the hubbub about Kindles, Nooks and their utility, I thought this bears repeating to a wider audience:

The Kindle is great for books that are just a bag of words, but falls short for anything with important visuals.

I've really enjoyed reading on my Kindle over the past year. You can't beat it for dragging a bunch of books with you on vacation or for reading by the poolside. That said, I don't use it to read anything technical with diagrams or source code listings. I certainly wouldn't use it to read anything like Tufte, which is exactly why his books aren't available on the Kindle. Where the Kindle shines is with pop-science books like Freakonomics and Star Wars novels1.

If you love books and reading, the Kindle is a nice addition to your bibliophilic habit, but it's no replacement for a well-chosen and varied library.

1 Did I say that out loud? Crap.

Oct 28 Testing declarative code

I'm a little conflicted about how and if one should write test code for declarative code. Let's say I'm writing a MongoMapper document class. It might look something like this:

class Issue

  include MongoMapper::Document

  key :title, String
  key :body, String
  key :created_at, DateTime

end

Those key calls. Should I write a test for them? In the past, I've said “yes” on the principle that I was test driving the code and I needed something to fail in order to add code. Further, the growing ML-style-typing geek within me likes that writing tests for this is somewhat like constructing my open wacky type system via the test suite.

A Shoulda-flavored test might look something like this:

class IssueTest < Test::Unit::TestCase

  context 'An issue' do

    should_have_keys :title, :body, :created_at

  end

end

Ignoring the recursive rathole that I've now jumped into, I'm left with the question: what use is that should_have_keys? Will it help someone better understand Issue at some point in the future? Will it prevent me from naively breaking the software?

Perhaps this is the crux of the biscuit: by adding code to make certain those key calls are present, have I address the inherent complexity of my application or have I imposed complexity?

I'm going to experiment with swinging back towards leaving these sorts of declarations alone. The jury is still out.

Oct 26 Texas is its own dumb thing

Southern American English

OK, here's the deal. Wikipedia has it all wrong.

  1. Texas is not part of the South. Texas is its own unique thing. Sure we have dumbasses, but they are our dumbasses, wholly distinct from your typical Southern dumbass.
  2. In Texas, the way you refer to “you all” is “ya'll”; it's a contraction of “ya all”.
  3. They neglected to mention the idiomatic pronunciation of words like “oil” (ah-wllllll) or “wash” (warsh).

Please take it under consideration: Wikipedia is edited by a lot of damn Oklahomans.

Oct 19 (J)Ruby and Android Development - 22 October 2009

I’ll be giving a presentation at the next Phoenix Android Developers Group meeting on 22 October 2009.

I’ll be talking about suing Ruby and JRuby for Android development. The talk is broken into three main parts:

The main focus, though, will be on the last two items. However, I’ve been using (and extending) Andi while I do Android development, so an overview of that tool (and using Ruby more generally) to augment your developer toolbox helps round out the discussion.

When: 22 October 2009

Where: OpenRain HQ
2220 South Country Club. Rd.
Suite #107
Mesa, AZ

Time: 6:30pm

Map to the meeting.

Doors open at 6:30pm; actual talk kicks off at 7pm.

Oct 17 Android development helper tool Andi, version 0.2.0, released

I just uploaded an updated gem for Andi, the helper tool for Android application development.

See the Neurogami post for details.

Oct 17 The Web, for Artists, so far

I’ve bundled up the drawings thus far into a largish PDF: The Web, for Artists

The trick now is to keep making time to finish it.

The plan is to intersperse the drawings with some expository text to fill in the numerous details.

Oct 8 Desert Code Camp - Nov. 7 2009

Another edition of Desert Code Camp is right around the corner. November 7. 2009

The session/wish-list schedule page is up, so now’s the time to see about maybe giving a presentation.

Oct 4 The Web, for Artists

I’m honored to be the speaker at the next Tiny Army meeting.

Tiny Army is the brainchild of Daniel Davis, he of Monster Commute fame. It’s a monthly gathering of Phoenix-area artists and illustrators.

Basically, the talk will be about assorted Internet geekery (What exactly is the Internet? What’s a domain name? What’s a hosting service? What’s HTML? Is that the same thing as PHP? Is it contagious? ) for people who are not Internet geeks.

And I’m doing a comic to help ‘asplain it all.

Web for Artists

There are great opportunities for artists to get their stuff on the Web, and a little tech knowledge can help guide some key decisions.

When: Wednesday, October 7th, 6 pm

Where: Art Institute of Phoenix

2233 W Dunlap Ave # 109, Phoenix, AZ‎

We’re meeting in Room 239.

Take the elevator to the 2nd floor and make an immediate right as you step out the doors and you’ll come to a hall.

Make a left down the hall.

Follow the hall down & it dead-ends into Rm. 239.

Sep 23 Poker Night Fundraiser for HeatSync Labs

HeatSync Labs, the Valley's hackerspace, is having a fundraiser.

Poker Night

Theme: Poker Night! And Other Nefarious Deeds…

Date: October 3, 2009

Time: 6-10 pm

Location: Mesa FOP Lodge 9 (the current regular HSL meeting place; 1452 E. Main St., Mesa, AZ 85203M)

Tickets: Pre-sale (available at the Oct. 1 HeatSync Lab meeting) $10 pp and $12 couples, Door $12 pp and $18 couples.

HeatSync Labs is a grassroots, non-profit hacker group trying to jump-start a real hackerspace for the Phoenix area. They meet every 1st and 3rd Thursday of the month at 8:00PM at the Mesa F.O.P. Lodge.

Drop by, and consider helping out by supporting this fund raiser.

Sep 2 From the O'Reilly Ruby Blog

I used to write the occasional post for the O”Reilly Ruby blog. It’s more or less faded away, but I still like a few of my longer pieces. I’ve collected these over on the Neurogami site

Aug 31 Staying on task while encountering new bugs

I have a new post up on the Ruby Best Practices blog: James will be right back after these interruptions

I’m a big fan of automating mundane tasks. The typical process is that I’ll hack out something barely functional, and over time weigh the annoyance of lack of features against effort required to add or fix something. Sometimes things just stay simple; the ”@” script, for example. Other times I end up growing a library. See Todoist-NG, for example.

Often things just settle into a state of “good enough”. That’s the case with Todoist-NG; I’ve been using GitHub for pretty much all my OSS projects lately, but this is one that somehow never made the migration from Gitorious. I’m pretty sure it’s because I’ve not had to change anything in a while. WFJ.

I’ll move it, though; it’s easy. I think that’s one reason I really like GitHub. Creating a new repo is largely frictionless, so I tend to do it for even minor things. I can then make apps, snippets, gems, and so on available to whoever is interested, but without the sense of formality one gets from a RubyForge.org project. The feeling of “might as well” is a big aid in making more code available to more people.

Likewise with helper apps; if I find even a small bug or quirk, or think of a possible feature, I figure I might as well make a note of it since it’s so easy.

Jun 10 Agile Diary




Dear Diary:

I had a goal in January to write a series of ongoing blog posts called Agile Diary.

While a lot has been written about various Agile methods, rather than a presenting a methodology or case studies, I thought a regular, diary entries might paint a different picture and provide different insights.

I hope to at least talk about:

  • The situation
  • What my initial goals were
  • The initial plan
  • how we were able to follow
  • what we had to adapt to
  • failures as well as success

Naturally as situations will always change, we will always iterate through the above --- Diary Iterations, per se.

So I'm 5 months behind, I'll try to write some fill in articles and catch up.



Forrest
May 11 We need both engineers and artists in programming

Uncle Bob delivered a compelling keynote at RailsConf last week that put forth the argument that what we need most in programming is more professionalism. I loved the delivery, but I disagree with the conclusion.

I originally never wanted to be a programmer exactly because I thought the only type of programmers that existed where the kind that Bob talked about: The engineers with the proud professional practices that never wavered under pressure.

While I deeply respected that stature, it just never felt like a place that I belonged. I didn't identify with the engineering man or the seriousness of the efforts he pursued. Before I discovered Ruby, I felt in large parts that I was just faking my way along in this world. Here at a brief time for rent.

But that all changed when I found Ruby and a community consisting as much of artists as engineers. People waxing lyrically about beautiful code and its sensibilities. People willing to trade the hard scientific measurements such as memory footprint and runtime speed for something so ephemeral as programmer happiness.

That's where I found an identity that I could finally relate to directly. That's when I finally got really passionate about what I do for a living and started to blossom my own participation.

Now the wonderful thing about this new age of programming is that we need and prosper from both types of programmers. I believe Ruby is such a fantastic community and platform exactly because both types are coming together and sharing with each other. The bazaar is so much richer when the cultural backgrounds of the participants are diverse.

So while I love the idea of Bob's green wristband that reminds him always to do test-first development and his own personal professional oath, that level of adherence has never worked for me. I never had the discipline it takes to fulfill such a lofty goal of professionalism.

Now Bob may think that there's no place for people like me in programming (I sure know plenty of people who do!), I obviously think that would be a mistake. Not just because I've grown rather fond of what I do, but because I've seen so many other unprofessionals just like me come in and add those delicious twists that can really change things.

We aren't perfect. We often swear, act unresponsively, and can certainly be characterized as unprofessional a lot of the time. But I think that together with professionals like Bob, we stand a good chance leaving the world of programming in a better condition than we found it.

May 1 So how do we get more women into Rails?

Now that the internet hysteria is dying down, I'd love to explore some of the more concrete things that we could do to actually get more women involved. As I've stated earlier, I doubt simply refraining from having saucy pictures of pole dancers is going to do the trick. If that was all it'd take, it'd be easy beans.

There's going to be a session called Women in Rails at RailsConf next Tuesday, which is bound to be focused a lot of this, but there'll undoubtedly be a lot of good ideas outside of that group as well that we shouldn't wait to get going on. Here are a few ideas to get started with:

Share your discovery story
For the women already in Rails, it'd be great to hear what in particular attracted you to the platform. Highlighting areas of the ecosystem that could get even more support. Perhaps there was an especially well-written introduction that just made everything click. Perhaps a screencast or an interview or something else.

Highlight local communities with women
There are a bunch of local Rails user groups all over the place. If women could get an idea of which groups already had other women present there, it'd probably be a less daunting thought to attend. Knowing that there's at least going to be one other woman in attendance could help a bunch.

Can we pair up with other communities?
Programming communities may indeed often be awfully short on women, but programmers interact with plenty of other professions that are not. I wonder if there are ways where we could get women from, for example, the design community to intermingle on projects like Rails Rumble day. Sorta how the police academy and the nurses in training always throw joint parties in Denmark.

I'd love to hear more and would be more than happy to help promote and push it. Despite the spasm over that one talk and the underlying differences of opinion exposed by it, there's no reason we can't use this as a jumping point to do something about the actual, core issue.

So either email, tweet, or blog your suggestions and stories and I'll use this space to help point it out. Let's treat the low number of women in the community as a bug, cut-out most of the needless bluster, and work on some actual patches. Onward and upwards!

Apr 27 Alpha male programmers aren't keeping women out

I just can't get into the argument that women are being kept out of programming because the male programmer is such a testosterone-powered alpha specimen of our species. Compared to most other male groups that I've experienced, the average programmer ranks only just above mathematicians in being meek, tame, and introverted.

When I talk to musicians, doctors, lawyers, or just about any other profession that has a fair mix of men and women, I don't find that these men are less R rated than programmers and that's scaring off women from these fields. Quite the contrary in fact.

When I sit down with any of these groups, I usually find that I'm the one blushing. Yet that atmosphere some how doesn't keep women from joining any of these fields. It's from that empirical observation that I draw the conclusion that this argument is just bullshit.

Now that doesn't mean the underlying problem isn't worth dealing with. It absolutely is! I think that the world of programming could be much more interesting if more women were part of it. I wish I knew how to make that happen. If I find out, I'll be the first to champion it.

But in the mean time I don't think we're doing anyone a service by activating the WON'T SOMEBODY THINK OF THE CHILDREN police and squash all other sorts of edges and diversity in the scene.

You certainly have to be mindful when you're working near the edge of social conventions, but that doesn't for a second lead me to the conclusion that we should step away from all the edges. Finding exactly where the line goes — and then enjoying the performance from being right on it — requires a few steps over it here and there.

Apr 27 I'm an R rated individual

I've found that the fewer masks I try to wear, the better. This means less division between the personality that's talking to my close personal friends, socializing with my colleagues, and for interacting with my hobby or business worlds.

Blending like this isn't free. You're bound to upset, offend, or annoy people when you're not adding heavy layers of social sugarcoating. I choose to accept that trade because my personal upside from congruence is that I find more energy, more satisfaction, and more creativity when the bullshit is stripped away.

This means that it leaks out that I love listening to Howard Stern, that Pulp Fiction is one of my favorite movies, that I laugh out loud at Louis CK's Bag of Dicks joke, that I whole-fully accept my instinctual attraction to the female body, that I think drugs should be legal, that I really like the word fuck and other gems of profanity, and on and on.

Now I get that lots of people find much of that crude and primitive. I'm okay with that. I do take offense when yet another lame stereotype is thrown out (like that porn by definition is misogynistic), but I've learned to deal with that.

What I'm not going to do, though, is apologize for any of these preferences and opinions. I'm happy to be an R rated individual and I'm accepting the consequences of the leakage that comes from that. If you can deal with that, I'm sure we're going to get along just fine.

Apr 2 Creating dates in a time zone w/ActiveSupport
As easy as 1-2-3

eastern_timezone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"]
mon_before_market_opening = eastern_timezone.parse "3/23/2009 07:59:59 AM"
Mar 10 Rails, "do what I mean"
A pleasant surprise for me just now. I typed in

script/generate migration add_application_to_content_categories application:string

And the entire migration was generated. The descriptive name I thought of was the right convention to trigger the instant magic. Beautiful.
Mar 10 Jack Bauer 94
I was reminded for some reason of this video I saw last year to share w/my coworkers. Thought I'd share it here. http://www.collegehumor.com/video:1788161

It's 24 if shot in 1994. Amazing how far we've come since


Mar 10 Instant 3 way bi coastal debugging session

courtesy via iChat
Mar 4 VirtualBox > VirtualPC
I have available to me a rather muscular 20inch Vista laptop -- that's right, 20 inches, this is a laptop for King Kong.


Anyways, one of the uses for the laptop is to run a Microsoft provided XP VirtualPC image with Internet Explorer 6, unfortunately still a dominant browser and the "Great Satan" for web developers everywhere. As part of the virtualization wars, Microsoft has graciously made VirtualPC 2007 a free download.



I also planned to setup a CruiseControl.rb instance on a linux VM, and the Vista laptop had plenty of resources to spare (even running Vista). Naturally since I was already running the XP image on VirtualPC it made sense to try and to reuse VirtualPC for a Linux VM.


Some googling, and hoop jumpings later I had a Linux VM running, but it was kind of slow, and unstable. The Linux VM never stayed booted up for more than 2 days. MS does not officially support Linux VM's, go figure ;). Apparently there were linux add ons for VirtualPC 2005, but those didn't support Ubuntu, and no one has been able to get them to run with VirtualPC 2007.


So I decided to give VirtualBox a try after hearing good things about it. The install went very smoothly, and the VM is both stable and quick. The VirtualBox VM runs our unit tests in about 1/3 the time of the VirtualPC.

In general I seem happier with using VirtualBox, though I'll have to come up with a different solution. I will say on VirtualPC's behalf, that XP ran fine under VirtualPC
Mar 4 thru-you.com
Wow, just caught this from @obie http://thru-you.com/


It's amazing what "undiscovered talent" there is out there. Though I imagine he won't be undiscoved that long. Makes me wanna play again.
Feb 27 Remote collobaration via 4 Way Video Conference with iChat
Title says it all. Mondo cool.


I stayed home to help watch a sick child, but this came in handy. Normally the 3 on the right are in the same office in Southern California (2 of them are on the call), and the gentlemen at the left is in New Haven, CT.

Pretty nice for free!
Feb 20 Generate SQL from your migrations

On one of the projects we're working on, we needed to occassionaly generate SQL from our migrations. Déjà vu, I thought. A few minutes of Googling later, I remembered why: Jay and I had been on a project a couple of years ago whence we had the same need. Jay's code didn't quite work any more due to some ActiveRecord changes, and a search for an alternative implementation turned up nothing.

I took his code and modified it to our needs. A short time later, I had the code pulled out into a rails plugin, migration_sql_generator. Install it (script/plugin install git://github.com/muness/migration_sql_generator.git) and then run the rake task:

rake db:generate:migration_sql

Running this task generates two sql files per migration in db/migration_sql in the form 20090216224354_add_users.sql and 20090216224354_add_users_down.sql.

I've used the plugin with success using the sqlserver adapter, less luck with the mysql adapter (change_column and rename_column blow up because the mysql adapter checks for the presence of a column first) and no luck with the sqlite adapter. Haven't tried it with the postgres adapter.

Feb 20 Easily switch between Ruby 1.8.6 and 1.9.1

Chad mentioned that he'd gotten ruby 1.9.1 and 1.8.6 side by side on his workstation (his code for this is in his awesome spicy-config repo).

I took some time this morning to get a similar setup working. Now, on my prompt, I type, use_ruby_186 or use_ruby_191 to go back and forth between the Ruby 1.8.6 shipped with Leopard and a self-compiled install of ruby 1.9.1.

Steps for you to get there:

  1. Compile and install ruby 1.9.1:
    mkdir -p ~/tmp
    cd ~/tmp
    curl -O ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.1-p0.tar.gz
    tar xzf ruby-1.9.1-p0.tar.gz
    cd ruby-1.9.1-p0
    ./configure --prefix=$HOME/.ruby_versions/ruby_191
    make
    make install
    
  2. Install the ruby switcher:
    curl -L http://github.com/relevance/etc/tree/master%2Fbash%2Fruby_switcher.sh?raw=true?raw=true > ~/ruby_switcher.sh
    echo "source ~/ruby_switcher.sh" >> ~/.bash_profile
    

Note that I use ~/.gem for my gems. If you don't do that, you'll have to modify the switcher to specify your GEM_HOME. Type gem env and look for GEM PATHS to figure out what you should set it to.

Feb 18 Favorite recent photographs
Feb 12 Rapid progress: kudos to JRuby
Courtesy of Facebook

Charles Oliver Nutter JRuby has had over 850 revisions applied since 1.1.6 was branched in December. That's better than 14 commits per day. And 153 issues fixed.

Sweet...
Feb 3 Maatkit installation: the concise guide
If you use MySQL, odds are you need Maatkit whether you know it or not. It's the Swiss army knife: I mostly use it to parallelize backup and restore of huge databases on multi-core machines, but it's also handy for fake splitting large files, executing sql on multiple tables and a whole lot more. (You also want mytop if you're wondering what's up with MySQL connections.)

Here's the install script if you too want Maatkit at your fingertips (and you do. trust me.):


#!/bin/sh
# tested on Leopard with MySQL installed using the package installer

sudo perl -MCPAN -e 'install DBI::Bundle'
sudo perl -MCPAN -e 'install DBD::mysql'
# you may need to force the install as follows:
# sudo perl -MCPAN -e 'force install DBD::mysql'

mkdir -p ~/tmp
cd ~/tmp
curl -O http://maatkit.googlecode.com/files/maatkit-2725.tar.gz
tar xzvf maatkit-2725.tar.gz
cd maatkit-2725
perl Makefile.PL
sudo make install

Jan 22 No network after copying an Ubuntu VMWare image
After you copy an Ubuntu image, you'll probably lose your network connectivity. After a little bit of digging, it turns out that Ubuntu persists the MAC address of the network device in /etc/udev/rules.d/*net.rules . The fix:
  sudo rm /etc/udev/rules.d/*net.rules
  sudo shutdown -r now #to reboot

Dec 26 Bringing Merb's provides/display into Rails 3

The flow of Merb ideas into Rails 3 is already under way. Let me walk you through one of the first examples that I've been working on the design for. Merb has a feature related to Rails' respond_to structure that works for the generic cases where you have a single object or collection that you want to respond with in different formats. Here's an example:

class Users < Application

provides :xml, :json

def index
@users = User.all
display @users
end
end

This controller can respond to html, xml, and json requests. When running display, it'll first check if there's a template available for the requested type, which is often the case with HTML, and otherwise fallback on trying to convert the display object. So @users.to_xml in the result of a XML request.

The applications I've worked on never actually had this case, though. I always had to do more than just convert the object to the type or render a template. Either I needed to do a redirect for one of the types instead of a render or I need to do something else besides the render. So I never got to spend much time with the default case that's staring you in the face from scaffolds:

class PostsController < ApplicationController

def index
@posts = Post.find(:all)

respond_to do |format|
format.html
format.xml { render :xml => @posts }
end
end

def show
@post = Post.find(params[:id])

respond_to do |format|
format.html
format.xml { render :xml => @post }
end
end
end

Cut duplication when possible, give full control when not
But the duplication case is definitely real for some classes of applications. And it's pretty ugly. The respond_to blocks are repeated for index, show, and often even edit. That's three times a fairly heavy weight structure. This is where the provides/display setup comes handy and zaps that duplication.

For Rails 3, we wanted the best of both worlds. The full respond_to structure when you needed to do things that didn't map to the generic structure, but still have the generic approach at hand when the circumstances were available for its use.

Dealing with symmetry and progressive expansion in API design
There were a couple of drawbacks with the provides/display duo, though, that we could deal with at the same time. The first was the lack of symmetry in the method names. The words "provides" and "display" doesn't reflect their close relationship and if you throw in the fact that they're actually both related to rendering, it's gets even more muddy.

The symmetry relates to another point in API design that I've been interested in lately: progressive expansion. There should be a smooth path from the simple case to the complex case. It should be like an Ogre, it should have layers. Here's what we arrived at:

class PostsController < ApplicationController

respond_to :html, :xml, :json

def index
@posts = Post.find(:all)
respond_with(@posts)
end

def show
@post = Post.find(params[:id])
respond_with(@post)
end
end

This is the vanilla provides/display example, but it has symmetry in respond_to as a class method, respond_with as a instance method, and the original respond_to blocks. So it also feels progressive when you unpack the respond_with and transform it into a full respond_to if you suddenly need per-format differences.

The design also extends the style to work just at an instance level without the class-level defaults:

class DealsController < SubjectsController

def index
@deals = Deal.all
respond_with(@deals, :to => [ :html, :xml, :json, :atom ])
end

def new
respond_with(Deal.new, :to => [ :html, :xml ])
end
end

It's quite frequent that the index action has different format responsibilities than the new or the show or whatever. This design encompasses all of those scenarios.

Yehuda has also been interested in improving the performance of respond_to/with by cutting down on the blocks needed. Especially when you're just using respond_with that doesn't need to declare any blocks at all.

All in all, I think this is a great example of the kind of superior functionality that can come out of merging ideas from both camps. We're certainly excited to pull the same trick on many other framework elements. I've been exploring how a revised router that imports the best ideas from both could look and feel like. I'll do a write-up when there's something real to share.

Dec 24 Work on what you use and share the rest

It seems that we thoroughly caught the interwebs with surprise by announcing that Merb is being merged into Rails 3. 96% of the feedback seems to be very positive. People incredibly excited about us closing the rift and emerging as a stronger community.

But I wanted to take a few minutes to address some concerns of the last 4%. The people who feel like this might not be such a good idea. And in particular, the people who feel like it might not be such a good idea because of various things that I've said or done over the years.

There's absolutely no pleasing everyone. You can't and shouldn't try to make everyone love you. The best you can do is make sure that they're hating you for the right reasons. So let's go through some of the reasons that at least in my mind are no longer valid.

DHH != Rails
I've been working on Rails for more than five years. Obviously I've poured much of my soul, talent, and dedication into this. And for the first formative years, I saw it as my outmost duty to ensure the integrity of that vision by ruling with a comparably hard hand. Nobody had keys to the repository but me for the first year or so.

But I don't need to do that anymore — and haven't for a long time. The cultural impact of what is good Rails has spread far and wide and touched lots of programmers. These programmers share a similar weltanschauung, but they don't need to care only about the things that I care about. In fact, the system works much better if they care about different things than I do.

My core philosophy about open source is that we should all be working on the things that we personally use and care about. Working for other people is just too hard and the quality of the work will reflect that. But if we all work on the things we care about and then share those solutions between us, the world gets richer much faster.

Defaults with choice
So let's take a concrete example. Rails ships with a bunch of defaults. For the ORM, you get Active Record. For JavaScript, you get Prototype. For templating, you get ERb/Builder. And so on and so forth. Rails 3 will use the same defaults.

I personally use all of those default choices, so do many other Rails programmers. The vanilla ride is a great one and it'll remain a great one. But that doesn't mean it has to be the only one. There are lots of reasons why someone might want to use Data Mapper or Sequel instead of Active Record. I won't think of them any less because they do. In fact, I believe Rails should have open arms to such alternatives.

This is all about working on what you use and sharing the rest. Just because you use jQuery and not Prototype, doesn't mean that we can't work together to improve the Rails Ajax helpers. By allowing Rails to bend to alternative drop-ins where appropriate, we can embrace a much larger community for the good of all.

In other words, just because you like reggae and I like Swedish pop music doesn't mean we can't bake a cake together. Even suits and punk rockers can have a good time together if they decide to.

Sharing the same sensibilities
I think what really brought this change around was the realization that we largely share the same sensibilities about code. That we're all fundamentally Rubyists with very similar views about the big picture. That the rift in many ways was a false one. Founded on lack of communication and a mistaken notion that because we care about working on different things, we must somehow be in opposition.

But talking to Yehuda, Matt, Ezra, Carl, Daniel, and Michael, I learned — as did we all — that there are no real blockbuster oppositions. They had been working on things that they cared about which to most extends were entirely complimentary to what Jeremy, Michael, Rick, Pratik, Josh, and I had been working on from the Rails core.

Once we realized that, it seemed rather silly to continue the phantom drama. While there's undoubtedly a deep-founded need for humans to see and pursue conflict, there are much bigger and more worthwhile targets to chase together rather than amongst ourselves. Yes, I'm looking at you J2EE, .NET, and PHP :D.

So kumbaja motherfuckers and merry christmas!

Dec 23 The significance of Red in Red, Green,Refactor

(image from http://weepeixin.blogspot.com/2008/06/red-light.html)

What a lot of people miss is that the Red part of the TDD mantra "Red, Green, Refactor" serves as a test of the test (or spec for the BDD faithful). In seeing a test fail prior to the addition of code and seeing the test subsequently pass after the addition of code you learn 2 things
  1. The test indeed tested something that actually changed with the addition of code
  2. The code added had something to do with that test changing

One really appreciates this when they've been bitten -- written a test w/o bothering to see it fail, and writing code that supposedly makes it pass, but in fact did not. What can happen, albeit infrequently, is that since the test might've passed w/o the addition of new code--- the code added had nothing to with the code passing, or the test didn't test what you thought it did --- both variations of "accidental programming." Unfortunately, you won't be alerted to this since you never had the red turn into green as a result of the new code. This will break the normally "debugger free" cycle of TDD and reduce your coding momentum. I've been bitten, so I'm particularly aware of this phenomenon. Simply making it habit to always see the red, can avoid this.

I think side effects of not being able to "test the test" occurs more frequently test last, whether you are doing so by design (non TDD coding) or by necessity (adding tests to legacy code, working on code that is not easily TDD'd). In such situations, it's often hard, or not worth the ROI to find a way to make the test fail prior to writing the test. Consequently, writing tests last can often just serve as "documenting how the existing code works", rather than testing it.

(image from http://blogs.technet.com/seanearp/archive/2007/10/02/map-active-directory-in-visio.aspx)

I fell prey to this effect while putting some tests on some LDAP/ActiveDirectory code that I had to explore to get working . Normally, I strive to TDD as much as possible, but I couldn't really see how to do so in this case. I did a spike, exercising the LDAP API until it got the results I needed, then proceeding to refactor and add tests to this "legacy code" (as defined by Michael Feathers).

The test in question itself was wrong -- it didn't test what I thought it did, but since I never saw it fail, then pass, I didn't know it. Fortunately, I had a controller test (Rails app) that touched this code which failed and alerted me to the faulty test which also should've failed (yay multi level test coverage).


I'm reminded of Micah Martin's Ruby Kata and Sparring presentation at RubyConf where Micah did an exercise of live coding w/critiques as a device to improve one's coding. He mostly did a by the book "red, green, refactor" TDD/BDD with Rspec. I had pointed out that he had written a test in which he never saw it fail, but went straight ahead wrote the implementation to see the green. Now it was obvious that Micah had coded this problem before, that he pretty much knew what he was going code here, and that it was probably unlikely that there would be existing code to make this test pass, but none the less it's possible he might've written the wrong test, which would've sent him into a debugging cycle at some later point. When I brought this up, another attendee thought it was a spurious criticism, something along the lines that "we were judging his coding, not his adherence to TDD." I feel that person didn't get the significance of Red in Red, Green,Refactor, but perhaps he's never been bitten.
Dec 22 Kent Beck is a bloody genius, or How I learned to stop worrying about clean books and love the highligther


I just started reading Kent Beck's Implementation Patterns and have been quite impressed. I've read several of his other books, Extreme Programming Explored, 1st and 2nd Editions as well as Test Driven Development and find him to be remarkably insightful and communicative. The way he's able to express deep thoughts with clarity and brevity, while making it accessible rather than pedantic and dry is a joy to read. While I agree with and have often independently come up with many of the same thoughts he has expressed, Kent expresses them much better than I could. It is definitely useful for me to be able to draw upon his words when trying to express the same thoughts. Kent Beck is a genius.



In the past I've never taken too much writing in my books. I suspect it may stem back partly to the "Don't write in your text books" public school school training. Other factors may be some residual "keep your books pristine" OCD and the fear of marking the books up with something that I might not agree with later. As a compromise, I've annotated books w/sticky notes but doing so was often awkward. Many times, I'll read a section that I've gotten a lot out of, made a mental note to revisit, or write about it, but usually never got around to doing it. Consequentlym I would lose those ideas.

I started reading this book and mentally noting some great point I might want to discuss w/a co worker or write about, and finally broke down and got out a highlighter and a pencil and proceeded to mark it up.



Wow, I think I've enjoyed the parts I've read thus far much deeper than I have in past. I think the effort of highlighting and writing in the blank sections really helped to gel things more than just reading. I'll note that Head First series tries to actively encourage such as an active learning exercise as well.

Anyways, I've had such a good time doing so, I'll have to go back and reread and annotate my other Kent Beck books doing the same.
Dec 10 Done in by truncation
This was from my LinkedIn Network Updates this morning. Names removed to protect the innocent..






I've highlighted the key part that was "done in by truncation."

Of course, we know that it was supposed to be "She was a huge asset"...

Or do we ;-)
Nov 17 Myth #6: Rails only speaks English

It used to be somewhat inconvenient to deal with UTF-8 in Rails because Ruby's primary method of dealing with them was through regular expressions. If you just did a naïve string operation, you'd often be surprised by results and think that Ruby was somehow fundamentally unable to deal with UTF-8.

Take the string "Iñtërnâtiônàlizætiøn". If you were to do a string[0,2] operation and expected to get the two first characters back, you'd get "I\303" because Ruby operated on the byte level, not the character level. And UTF-8 characters can be multibyte, so you'd only get 1.5 characters back. Yikes!

Rails dealt with this long ago by introducing a character proxy on top of strings that is UTF-8 safe. Now you can just do s.first(2) and you'll get the two first characters back. No surprises. Everything inside of Rails uses this, so validations, truncating, and what have you is all UTF-8 safe.

Not only that, but we actually assume that all operations are going to happen with UTF-8. The default charset for responses sent with Rails is UTF-8. The default charset for database operations is UTF-8. So Rails assumes that everything coming in, everything going out, and all that's being manipulated is UTF-8.

This is a long way of saying that Rails is perfectly capable of dealing with all kinds of international texts that can be described in UTF-8. The early inconveniences of Ruby's regular expression-based approach has long been superseded. You need no longer worry that Rails doesn't speak your language. Basecamp, for example, has content in some 70+ languages at least. It works very well.

But what about translations and locales?
It was long a point of contention that Rails didn't ship with a internationalization framework in the box. There has, however, long been a wide variety of plugins that added this support. There was localize, globalize, and many others. Each with their own strengths and tailored to different situations.

All these plugins have powered Rails applications in other languages than English for a long time. Some made it possible to translate strings to multiple languages, others just made Rails work well for one other given language. But whatever your translation need was, there was probably a plugin out there that did it.

But obviously things could be better and with Rails 2.2 we've made them a whole lot more so. Rails 2.2 ships with a simple internationalization framework that makes it silly easy to do translations and locales. There's a dedicated discussion group, wiki, and website for getting familiar with this work. I've been using it in a test with translating Basecamp to Danish and really like what I'm seeing.

So in summary, Rails is very capable of making sites that need to be translated into many different locales. Before Rails 2.2, you'd have to use one of the many plugins. After Rails 2.2, you can use what's in the box for most cases (or add additional plugins for more exotic support).

Don't forget about time zones!
Dealing well with content in UTF-8 and translating your application into many languages goes a long way to make your application ready for the world, but most sites also need to deal with time. When you deal with time in a global setting, you also need to deal with time zones.

I'm incredibly proud of the outstanding work that Geoff Buesing lead for the implementation of time zones in Rails 2.1. It's amazing how Geoff and team were able to reduce something so complex to something so simple. And it shows the great power of being an full-stack framework. Geoff was able to make changes to Rails, Action Pack, and Active Record to make the entire experience seamless.

To lean more about time zones in Rails, see Geoff's tutorial or watch the Railscast on Time Zones.

See the Rails Myths index for more myths about Rails.

Nov 15 Myth #5: Rails is hard because of Ruby

I've talked to lots of PHP and Java programmers who love the idea and concept of Rails, but are afraid of stepping in because of Ruby. The argument goes that since they already know PHP or Java, that it would be less work to just pick one of the Rails knockoffs in those languages. I really don't think so.

Ruby is actually an amazingly simple language to pickup the basics on. Yes, there's a lot of depth in the meta programming corners, but you really don't need to go there to get stuff done. Certainly not to get going. The base mechanics of getting productive takes much shorter than you likely think.

After all, Ruby is neither LISP nor Smalltalk. It's not a completely new and alien world if you're coming from PHP or Java. Lots of concepts and constructs are the same. The code even looks similar in many cases, just stated more succinctly.

Learn Ruby in the time it would take to learn a framework
I'd argue that most programmers could get up and running in Ruby in about the same time it would take them to learn another framework in their current language anyway. I know it sounds a lot more scary to learn a whole new language rather than just another framework, but it really isn't.

The number one piece of feedback I get from people who dreaded the jump but did it anyway is: Why didn't I do this sooner?

Learn while doing something real that matters to you
Also, speaking from my own experience learning Ruby, I'd actually recommend trying to do something real. Don't just start with the basics of the language in a vacuum. Pick something you actually want done and just start doing it one step of the time. You'll learn as you go along and you'll have to motivation to keep it up because stuff is coming alive.

So don't write off Rails because you don't know Ruby. Your fears of starting from scratch again will quickly make way for the joy of the new language and you'll get to use the real Rails as a reward. Come on in, the water is fine!

See the Rails Myths index for more myths about Rails.

Nov 15 Myth #4: Rails is a monolith

Rails is often accused of being a big monolithic framework. The charges usually contend that its intense mass makes it hard for people to understand the inner workings, thus making it hard to patch the framework, and that it results in slow running applications. Oy, let's start at the beginning.

Measuring lines of code is used to gauge the rough complexity of software. It's an easy but also incredibly crude way of measuring that rarely yields anything meaningful unless you apply intense rigor to the specifics. Most measurements of LOCs apply hardly any rigor and reduces what could otherwise be a somewhat useful indicator to an inverse dick measurement match.

Applying rigor to measuring LOCs in Rails
The measurements of LOC in Rails have not failed to live up to the low standards traditionally set for these pull-down-your-pants experiments. Let's look at a few common mistakes people commit when trying to measure the LOCs in Rails:

Now let's take a simple example of committing all these mistakes against a part of Rails and see how misleading the results turn out to be. I'm going to use Action Mailer as an example here:

So the difference between committing all the mistakes and reality is a factor of 20. Even just the difference between committing the dependency mistake and reality is a factor of 10! In reality, if you were to work on Action Mailer for a patch, you would only have to comprehend a framework of 667 lines. A much less challenging task than digging into 12,406 lines.

Rails measured with all it's six major components without the mistakes is 34,097 lines divided across Action Mailer at 667, Active Resource at 878, Active Support at 6,684, Active Record at 9,295, Action Pack at 11,117 (the single piece most web frameworks should be comparing themselves to unless they also ship as a full stack), and Rail Ties at 5,447.

Looking at the monolithic charge
That Rails is big in terms of lines of code is just one of the charges, though. More vague and insidious is the charge that Rails is monolithic. That is one giant mass where all the pieces depend on each other and are intertwined in hard-to-understand ways. That it lacks coherence and cohesion.

First, Rails can include almost as much or as little of the six major pieces as you prefer. If you're making an application that doesn't need Action Mailer, Active Resource, or Active Record, you can swiftly cut them out of your runtime by uncommenting the following statement in config/environment.rb:

# config.frameworks -= [ :active_record, :active_resource, :action_mailer ]

Now you've reduced your reliance on Rails to the 23,248 lines in Action Pack, Active Support, and Rail Ties. But let's dig deeper and look at the inner workings of Action Pack and how much of that fits the monolithic charge.

Taking out the optional parts
The Action Controller part of Action Pack consists of 8,282 lines which breaks down into two major halves. The essential, stuff that's needed to run the bare minimum of controllers, and the optional that adds specific features, which you could do without.

First the essentials of which there are 3,797 lines spread across these files and directories: base.rb, cgi_ext, cgi_ext.rb, cgi_process.rb, cookies.rb, dispatcher.rb, headers.rb, layout.rb, mime_type.rb, mime_types.rb, request.rb, response.rb, routing, routing.rb, session, session_management.rb, status_codes.rb, url_rewriter.rb.

The more interesting part is the optional parts of which there are 3,481 lines spread across these files and directories: assertions, assertions.rb, benchmarking.rb, caching, caching.rb, components.rb, filters.rb, flash.rb, helpers.rb, http_authentication.rb, integration.rb, mime_responds.rb, performance_test.rb, polymorphic_routes.rb, rack_process.rb, record_identifier.rb, request_forgery_protection.rb, request_profiler.rb, rescue.rb, resources.rb, streaming.rb, test_case.rb, test_process.rb, translation.rb, verification.rb.

All these optional parts can actually very easily be turned off as well, if you so please. If you look at actionpack/lib/action_controller.rb, you'll see something like the following:

ActionController::Base.class_eval do

include ActionController::Flash
include ActionController::Benchmarking
include ActionController::Caching
...

This is where all the optional bits are being mixed into Action Pack. But they didn't need to be. If you really wanted to, you could just edit this 1 file and remove the optional bits you didn't need and you'd have some 3,500 lines of optional goodies to pick from.

For example, let's say you didn't need caching in your application. You comment the include ActionController::Caching line out and delete the associated files and that's 349 lines for the savings there. Or let's say that you don't like the flash, that's another 96 lines.

The reason many of these pieces can be optional is because of a wonderful part of Active Support called alias_method_chain. With alias_method_chain, you can latch on to a method to embellish it with more stuff. For example, the Benchmarking module uses alias_method_chain like this to hook into perform_action and render:


module Benchmarking
def self.included(base)
base.extend(ClassMethods)

base.class_eval do
alias_method_chain :perform_action, :benchmark
alias_method_chain :render, :benchmark
end
end

ActionController::Base declares render and perform_action, but doesn't know anything about benchmarking (why should it?). The Benchmarking modules adds in these concerns when it's included similar to how aspects work. So as you can see, alias_method_chain is a great enabler for clearly defined modules in Rails.

All the other frameworks in Rails works in a similar fashion. There's a handful of essential parts and then a handful of optional parts, which can use alias_method_chain if they need to decorate some of the essential pieces. This means that the code is very well defined and you can look at just a single piece in isolation.

But why on earth would you bother?
The analysis above of how you can bring Action Controller down to some 3,500 lines carefully side-stepped one important question: Why would you bother? And that's an answer I don't quite have for you.

The important part about being modular is that the pieces are understandable in isolation. That the individual modules have coherence and cohesion. Not that they're actually handed to you as a puzzle for you to figure out how to put together.

I'd much rather give someone a complete picture, which they can then turn into a puzzle if they're so inclined. As I've shown you above, it's actually really simple to deconstruct the frameworks in Rails and you can make them much smaller really easily if you decide that's a good use of your time and energy.

See the Rails Myths index for more myths about Rails.

Nov 14 Myth #3: Rails forces you to use Prototype

There are lots of great JavaScript libraries out there. Prototype is one of the best and it ships along Rails as the default choice for adding Ajax to your application.

Does that mean you have to use Prototype if you prefer something else? Absolutely not! Does it mean that it's hard to use something else than Prototype? No way!

It's incredibly easy to use another JavaScript library with Rails. Let's say that you wanted to use jQuery. All you would have to do is add the jQuery libraries to public/javascripts and include something like this to the in your layout to include the core and ui parts:

<%= javascript_include_tag "jquery", "jquery-ui" %>

Then say you have a form like the following that you want to Ajax:

<% form_for(Comment.new) do |form| %>

<%= form.text_area :body %>
<%= form.submit %>
<% end %>

By virtue of the conventions, this form will have an id of new_comment, which you can decorate with an event in, say, application.js with jQuery like this:


$(document).ready(function() {
$("#new_comment").submit(function() {
$.post($(this).attr('action') + '.js',
$(this).serializeArray(), null, 'script');

return false;
});
});

This will make the form submit to /comments.js via Ajax, which you can then catch in the PostsController with a simple format alongside the HTML response:

def create

@comment = Post.create(params[:comment])

respond_to do |format|
format.html { redirect_to(@comment) }
format.js
end
end

The empty format.js simply tells the controller that there's a template ready to be rendered when a JavaScript request is incoming. This template would live in comments/create.js.erb and could look something like:

$('#comments').append(

'<%= escape_javascript(render(:partial => @comment)) %>');
$('#new_comment textarea').val("");
$('#<%= dom_id(@comment) %>').effect("highlight");

This will append the newly created @comment model to a dom element with the id of comments by rendering the comments/comment partial. Then it clears the form and finally highlights the new comment as identified by dom id "comment_X".

That's pretty much it. You're now using Rails to create an Ajax application with jQuery and you even get to tell all the cool kids that your application is unobtrusive. That'll impress them for sure :).

Rails loves all Ajax, not just the Prototype kind
This is all to say that the base infrastructure of Rails is just as happy to return JavaScript made from any other package than Prototype. It's all just a mime type anyway.

Now if you don't want to put on the unobtrusive bandana and instead would like a little more help to define your JavaScript inline, like with remote_form_for and friends, you can have a look at something like jRails, which mimics the Prototype helpers for jQuery. There's apparently a similar project underway for MooTools too.

So by all means use the JavaScript library that suits your style, but please stop crying that Rails happens to include a default choice. That's what Rails is. A collection of default choices. You accept the ones where you don't care about the answer or simply just agree, you swap out the ones where you differ.

Update: Ryan Bates has created a screencast that shows you how to do the steps I outlined above and more.

See the Rails Myths index for more myths about Rails.

Nov 14 Git: things I love and manipulating remote branches

I've been happily using Git for months now. The primary benefit for me has been the ability to work offline without messing with SVK, not having to use the svn commands for renames and moves, the ability to use multiple remote servers and better tools to look at branch level history (think gitk).

Branching is much improved, besides. In Subversion, to branch, you copy the current tree elsewhere and then you work in this branch and finally, merge your changes manually back into trunk (to wit, you have to keep track of what was already merged and not reapply those commits). In git, though, that's all handled for you. Another difference is best illustrated by example: you've started a new feature. Several file modifications later, you look at your diff and realize, "I should have started a new branch for this. doh." With Subversion, there's not much you can do automatically to get these changes into a branch. You'd typically now:

  1. generate a diff
  2. undo your changes
  3. create a branch
  4. switch to the branch
  5. apply the diff
  6. back to work
In git on the other hand, you type git branch feature_22.

Sweet, huh?

Well, not altogether. Pushing this local branch to a remote server is altogether too complicated:


git push origin feature_22:refs/heads/feature_22
git fetch origin
git config branch.feature_22.remote origin
git config branch.feature_22.merge refs/heads/feature_22
git checkout feature_22

Sure, you could have created the branch on the remote server first and saved yourself some hassle:


git push origin master:refs/heads/feature_22
git fetch origin
git branch --track feature_22 origin/feature_22
git checkout feature_22

Not exactly straight forward either. Neither are other standard branch related activities. Here's how you delete that remote branch:

git push origin :refs/heads/feature_22 # yeah, that's how you delete a remote branch.  :(
git branch -d feature_22 # delete it locally too

Fortunately, Git has a vibrant community that work to abstract away some of these complications. One of my favorite Git tools is git_remote_branch. By using it, working with remote git branches becomes a breeze:


grb publish feature_22 # publish a local branch
grb create feature_22 # create a remote branch and local branch to track it
grb delete feature_22 # delete the remote and local tracking branch

Ah, that's better!

Nov 13 Myth #2: Rails is expected to crash 400 times/day

Zed Shaw's infamous meltdown showed an angry man lashing out at anything and everything. It made a lot of people sad. It made me especially sad because this didn't feel like the same Zed that I had dinner with in Chicago or that I had talked to so many times before. I actually thought he might be in real trouble and in need of real help, but was assured by third party that he wasn't (Zed never replied to my emails after publishing).

But Zed's state of mind isn't really what this is about. This is about the one factual assault he made against Rails that despite being drenched in unbelievable bile somehow still stuck to parts of the public conscious.

The origin of the claim
Zed insinuated that it's normal for Rails to restart 400 times/day because Basecamp at one point did this with a memory watcher that would bounce its Mongrels FCGIs when they hit 160MB 250MB. These FCGIs would then gracefully exit after the current request and boot up again. No crash, no lost data, no 500s.

But still an inconvenience, naturally. Nobody likes a memory leak. So I was happy when a patch emerged that fixed it and we could stop doing that. I believe the fix appeared some time in 2006. So even when Zed published his implosion at the end of 2007, this was already ancient history.

Yet lots of people didn't read it like that. I've received more than a handful of reports from people out talking Rails with customers who pull out the Zed rant and say that their consultants can't use Rails because it reboots 400 times/day. Eh, what?

Fact: Rails doesn't explode every 4 minutes
So let's make it clear once and for all: Rails doesn't spontaneously combust and restart itself. If we ever have an outright crash bug that can take down an entire Rails process, it's code red priority to get a fix out there.

A Rails application may of course still leak memory because of something done in user space that leaks. Just like an application on any other platform may leak memory.

Update: Zed points out that the leak was occurring while Basecamp was still on FCGI, not Mongrel, which is correct. I don't know how that makes the story any different (it was the fastthread fix that stopped the leak and our minor apps were on Mongrel with leaks too), but let's definitely fix the facts.

See the Rails Myths index for more myths about Rails.

Nov 13 Myth #1: Rails is hard to deploy

(If you don't want to bother with the history lesson, just skip straight to the answer)

Rails has traveled many different roads to deployment over the past five years. I launched Basecamp on mod_ruby back when I just had 1 application and didn't care that I then couldn't run more without them stepping over each other.

Heck, in the early days, you could even run Rails as CGI, if you didn't have a whole lot of load. We used to do that for development mode as the entire stack would reload between each request.

We then moved on to FCGI. That's actually still a viable platform. We ran for years on FCGI. But the platform really hadn't seen active development for a very long time and while things worked, they did seem a bit creaky, and there was too much gotcha-voodoo that you had to get down to run it well.

Then came the Mongrel
Then came Mongrel and the realization that we didn't need Yet Another Protocol to let application servers and web servers talk together. We could just use HTTP! So packs of Mongrels were thrown behind all sorts of proxies and load balancers.

Today, Mongrel (and it's ilk of similar Ruby-based web servers such as Thin and Ebb) still the predominate deployment environment. And for many good reasons: It's stable, it's versatile, it's fast.

The paradox of many Good Enough choices
But it's also a jungle of options. Which web server do you run in front? Do you go with Apache, nginx, or even lighttpd? Do you rely on the built-in proxies of the web server or do you go with something like HAProxy or Pound? How many mongrels do you run behind it? Do you run them under process supervision with monit or god?

There are a lot of perfectly valid, solid answers from those questions. At 37signals, we've been running Apache 2.2 with HAProxy against monit-watched Mongrels for a few years. When you've decided on which pieces to use, it's actually not a big deal to set it up.

But the availability of all these pieces that all seem to have their valid arguments lead to a paradox of choice. When you're done creating your Rails application, I can absolutely understand why you don't also want to become an expert on the pros and cons of web servers, proxies, load balancers, and process watchers.

And I think that's where this myth has its primary roots. The abundance of many Good Enough choices. The lack of a singular answer to How To Deploy Rails. No ifs, no buts, no "it depends".

The one-piece solution with Phusion Passenger
That's why I was so incredibly happy to see the Phusion team come out of nowhere earlier this year with Passenger (aka mod_rails). A single free, open source module for Apache that brought mod_php-like ease of deployment to Rails.

Once you've completed the incredibly simple installation, you get an Apache that acts as both web server, load balancer, application server and process watcher. You simply drop in your application and touch tmp/restart.txt when you want to bounce it and bam, you're up and running.

But somehow the message of Passenger has been a little slow to sink in. There's already a ton of big sites running off it. Including Shopify, MTV, Geni, Yammer, and we'll be moving over first Ta-da List shortly, then hopefully the rest of the 37signals suite quickly thereafter.

So while there are still reasons to run your own custom multi-tier setup of manually configured pieces, just like there are people shying away from mod_php for their particulars, I think we've finally settled on a default answer. Something that doesn't require you to really think about the first deployment of your Rails application. Something that just works out of the box. Even if that box is a shared host!

In conclusion, Rails is no longer hard to deploy. Phusion Passenger has made it ridiculously easy.

See the Rails Myths index for more myths about Rails.

Nov 13 The Rails Myths

Ruby on Rails has been around for more than five years. It's only natural that the public perception of what Rails is today is going to include bits and pieces from it's own long history of how things used to be.

Many things are not how they used to be. And plenty of things are, but got spun in a way to seem like they're not by people who had either an axe to grind, a competing offering to push, or no interest in finding out.

So I thought it would be about time to set the record straight on a number of unfounded fears, uncertainties, and doubts. I'll be going through these myths one at the time and showing you exactly why they're just not true.

This is not really to convince you that you should be using Rails. Only you can make that choice. But to give you the facts so you can make your own informed decision. One that isn't founded in the many myths floating around.

Sep 21 Mingle, meet Git

Several weeks back, Adam Monago, Mingle's product manager was visiting our office in Chapel Hill. One of the topics that came up was Git integration with Mingle. Alas, it sounded like it was a ways out. But he explained that the SCM integration was pluggable and that we could write the code and drop it in place, echoing things I'd heard from other ThoughtWorkers.

A couple of days later, Don and I were curious as to just what it'd take to implement the integration. Reverse engineering the interface we had to implement from the Subversion and Perforce plug-ins was anything but fun, but before the day was over, we had rudimentary integration working: we could see commit messages and the list of files modified per check-in. Since then, Don implemented the rest of it including Mingle-based source code browsing.

We've been using the mingle_git plugin for a little while with no problems. For performance reasons, we're not using the source code browsing from inside Mingle. Instead, we use GitHub's source browsing: see the README for instructions on wiring things that way too.

Installation is documented in the README. We've only used this on Mac OS, FreeBSD and Linux. Windows users, you may have luck by using msysgit.

Caveat emptor: if you browse around the code, you'll quickly conclude that it is a spike: we started with the subversion plugin and evolved it to this. Since the SCM integration API is not documented, we can't even be positive that we implemented it correctly (though the evidence suggests that we have). Also note that Mingle makes the assumption that check-in numbers are sequential, and that's an assumption that is not Git-friendly and it shows in the code.

Enjoy, but keep in mind that this is unsupported, use-at-your-own-risk software. For me, that's better than no Git integration. ;)

Note: Mingle's APIs changed from 2.0 to 2.1 and we haven't had a chance to update this plugin yet. If you installed this plugin, and are ready to upgrade to 2.1, you'll want to remove the plugin and then execute this SQL on your Mingle database: delete from plugin_schema_info where plugin_name = 'mingle_git';

Aug 17 Encrypt your client data in 53 minutes

Thanks to Aaron's continued efforts to make us ever more security conscious, I've been encrypting client data on my laptop. This came up in conversation during erubycon (thanks EdgeCase for a fun conference with engaging evening events). A couple of people asked me to get them started on encrypting their data too.

Here are instructions. They're written for Mac users, but they'd be nearly identical for Linux and Windows users since TrueCrypt is available there too.

  1. Install TrueCrypt.
  2. Create a container based encrypted file. Pick FAT as the file system. I use both keyfiles and a password.
  3. Erase the FAT partition and then format as HFS/ext2/[fs of choice] using Disk Utility/[partition manager of choice]. Name it client_data.
  4. Mount the newly created partition.
  5. Move your sensitive data to /Volumes/client_data. This is by far the slowest part of the process. While you wait, watch The Enemies of Reason (48 minutes -- everything else should take 5 minutes or less).
  6. Modify TrueCrypt preferences to suit your needs. Some suggestions: leave encrypted volumes mounted when quitting TrueCrypt, set Auto-dismount volume after 30 minutes of inactivity in the partition.

As mentioned in my previous blog entry, I use a script to automatically create aliases to allow easy switching to project directories. All I had to do was switch that entry to point to /Volumes/client_data instead of the old ~/work/client_data. Now, when I want to work on client projects or contracts, I launch TrueCrypt, mount the container and open a new terminal window. All my old aliases work just like they used to.

Mac users: if you don't care about the cross-platform compatibility that TrueCrypt offers, and trust Apple to encrypt your data, you could use Disk Utility to create encrypted partitions instead. Some people insist it's more convenient (You know who you are!).

Jul 27 The startup school talk

I keep getting a flow of positive feedback about the presentation I delivered at Startup School in the Spring. Since it was never linked up here, I thought I'd made sure it made it into the archives: The secret to making money online.

Jun 29 Lazy bash cd aliases
Those of you who've found value in my last couple of bash specific posts may also like the latest addition to my ~/.bash_profile.

This one iterates through the one or more directories and creates aliases to the subdirectories so I don't have to. Here's the scenario: I've got a directory ~/work/ where I keep work projects, a ~/writings/ where I keep all the writing projects and so on. I used to have aliases to each subdirectory. e.g. alias project1="cd /Users/muness/work/project1". With shame, I admit that I maintained each of these manually. No more!

Install instructions:

curl -L http://github.com/relevance/etc/tree/master%2Fbash%2Fproject_aliases.sh?raw=true?raw=true > ~/.project_aliases.sh
echo "source ~/. project_aliases.sh" >> ~/.bash_profile

Usage instructions:

You may be interested in my blog post over at PragMactic OS-Xer where I describe my motivation for these recent shell scripts.

Jun 17 bash: don't make me think

Last week I figured out a way to make my life a little bit easier by abstracting the scm I was using and having the prompt indicate whether I was in a Subversion or Git. Thanks to Mike Hommey whose script I tweaked for my needs.

For a long time, I've wanted my iTerm tab title to be more useful. I started by having it display the last process I executed in that tab (this also shows the full path in iTerm's window title bar):


PS1='\[\e]2;\h::\]${PWD/$HOME/~}\[\a\]\[\e]1;\]$(history 1 | sed -e "s/^[ ]*[0-9]*[ ]*//g")\a\]\$ '

Next up I wanted to show the currently running command. Google showed me how:


trap 'echo -e "\e]1;$BASH_COMMAND\007\c"' DEBUG

Instead of trying to explain this code I'll quote the Bash man page:

BASH_COMMAND
The command currently being executed or about to be executed, unless the shell is executing a command as the result of a trap, in which case it is the command executing at the time of the trap.

Some more tweaks followed:

And a screenshot to summarize:

The code is in github/relevance/etc/tree/master/bash/bash_vcs.sh.

Install instructions:


curl -L http://github.com/relevance/etc/tree/master%2Fbash%2Fbash_vcs.sh?raw=true > ~/.bash_dont_think.sh
echo "source ~/.bash_dont_think.sh" >> ~/.bash_profile

Enjoy! Tested with iTerm on Leopard.

Jun 11 Stop the presses: bash said to embrace subversion and git

Update: I've since updated and moved this script. See my new blog post.

I had a chance to pair with Rob today. On his console window, I noticed something I wanted: his bash prompt had an indication that he was in a Git repository along with the branch he was on. Later, after he'd left, I found myself wondering how that worked and that I simply had to have it, and I wasn't willing to wait a whole day to figure out how he'd done it. Patience is not a virtue. (In that spirit, click here for the code if you're too impatient to read the rest of this blog entry which I spent countless hours writing. Uphill both ways. In the snow.)

A few minutes of googling turned up a blog entry with relevant bash fu. The code there was for changing the prompt such that it indicated whether you were using svn, git, svk or Mercurial along with some repository metadata. A couple of minutes later (it took a while to copy and paste the code since it was interweaved with comments), I found out it didn't work on Leopard. readlink turned out to be the culprit. Instead of figuring out why it wasn't working, I replaced it with something simpler (specifically I used: base_dir=`cd $base_dir; pwd`). Voila, things worked: I now had a hella cool prompt that showed me if I was in a Subversion or a Git repository - I never used Mercurial, and left SVK for Git a couple of months ago. Yay.

Being who I am I had to do something more with this new ability to distinguish between Subversion and Git. And I knew exactly which itch to scratch: 90% of the time I use the same scm commands. I even had shell aliases for them so I wouldn't have to type them. A few minutes later I'd converted my previously Subversion specific aliases to generic ones that worked with Git too. Screenshot says it all:

If you want the same, download the script as ~/.bash_vcs and add source ~/.bash_vcs at the end of your ~/.bash_profile.

Apr 29 Twitter me this

If a tweet is uttered with no followers, does it make a peep? I'm getting going with Twitter on http://twitter.com/d2h.

Apr 25 Buckets of mice

We have 24" and 30" pairing stations, an intern, freshly roasted coffee delivered weekly, a fridge stocked with caffeine, more caffeine, beer, and Dave's Insanity sauce. We have cool t-shirts and all manner of radiators up on the walls, whiteboards and the Beta Brite. Music is served by our CI/Music server.

The bookshelves are stocked with reference materials, the occasional bottle of scotch, and recommended readings. On the list of recommended readings we've got The Carpet Makers, The Company, The Omnivore's Dilemma, The Eyre Affair, Behind Closed Doors, Bloodsucking Fiends and The Deadline, Men In Hats, Volume I, Don't Make me Think, The Insane are Running the Asylum.

Our favorite radiator is the Friday radiator. Fridays are special: we don't do billable work. Instead we open source, blog (self reference makes this blog entry extra cool), watch educational movies, play Wii on the projector. Here's today's:

Oh, let's not forget the buckets of mice.

This blog entry inspired by another excellent business card cartoon from Hugh Macleod.


Apr 22 The silent majority

I had a great time on the West coast recently with stops in Santa Barbara and Palo Alto. What always surprises me at events like these is the huge number of people I meet that are doing cool things with Rails that I've never heard of. The kind of people who are just really happy to be using Rails and happy to build businesses with it.

Most of them are not heavily involved with the community in the sense of always being in front of it. They're not the ones constantly commenting on the blogs. They're just enjoying working with the tools. That's a really refreshing sentiment.

It's easy for people to think that the interaction they witness on the web is a complete reflection of the world in general. Often it's quite the contrary. Which is why I so enjoy getting out of the web world and meeting people in the flesh. Hearing their stories, discussing their concerns, and sharing passions.

You can easily end up burning out on web participation because the loud minority twists your perception of what matters and who cares. But there's nothing like meeting people who tell you that working with Rails or listening to a talk or reading something you wrote either touched them, changed them, or made them move in a new direction. That's a big pay-off for getting involved with public sharing.

So thank you so very much to everyone who came up to me at any of the events out in California. It makes it all worth it to hear your stories. Keep on rocking with whatever it is that you're doing. Keep the passion and the optimism alive.

Apr 16 cmd line history meme

Rob tagged me. So:

muness$ history 1000 | awk '{a[$2]++}END{for(i in a){print a[i] " " i}}' | sort -rn | head
102 git
72 ls
63 cd
40 ss
35 rake
24 m
17 up
14 st
12 sc
11 ri

Tag, you're it.

Apr 11 Distributed Retrospectives

Agile Retrospectives (Esther Derby, Diana Larsen) and Project Retrospectives (Norman L. Kerth) have been a great resource in facilitating - or helping others facilitate - retrospectives. I'll often leaf through them a day or two before a retrospective to remind myself of the framework (more on that in an forthcoming post), and to introduce new activities or create my own.

Something that neither of those books tackle directly is how to facilitate a distributed retrospective. Given that we've been running a few of those lately, I wanted to share some tips:

I've shared a Google Doc template for a 2 hour iteration retrospective for 4 to 8 people you can refer to or use as a starting point for your own living retrospective document. Credit goes to Agile Retrospectives for the activities.

Apr 11 Going to California

I'll be speaking at an event put on by AppFolio at 6:30PM on the 17th, at Paul Graham's Startup School on the 19th at around noon, and finally meeting up with some people from the SD Forum Ruby conference on the eve of the 19th. If you're at any of these events, do stop by and say hi.

Apr 11 Testing declarative code

For a while now, I've had my doubts about the usefulness of one aspect of test driven development (which applies equally well to behavior driven development): that it should be done 100% of the time.

The first time I came across this, was at ThoughtWorks. The question was whether we should TDD declarative delegations. I remember a several hour long conversation about the merits of tests for Forwardable based delegations.

class A
  extend Forwardable
  def initialize(b)
    @b = b
  end
  def_delegator :@b, :some_method  # Should I write a test before writing this declaration?!
end

A specification for this declaration would be:

describe "A" do
  it "delegates some_method to b" do
    a = A.new(stub(:some_method => :x))
    a.some_method.should == :x
    # or you could use the Handoff assertion:
    assert_handoff.from(A.new).to(:@b).for_method(:some_method)
  end
end

I didn't get the fuss -- it was clear to me that testing such delegations was wasteful and a maintenance hassle. But I didn't realize that this was part of a larger argument.

Not an isolated case

Since then, I've learned that to some developers this is a general rule. Here's another example, re testing stock ActiveRecord validation declarations, e.g.:

class Model < ActiveRecord::Base
  validates_presence_of :attr_1
end

The test for this would be:

describe "Model" do
  it "validates_presence_of :attr_1" do
    model = Model.new
    model.valid?
    model.errors.on(:attr_1).should == "must not be blank"
  end
  # or you might write a helper that reflects on validates_presence_of declarations
  test_model_validates_presence_of Model, :attr_1
end

It took me a while (too long) to get the general pattern: these discussions I kept finding myself in all had to do with testing declarations.

How did we get here?

Test driven development as best as I can tell is a - pragmatic - descendant of formal specifications:

"A formal specification is a mathematical description of software or hardware that may be used to develop an implementation. It describes what the system should do, not how the system should do it. Given such a specification, it is possible to use formal verification techniques to demonstrate that a candidate system design is correct with respect to the specification."

Writing formal specifications for the majority of the software isn't practical. Writing tests first provides us a simple, practical way to write executable specifications. True, they don't give us the ability to use "formal verification techniques" to prove anything about our code, but they do give us confidence that our code does what our tests say the code does (as much confidence as we have in our tests).

The rule

The rule regarding TDD is: If you can TDD it and it's destined to be production code, you should TDD it.

The problem I find with this rule is that it causes us to write tests like those above that duplicates the declarative code. At best case it goes like this:

  # We write this code first in the spec:
  test_model_validates_presence_of Model, :attr_1 
  # we run it and watch it fail...
  # and then we write this in the model class:
  validates_presence_of :attr_1 
  # rerun the test and watch it pass...

I find this wasteful: We first implement the test_declaration_is_called (in this case, test_model_validates_presence_of) for every declaration. After all that work (and not to mention code that we have to maintain) we end up with a test that tells us what the declaration itself does. But with less readability and intent. Indeed, declarative code is in fact formal specification.

Guidelines not rules

Writing tests first is a great guideline. I do it almost all the time. But I don't do it all the time. It makes me angry when I change declarative code only to have a test that looks exactly the same fail as well.

OK, tests for declarations don't really make me angry. But they do make me wonder if the developer who wrote the test really likes to answer the question, "are you sure that you're sure that you want to do what you just said you want to do?"

Apr 3 Git's avalanche

I remember thinking how impressive the roll-out of Subversion was. They reached some magic point where the majority of the development world just flipped and most everyone who've previously been on CVS switched in what seemed like an overnight transition.

Of course it didn't happen like that, but the perception of a sea of developers all collectively deciding to move on and knight Subversion the next savior seemed impressive at the time.

It's not so easy any more. First of all, Subversion is still a great SCM for the paradigm it embodies. It's unlikely to be out-gunned within its sphere any time soon. So any newcomers can't just out-SVN Subversion, like Subversion could out-CVS CVS.

Which means to topple Subversion, you have to bring a new paradigm to the table. The plethora of distributed version control systems seem to be that next paradigm. But it's not purely equitably "better", it's different. Better in many regards for many purposes, but not just better. Like SVN just felt better, period, than CVS.

So given all that, I think the Git move is even more interesting. That camp is competing not only to convince people that a new paradigm is appropriate for many things, but also as that it, one-out-of-many, should be the one to embody it.

I think they're going to get it. Killer apps makes or breaks any platform. With Github, I think the Git hub just scored one. Rails is going to be hosted there for the launch. Capistrano, Prototype, and Scriptaculous already moved there.

Go, go, Git.

Apr 3 The immediacy of PHP

I've been writing a little bit of PHP again today. That platform has really received an unfair reputation. For the small things I've been used it for lately, it's absolutely perfect.

I love the fact that it's all just self-contained. That the language includes so many helpful functions in the box. And that it managed to get distributed with just about every instance of Apache out there.

For the small chores, being quick and effective matters far more than long-term maintenance concerns. Or how pretty the code is. PHP scales down like no other package for the web and it deserves more credit for tackling that scope.

Mar 14 Where there's smoke signals...
In a previous post, I briefly described how we were using cc_campfire_notifier to get build success/failure notifications in campfire. cc_campfire_notifier has lost momentum over the last couple of months. Since we actively rely on the notifier for several projects, we've now forked it as smoke_signals.

The first release offers the following improvements:

Check out the notifier's home page for installation instructions or head on over to GitHub to browse the code.

Mar 7 Apple doesn’t get it

I doubt few of my readers have missed that Apple just released the iPhone SDK. How many read through the fine print?

Bottom line is: If you want to sell apps for the iPhone you gotta give Apple 30%. Thirty percent!?

Why?!

Apple is making ridiculous money off selling the iPhone. The more apps the iPhone gets, the more iPhone's they will sell, the more money they will make.

In Swedish we have an expression for this. “Dumsnål”, literally “stupid greedy”. You get greedy about some detail so that you end up loosing money on the bigger picture. The reason Windows dominated over Mac back in the days was partly because Windows had more and better apps. Is Steve doing the same mistake again?

Mar 7 Threads don’t scale? They might do now!

One of the interesting things in this industry is that every once in a while you have to completely re-evaluate your beliefs in light of new developments. It's long been common sense that thread-based servers scale worse than selector-based poll/NIO ones.

This certainly was true at one point in time, but it seems it may not be true any longer. There's several reasons:

It's funny that while the whole industry was learning how to do designs for non-threaded models there was this group of people fixing up the actual infrastructure itself.

Time to pick up Doug Lea's threading book again. Maybe this reading I will understand some of it.

Mar 6 Release early, release often, business edition
One of the things we preach as software developers is release early, release often. I think ESR is right in that our primary motivation for this is often related to quality:
In the bazaar view, on the other hand, you assume that bugs are generally shallow phenomena—or, at least, that they turn shallow pretty quickly when exposed to a thousand eager co-developers pounding on every single new release. Accordingly you release often in order to get more corrections, and as a beneficial side effect you have less to lose if an occasional botch gets out the door.

As I've done more project consulting and management, I've realized that the benefits extend well beyond the technical ones. But I've had a difficult time articulating the business benefits to incremental, frequent releases.

Last week, Ross posted an article that describes one of the primary business benefits to frequent, early releases, Minimising the Speculative Risk of IT Investments:

With each incremental delivery, and every increase in tangible value, the intangible or speculative value decreases. The reduction in speculative value at risk represents a reduction in the total value that can be depressed through delays in delivery. Thus, early delivery reduces the risk of speculative value not being realised. Simultaneously, it reduces the volatility of returns.

What other benefits do you find to the business from releasing early, releasing often?

Mar 5 Facebook: talk about dropping the ball!

facebook.pngFacebook. The future of internet. How high hopes we had. What silly amounts of money Microsoft spent.It was such a great idea. One community to rule them all and anyone can extend it with their own apps.But as always, a platform is nothing without it's killer app. All Facebook got was a couple of stupid movie quiz and dating apps.I still think it's a great idea in principle but the implementation has to be:

I'm thinking whoever puts together things like OpenID, hFN, hCard, plain old email and makes it work for my grand mother is on a winner.Facebook on the other hand, I have one word for you: Unsubscribe.

Mar 4 A leisurely read through ECMAScript v4
“like”
The special type operator like is used to test whether an object “looks like” a particular type even without being of that type. For example,
var v: like { x: int, y: int }
will accept both of these values:
{ x:3, y:3 } : Point
{ x:3, y:3 }

Advice to language designers: If you ever get to the point where it feels logical and appropriate to add a language feature such as like, please, just give up.

The future will thank you.

Plenty more from where that came from.

Feb 7 CC.rb Campfire Notifier Released
Note: I've forked this notifier to add features and fix some bugs at in Smoke Signals. At Relevance, we make heavy use of Campfire for our distributed projects. One room per project, and we expect everyone to "be in" the relevant room associated with the project they're working on at the time. We use it to communicate: to ask for a pair (we've tried Leopard's Remote Desktop Sharing, but have no settled mostly on emacs + screen), ask questions, request code reviews (we've taken to using the topic for posting ad hoc requests like that), and make announcements.

This virtual space has many disadvantages over being in the same room as I'd been used to on my previous couple of projects, but it did have a nice perk: SVN commit notifications were right there alongside our own discussions. The notices were more useful than I expected, a quick, clear indicator of our pace on a given day.

Naturally, I wanted our other major automated task to notify us of CCMenu is OK, but it's disconnected from our primary virtual space (Campfire, as discussed above). Being lazy, I didn't want to build it myself, so I first looked around for tools that suited my needs. Much to my chagrin, none did, so I took the one that was closest and added to it what I needed: specs. Then came the stuff that was missing: ssl support and support for one room per project. And last but not least, to help deal with configuration hassles and debugging, I added logging.

If you're using CruiseControl.rb and Campfire, give it a whirl. Instructions are in the README.

Feb 5 Pi
Jan 29 In it for the long haul

Announcing RailsConf '08 today, I stopped to think about that by the time this conference rolls around, I will have been working on Ruby on Rails for five years. Wow. There are so many memories from this wild ride that it's at once both hard to fathom that it's been so long and yet it feels like I've been doing it forever. Time can be funny like that.

But what pleases me the most is that I still absolutely love working on and with Ruby and Rails. It didn't pass, it wasn't just a phase, it wasn't a run for an exit event. I think that's significant because it means that I, and everyone else still involved with the project, are just as likely to keep at this for another five years or more.

When you do what you love for the sake of itself, the rewards are so much greater than if you just do it for external incentives. For lots of measures of "winning", we've long since won with Ruby on Rails. The impact on the industry, the adoption by thousands of companies and developers, the books, the conferences, and all that jazz. And yet, it doesn't really matter that much in the end. What matters is getting excited about continuing the work.

In light of this, I strongly recommend that you find a vocation in your life where you just really enjoy the act itself. Not just the results, not just the external incentives. The actual work. There's not enough time to spend it doing anything else.

Powered by Feed Informer
xyzzyable