Working for Unboxed Consulting

Posted on October 12, 2009

I have not been posting lately, mostly because a lot has been happening. I have started to work for Unboxed Consulting. We are a relatively small Rails development and agile consultancy company who (try to) do agile the right way. It has been great to work with smart people who know their stuff and together with clients who are willing to try out proper agile. Fortunately it has worked out really well for us and we have been able to deliver consistently. Since February I have been involved in several projects including Channel Five's Holy Soap and the Fifth Gear / Gadget show website.

The nice thing about working on Holy Soap has been that we have built it from the ground up using BDD all the way. This has resulted in a comprehensive test suite using both RSpec and Cucumber. It feels good to be able to be confident about our code and trust that our tests will break if the site will break. There are 1236 cucumber scenarios amounting to a total of 11658 steps. This has inspired me to write some tools to manage large cucumber projects, but there is nothing far enough yet to report on. This weekend I will be attending the UK Rails Camp and hopefully I will find time to work on something like that.

Make CouchDB Peepcode work with current version of couchrest

Posted on February 23, 2009

Following along with the couchdb peepcode, I received the following error:

MissingSourceFile (no such file to load -- couchrest/helper/file_manager):
    /app/models/basic_model.rb:43:in `db'

The reason for the error is that the FileManager class is no longer a part of the couchrest gem. It's functionality is being pushed out to a stand alone script called couchapp which manages putting a directory structure into a design doc. Although there is a ruby gem for couchapp on github, it is in the process of getting left behind. The best version of couchapp is now the python version which can be installed doing a

sudo easy_install couchapp

For now though, I got an error from macports so I have been using the ruby version of couchapp just to be able to move on:

sudo gem install jchris-couchapp

So now there should be a utility couchapp which you can run from the command line. Next, in the self.db method in app/models/basic_model.rb replace

file_manager = CouchRest::FileManager.new(File.basename(full_url_to_database))
file_manager.push_views(File.join(Rails.root, "db", "views"))
with
system("couchapp push #{full_url_to_database}")
and continue following along with the peepcode.

Rails team for hire

Posted on May 02, 2008

Working for Naked was a blast, but unfortunately the time has come to move on. We felt as the dev team that we were working rather well together and are therefore offering ourselves for hire as a complete team, seasoned in all aspects of developing a project on Rails.

Feel free to contact me or any of its members informally if you may be interested.

http://www.workingwithrails.com/group/8792-an-entire-rails-team-for-hire

Pimping emacs rails mode

Posted on April 29, 2008

Steve Yegge's inspiring Emacs post has urged me to finally get my ass in gear and get some work done on maintaining the Rails on Emacs mode.

The current emacs-rails mode is available from Rubyforge and I have cloned the current version of it to github at http://github.com/tomtt/emacs-rails. The github wiki has a braindump with "things i want from my rails mode". This may contain things that are already working but I will find that out as I go along :).

My plan is to have the github version be just how I like my mode, but I will push some of the things that work back into the official repository. I intend for Rubyforge to remain the authoritative site for tickets.

Rails schema browser plugin: proof of concept

Posted on February 12, 2008

I have just created my first rails plugin which is a proof of concept interactive graphical viewer for your database schema and relations. It is still very rough around the edges and I have not had as much time as I hoped due to starting a great job at Naked. I'm expecting to make some time for this soon though.

For an example of what you might expect see the schema browser of my own mephisto blog. Tables are drawn based on the tables defined in the current database and relations based on the belongs_to relations defined in the models.

Installing the schema_browser plugin:

cd yourapp/vendor/plugins
git clone git://github.com/tomtt/schema-browser.git
cd ../../
./script/generate schema_browser

Things may work for you this way, but it is also totally possible that you will have to add corresponding routes to config/routes.rb:

  map.connect 'schema_browser', :controller => "schema_browser"
  map.connect 'schema_browser/schema', :controller => "schema_browser", :action => "schema"

If you have to do this, you may also have to restart your server.

The schema browser is now available at http://yoursite.com/schema_browser. Note that currently this would be shown in production as well which may not be something you want. Disabling the schema browser in production is one of many future plans for this plugin.
The xml representation is available at http://yoursite.com/schema_browser/schema

The javascript code to view this was taken from http://ondras.zarovi.cz/sql/ which is an amazing piece of work.

I'd be interested to hear if it is possible to serve up a git repos as if it were an svn repos so that script/plugin install would still work.

Real programmers

Posted on February 01, 2008

If you have geeky personal tendencies, you should know about xkcd. Here's a recent strip featuring my favourite editor.

By the way, xkcd mouse overs are the funniest bit sometimes, but firefox does not show them out of the box. Fortunately this is fixed by the Long Titles extension.

RSpec plain text story runner on a fresh rails app

Posted on January 25, 2008

RSpec is a wonderful Behaviour Driven Development framework that is also very suitable for Rails applications. After giving a talk on it for the Scotland Ruby usergroup I found that people are most impressed with its plain text story runner feature. I have found documentation on this rather meager so I created this post on how to setup a rails app from scratch that has a story with some scenarios that all pass. Once I had this in place the rest was a piece of cake*...

To find out more about how the story runner works have a look at the links at the bottom of this post. The peepcode on the issue is good and between the posts by David Chelimsky - the creator of this stuff - there is some useful information as well.

The central idea is to define each part of an acceptance test (given ... when ... then ...) as an English sentence. These sentences are then defined as 'steps' which perform the corresponding action or test. Once you have built up a decent library of steps a client can have a good shot at writing his own acceptance tests. Any sentences that are not yet covered by a step will show up as pending.

On with the practical business!

We do not need much of a rails app for us to be able to test it with a story. I will just use a fresh rails install with the needed RSpec and restful_authentication plugins. Like so:

$ rails storyapp
$ cd storyapp
$ rake db:create:all # after setting up database.yml for your system
$ ./script/plugin install git://github.com/dchelimsky/rspec.git
$ ./script/plugin install git://github.com/dchelimsky/rspec-rails.git
$ ./script/generate rspec
$ ./script/plugin install git://github.com/technoweenie/restful-authentication.git
$ ./script/generate authenticated user
$ rake db:migrate
$ rake db:test:prepare
Add the following snippet to your config/routes.db to define login/logout routes:
map.with_options :controller => "sessions" do | page |
   page.login "/login", :action => "new"
   page.logout "/logout", :action => "destroy"
end

At this stage you should be able to start your rails server and find a login form at http://localhost:3000/login. Our application behaves as follows: if you login with invalid credentials (all of them are until a user is created) you will be shown the login form again. If you create a user from http://localhost:3000/users/new this user will be created in the database and you will be redirected to "/" (for now still showing the default rails page). So let's write a story that tests this behaviour. First there is some more setting up to do though...

I am choosing the convention to name my text stories stories/foo_story and the corresponding runner stories/foo_story.rb. All steps will be named stories/steps/foo_steps.rb. My spec_helper will automatically require all the step files in the stories/steps directory. This is how we set this up:

$ mkdir stories/steps
and add stuff to your stories/helper.rb so that it looks like this:
ENV["RAILS_ENV"] = "test"
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
require 'spec/rails/story_adapter'
require 'ruby-debug'

dir = File.dirname(__FILE__)
Dir[File.expand_path("#{dir}/steps/*.rb")].uniq.each do |file|
  require file
end

##
# Run a story file relative to the stories directory.

def run_local_story(filename, options={})
  run File.join(File.dirname(__FILE__), filename), options
end

This is the story we will be using, so go ahead and save that as stories/login_story:

Story: User logging in

  As a user
  I want to login with my details
  So that I can get access to the site

  Scenario: User uses wrong password

    Given a username 'jdoe'
    And a password 'letmein'

    When the user logs in with username and password

    Then the login form should be shown again

  Scenario: Creates a new user

    Given a username 'jdoe'
    And a password 'letmein'
    And an email 'jdoe@test.com'
    And there is no user with this username

    When the user creates an account with username, password and email

    Then there should be a user named 'jdoe'
    And should redirect to '/'

And this is the corresponding stories/login_story.rb which just runs the file we just created using the steps we are about to define:

require File.dirname(__FILE__) + "/helper"

with_steps_for(:login) do
  run_local_story "login_story", :type => RailsStory
end

Save the steps for this story to stories/steps/login_steps.rb:

steps_for(:login) do
  Given "a username '$username'" do |username|
    @username = username
  end

  Given "a password '$password'" do |password|
    @password = password
  end

  Given "an email '$email'" do |email|
    @email = email
  end

  Given "there is no user with this username" do
    User.find_by_login(@username).should be_nil
  end

  When "the user logs in with username and password" do
    post "/sessions/create", :user => { :login => @username, :password => @password }
  end

  When "the user creates an account with username, password and email" do
    post "/users/create", :user => { :login => @username,
                                     :password => @password,
                                     :password_confirmation => @password,
                                     :email => @email }
  end

  Then "the login form should be shown again" do
    response.should render_template("sessions/new")
  end

  Then "there should be a user named '$username'" do |username|
    User.find_by_login(username).should_not be_nil
  end

  Then "should redirect to '$path'" do |path|
    response.should redirect_to(path)
  end
end

When you put a $something in the sentence of a step, RSpec will extract a value from a matching sentence in your story and pass that into the block. Note that what you put after your $ is just fluff. It is good practice to put quotes around your values so that there are less cases where the regexp matcher will get confused and split things up in a way you did not expect. Some character based regexp expressions are allowed as well. So Then "it has $n users?" will match "then it has 2 users" as well as "then it has 1 user".

We're all set! Run:

$ ruby stories/login_story.rb
et voilà:
2 scenarios: 2 succeeded, 0 failed, 0 pending

Success!

Here is a tarball with the git repos of the steps taken in this article.

Additional info on RSpec's plain text story runner:

*: the cake is a lie!

Update 2008-05-27: I have changed the plugin install commands to use the git repositories instead. The original install commands were:

$ ./script/plugin install svn://rubyforge.org/var/svn/rspec/trunk/rspec
$ ./script/plugin install svn://rubyforge.org/var/svn/rspec/trunk/rspec_on_rails
$ ./script/plugin install http://svn.techno-weenie.net/projects/plugins/restful_authentication/

Disabling default package checking for unknown Ubuntu commands

Posted on December 21, 2007

Ubuntu comes with a nifty script installed that is run when you type a non-existing command. It checks to see if there is a package that will provide this command and if there is it will show you a nice message how to install it. I do like this functionality but now that my system has pretty much all I need, the slight delay caused by running the script has become annoying. I could just do a 'sudo apt-get remove command-not-found' but I would still like to able to quickly check if there is a package providing a command if I want to. A few lines added to my ~/.bashrc can do exactly that:

command_not_found_handle() {
  return 127
}
alias check-command=/usr/lib/command-not-found

This redefines the command_not_found_handle defined in /etc/bash.bashrc to just display an error message and gives me check-command to check if a package is available for a command. And finally again 'l s-l' will barf at me instantly again :). And:

$ check-command aatv
The program 'aatv' is currently not installed.  You can install it by typing:
sudo apt-get install aatv

$ check-command emacs
Command 'emacs' is available in '/usr/bin/emacs'

True Porn Clerk Stories

Posted on December 13, 2007
This one has been on the inter tubes for a while but comes highly recommended by me. Ali Davis kept a journal of stories about her experiences working at a video store.

Feynman: online resources

Posted on December 11, 2007

My foremost personal hero is Richard Feynman: extravagant extraordinaire and reluctant Nobel prize winner. His skill at explaining his field (theoretical physics in general and quantum mechanics in particular) was so remarkable that the notes he prepared 44 years ago are still used by physics majors world wide. More impressively: after listening to his lectures even I briefly feel like I understand the subject :). He had the guts to stand up for what he believed was the right thing to do against advise by others: a quality that seems to be all too rare these days.

Here is a list of available online resources of Richard Feynman:

xkcd

An emacs koan

Posted on December 11, 2007

A novice of the temple once approached the Master Programmer with a question. "Master, does Emacs have the Buddha nature?" the novice asked. The Master Programmer had been in the temple for many years and could be relied upon to know these things. He thought for several minutes before replying. "I don't see why not. It's bloody well got everything else."

(shamelessly lifted from ykr)

Emacs, flymake and autotest: the fix

Posted on December 10, 2007

I sure do love my autotest but I have been having problems due to how it interacts with emacs.

Emacs rails mode uses flymake to do syntax checking while you type and to do this it creates a file called buffer_name_flymake.rb in the current directory. When autotest detects this file, it starts to run it but by that time emacs has closed and deleted it already which causes autotest to crash.

The only solution I could find online was to set exceptions of the Autotest instance so that it will match the flymake file, but autotest only prunes directories and therefore this does not work.

My solution was to add one line to the find_files method in gems/ZenTest-3.6.1/lib/autotest.rb after line 292 that makes it always ignore flymake files:

289       ...
290       next if test ?d, f
291       next if f =~ /(swp|~|rej|orig)$/        # temporary/patch files
292       next if f =~ /\/\.?#/                     # Emacs autosave/cvs merge files
293       next if f =~ /_flymake\.\w+$/      # Emacs flymake files
294       ...

Download the entire patched file

I have submitted a patch with this fix so hopefully the ZenTest people will include it in the next release.

First post!

Posted on December 04, 2007

Putting a weblog online has been long coming - being a web professional and all that - so I thought I'd spend my day doing just that. And here it is!

Featuring: Ruby on Rails (on edge), Mephisto, Haml, Slicehost, Gutsy Ubuntu, Apache, Mongrel and many others.