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.
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.
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!"
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.
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.
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.
(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.
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
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.
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.
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