Coding is like gardening...

Personal victories

I love it when you can refactor a bulky, ugly function down into one line. It always makes me very happy indeed. Here is my solution for outputting a person’s name in a nice format, taking title, initials, first name, surname, suffix. Initials take precedence over first name.

This is how i did it originally:

  def contact_display_name
    returning String.new do |output|
      output << title + ' ' unless title.blank?
      if initials
        output << initials + ' ' unless initials.blank?
      else
        output << first_name + ' ' unless first_name.blank?
      end
      output << surname + ' ' unless surname.blank?
      output << suffix unless suffix.blank?
      output.strip!
    end
  end

Rather too long-winded for my liking. I managed to refactor it down to this:

def contact_display_name
    [title, (initials? ? initials : first_name),
      surname, suffix].delete_if(&:blank?).join(' ')
  end

Of course, it is another advantage of behaviour-driven development, that i had already specced out what i wanted to happen, and i could use the specs to ensure that my two versions of the function were equivalent. See below for the specs that verify the behaviour.

 describe "contact_display_name" do
    it "should output the first_name and surname" do
      contact = Contact.new(:first_name => 'Gabriel', :surname =< 'Gray')
      contact.contact_display_name.should == 'Gabriel Gray'
    end

    it "should use the title if there is one" do
      contact = Contact.new(:title => 'Mr', :first_name => 'Gabriel',
        :surname => 'Gray')
      contact.contact_display_name.should == 'Mr Gabriel Gray'
    end

    it "should use the initials rather than the first_name if it has them" do
      contact = Contact.new(:title => 'Mr', :initials => 'G',
        :first_name => 'Gabriel', :surname => 'Gray')
      contact.contact_display_name.should == 'Mr G Gray'
    end

    it "should add on the suffix if there is one" do
      contact = Contact.new(:first_name => 'Gabriel', :surname => 'Gray',
        :suffix => 'BSc Hons')
      contact.contact_display_name.should == 'Gabriel Gray BSc Hons'
    end

    it "should not mind if there is no first name or initials" do
      contact = Contact.new(:title => 'Mr', :surname => 'Gray')
      contact.contact_display_name.should == 'Mr Gray'
    end

    it "should ignore any nil values" do
      contact = Contact.new(:title => '', :first_name => nil,
        :surname => 'Gray')
      contact.contact_display_name.should == 'Gray'
    end
  end

2 Responses to “Personal victories”

  1. Richard says:

    Thats the really cool thing that I have learnt from Ruby. If the code looks messy or there is a lot of repetition then there is usually a much shorter way of writing it. However I do find that sometimes cutting it down a lot can sometimes make its purpose or function less obvious (not in this case), or is that just me?

  2. Aimee says:

    Yes, there is still a case for ‘clarity over cleverness’. You could write an amazing one-liner that’s really fast and impressive, but nobody can understand actually what it does. I must remain vigilant not to fall into that trap.

    Another potential trap of refactoring is what i call the ‘treasure trail’. You break everything down into tiny little functions which call other functions, often in different files. It can be quite a hunt to find the piece of code you’re looking for.