Be Genius

me

Bo Jeanes

I am an software engineer who has lived and worked in New York, Brisbane, Chicago, San Francisco, and now Melbourne. I primarily work in Ruby though am a functional programmer at heart and a fan of programming languages in general. In particular, I love Rust and Clojure but keep my eye on many langauges all the time.

New design

Just a quick post to point out the new design for this blog. It's nothing special — I just needed a change.

Hopefully, the change of aesthetics will motivate me to get back into blogging.

Let me know if there is any weird display issues on your browser. I only tested the latest versions of non-IE browsers, but if there are any stupid obvious fixes to any browser, I'll implement them.

Tell me what you think, keeping in mind I'm a developer not a designer :P.

Hell yes

Although long overdue, I’m here to tell you why I joined Obtiva and why I think you should too.

About 10 months ago, I found myself looking for a job. I had plenty of freelance work and plenty of time to find the right fit for myself. With this in mind, I decided to adopt a new philosophy to apply in situations like this.

I realised that you don’t always get the full potential out of life until you face up to what you really want out of it.

The core principle of this outlook was inspired by reading a fantastic blog post that had one message: If you can’t say “HELL YEAH!” to something, just say “No” instead.

This message resonated with me and helped me considerably to get what I really wanted out of the next few months. I knew that what I really wanted more than anything was to work with incredible people who inspired and challenged me on a daily basis. I knew then and still do now that if this basic need wasn’t met, I’d be looking for a new job within a few months.

I knew that to make the best of my time, I had to take my time. I put the word out to the world (via a blog post) stating what I wanted and began networking and contacting companies I thought I’d like.

One of the first things I did when I got on the phone with any potential employer was to tell them that I would not be accepting any jobs immediately. I wanted to take at least a few months to get a good feel for the work places and the people of which they were comprised.

I was contacted by nine fantastic opportunities across the world. They included opportunities in Sweden, Spain, Mexico, the USA, Canada, and my home, Australia.

With each opportunity, I stated that I wanted to come to their office (anywhere in the world) and spend a week working with the people who would become my coworkers and on the projects that I would be a part of.

After several experiences at different locations, I had the pleasure of spending a week in Chicago with the Obtivians. Finally, this was a place I knew I wanted to work at. Obtiva has some of the most amazing people I’ve had the pleasure of getting to know. Each of them is smart, passionate, interesting, modest, and inspiring. I knew I could only come out the other end of working with them a better developer and human being than before.

Several of my visits with offices prior to Obtiva felt like interesting and challenging places to work at, but none of them gave me an overwhelming sensation of happiness and excitement as Obtiva did and still does.

Ultimately, I don’t plan on being a consultant for most of my career, but I know that as long as I am one, I want to be one with these guys.

So, face up to what you want. Say no until you are moved to say yes as though by an external force (other than coercion!). There's no room for compromising on happiness, fulfillment, and personal growth.

Also, Obtiva kicks ass. If you are a passionate developer or have an interesting project, drop us a line, and let us move you to say "HELL YES!"

Restoring ghost entries from Time Machine backup

Pat Allan just had some trouble with his laptop and he lost a bunch of data.

After he pinged me asking where ghost stored it’s hostname entries so he could restore them, I realised I didn’t know. Sure, on Linux, ghost just writes out to the /etc/hosts file, but on OS X, it uses the dscl command to get to the Directory Services.

Long story short, if you ever want to know where and how Directory Services stores a lot of it’s information, it’s mostly in the /var/db/dslocal/nodes/Default/ directory.

Specifically, the hosts are stored in /var/db/dslocal/nodes/Default/hosts/ directory, one .plist file per host. Pat reports that just grabbing those files from a his backup and dropping them in that directory worked wonders.

Rails bug in versions 1, 2, and 3

Want to know how to raise a 500 error in any version of rails (so far)? Simply add ?a&a[] to the end of any URL in any Rails application.

I tested this on a number of known rails sites such as Chargify, Twitter, Groupon, Hoptoad (oh the irony), and even a Rails v1 website somebody managed to find.

For such an old bug (essentially as old as it can be), it’s quite funny that it was apparently patched less than two weeks ago.

Pausing Cucumber Scenarios to Debug

Continuing what I started with my post last light, I’ve got another tip for developing productively when using Cucumber.

I’m going to show you a simple way to pause cucumber stories in order to investigate the current state of your application at that point.

AfterStep('@pause') do
  print "Press Return to continue"
  STDIN.getc
end

Then just tag any Cucumber feature or scenario with @pause. After the first step is run, the scenario will stop running and you can do whatever you like before proceeding.

My favourite tactic is to combine the @pause tag with @selenium tag to have WebDriver stop driving FireFox for a moment and let me click around in the application or inspect the HTML/CSS at that point.

My next post will be about enabling FireBug in the "WebDriver" profile to help inspecting the web page when you’ve paused a scenario.

Selector-Free Cucumber Scenarios

(a Serbo-Croation translation by Anja Skrbaa is available here)

I’ve been using Cucumber since pretty much the first day I heard about it. I’ve worked on a lot of projects that have relied on it’s presence for reliable development. Therefore, I’ve put a lot of effort into perfecting my Cucumber infrastructure to make this fantastic tool even better. I’m going to share one such morsel of code that makes developing with Cucumber even greater.

The Problem

I’ve worked on a lot of web applications and, as I’m sure many of you know, quite often the development of a web application is focussed on the functionality foremost, and the interface and style is incorporated later. It may be that the client doesn’t yet know the feel they want for their project or that they want to focus their budget towards prototyping the application first.

This is fine, except for the fact that changing the HTML and CSS of a web application after a lot of functionality has been developed is a fantastic way to break all your integration tests.

This is particularly true if you have scenarios like the following contrived one:

When I fill in "Username" with "bjeanes" within ".main-panel form#signup-form"
And I press "Sign up!" within ".main-panel form#signup-form"
Then I should see "You have successfully signed up" within ".flash.notice"

The problem is, of course, that designers might change the HTML that used to be .main-panel form#signup-form into something sexier and more semantic.

The Solution

This problem is not unlike an already-solved one; we’ve all moved away from hardcoding URLs like "/users/new" into our views and Cucumber scenarios and replacing them with new_user_path and the signup page, respectively.

So why not apply the same formula that paths.rb uses for removing URLs from scenarios to our situation with selectors?

Here’s what I add to all new projects:

# I'm in features/step_definitions/web_ext_steps.rb

When /^(.*) within ([^:"]+)$/ do |step, scope|
  with_scope(selector_for(scope)) do
    When step
  end
end

# Multi-line version of above
When /^(.*) within ([^:"]+):$/ do |step, scope, table_or_string|
  with_scope(selector_for(scope)) do
    When "#{step}:", table_or_string
  end
end  

And:

# I'm in features/support/selectors.rb

module HtmlSelectorsHelper
  def selector_for(scope)
    case scope
    when /the body/
      "html > body"
    else
      raise "Can't find mapping from \"#{scope}\" to a selector.\n" +
        "Now, go and add a mapping in #{__FILE__}"
    end
  end
end

World(HtmlSelectorsHelper)

Applying the Solution

My previous example of the flawed Cucumber scenario now becomes:

When I fill in "Username" with "bjeanes" within the sign up form
And I press "Sign up!" within the sign up form
Then I should see "You have successfully signed up" within the notice flash

And the selectors.rb case statement gets the following additions:

case
  # ...

  when /the sign up form/
    ".main-panel form#signup-form"
  when /the (notice|error|info) flash/
    ".flash.#{$1}"

  # ...
end

Notice how the scenario now identifies things on our page by their semantic identifiers, not by brittle CSS or XPath locations which are prone to change. As a bonus, now if when they do change, the paths only need to be updated in a single location in our Cucumber test suite!

Patching Cucumber

I feel pretty strongly that CSS and XPath don’t belong in our feature files because not only does it encourage brittle tests (as shown above), but also because those selectors are entirely irrelevant to end users, and that’s kind of the main point of using a natural language DSL to describe our integration tests, i.e. putting on the user shoes.

I’d really like to patch this back into Cucumber, and I entirely plan to do so, providing I get the time.

I got the time, and here is my pull request to have it merged.

Expanding the Solution

You’ll note my HtmlSelectorsHelper module only accommodates CSS selectors. That’s only because I have never needed XPath in this context. It’d be very simple to modify my examples to do so, though, with a combination of multiple return values and a splat. That’s an exercise for the reader (or me if I end up patching Cucumber).

Final Word

I apologise for the length of this article, but I congratulate you for making it all the way through it!

I now have so many blog post ideas lined up that I’ve had to create a new category in Things.app just to hold them all. This means that I’ll be striving to get a few more posts done and out the door in the next few weeks, including a performance comparison of different data encapsulations for web application APIs on the iPhone (i.e. is it better to use Plists, JSON, or XML?) and a post on why I think there should be 8 RESTful actions, not the 7 that Rails prescribes by default.

Options to Improve Time To Profit

I’ve needed to refer to this fantastic article a number of times and have always had trouble finding the link, so I am posting it on my blog because I think it’s something everyone trying to sell Agile to clients should read and I know I’ll need it again.

Options to Improve Time To Profit

My Future

Mocra

Two weeks ago, Dr Nic informed me, and my coworkers, that he had accepted a job with EngineYard and was moving to San Francisco within the month. Unfortunately, a consequence of Nic’s wonderful opportunity is that he had to fire us all and shutdown Mocra.

Of course, he broke the news to us in a more humane way, and even encouraged me to take on the Mocra name and start a new company to continue on without him. I haven’t ruled it out yet, but I am taking this change as an opportunity to consider moving on in my career and having some new experiences with fresh and inspiring people.

Over the last two years at Mocra, I’ve helped run the business, managed the clients, and written awesome code, as well as worked on a slew of open source contributions and projects, such as ghost.

Possibilities

A few opportunities and offers have presented themselves already, even without having put myself out there, as I’m now trying. Some of them have been quite tempting, and I’ve been exploring them, but some have been less so.

After reading No more yes. It’s either HELL YEAH! or no, I’ve decided that I want to try to find a job that’s will make me say "HELL YEAH!" and go for it.

If you have a position or an endeavour that you think I might be right for, please get in contact; I’d love to have a chat about the company, idea, or your processes, and how we might be able to help each other.

I am looking for work starting from the beginning of September. My long-term goal is to move out of Brisbane, so relocating is an option I’d enthusiastically pursue. For a number of reasons, however, I’m tied to Brisbane until about the end of the year.

Therefore, I’d love to find a company that can accommodate me as a contractor for the few months until my partner and I are in a position to move out of Brisbane, at which point I’d be eager to come on as a full-timer. I am more than happy to come work on-site out of Brisbane before the New Year for small stints, though.

If you want to know more, I’ll be making my About page more relevant to my skills, experiences, and interests over the next day or so. In the mean time, feel free to email me or call me on skype or +61412639224 to start a conversation.

Fix encoding errors preventing PostgreSQL database creation

I recently was setting up a new VPS on Linode and I got the following error when trying to create a new database:

ERROR: new encoding is incompatible with the encoding of the template database
HINT: Use the same encoding as in the template database, or use template0 as template.

This error is related to the locale of the system when Postgres was installed. If you run the commands in my previous post before installing Postgres, you should avoid these errors altogether.

If Postgres has already been installed, however, you can run the following commands (assuming Postgres version 8.4) to reinitialise the database with the correct encoding:

pg_dropcluster --stop 8.4 main
pg_createcluster --start -e UTF-8 8.4 main

Note: this will erase all databases and reset your postgres configuration so it is only really useful when you are first setting up your database, or have taken appropriate measures to be able to restore your data.

Fix locale errors on linux

Have you ever gotten error messages such as the following when running commands such as apt-get?

perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
 LANGUAGE = ,
 LC*ALL = ,
 LC*CTYPE = "en*US.UTF~~8",
 LANG = 
 are supported and installed on your system.

I’ve had this problem quite a lot on my VPS boxes on Linode and SliceHost. The solution is simple, simply run the following:

locale-gen en_US.UTF-8
update-locale LANG=en_US.UTF-8