We do a lot of data migrations for Donor Tools – a lot of folks are coming to us from other systems, and they need their data ported over. Depending on the kind of system they were using, this can be anywhere from a quick script to a major data transformation headache.

Recently I needed a quick way to parse a full name string into name parts. Given a name like “Dr. Joe Donor, M.D.”, I wanted to end up with a name object with a prefix of “Dr.”, a suffix of “M.D.”, a first name of “Joe”, and a last name of “Donor”. Complicating matters, it also needed to be able to handle odd permutations like “Dr. and Mrs. Joe and Jane Donor”, etc.

The main problem that I had was with the “and”. If there was an “and”, it should put the preceding and following words together to form a single word. This turned out to be nearly impossible with regular expressions, but pretty easy with a combination of Ruby and regex. Here’s how it looks.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Name < ActiveRecord::Base

  def self.parse(name)
    return false unless name.is_a?(String)
    
    # First, split the name into an array
    parts = name.split
    
    # If any part is "and", then put together the two parts around it
    # For example, "Mr. and Mrs." or "Mickey and Minnie"
    parts.each_with_index do |part, i|
      if ["and", "&"].include?(part) and i > 0
        p3 = parts.delete_at(i+1)
        p2 = parts.at(i)
        p1 = parts.delete_at(i-1)
        parts[i-1] = [p1, p2, p3].join(" ")
      end
    end
    
    # Build a hash of the remaining parts
    {
      :suffix => (s = parts.pop unless parts.last !~ /(\w+\.|[IVXLM]+|[A-Z]+)$/),
      :last_name  => (l = parts.pop),
      :prefix => (p = parts.shift unless parts[0] !~ /^\w+\./),
      :first_name => (f = parts.shift),
      :middle_name => (m = parts.join(" "))
    }
  end

end

Here’s the output:

1
2
3
4
5
6
7
8
9
10
11
Name.parse "Mr. Joe Donor"
=> {:middle_name=>"", :prefix=>"Mr.", :last_name=>"Donor", :suffix=>nil, :first_name=>"Joe"}

Name.parse "Dr. and Mrs. Joe Donor, M.D."
=> {:middle_name=>"", :prefix=>"Dr. and Mrs.", :last_name=>"Donor,", :suffix=>"M.D.", :first_name=>"Joe"}

Name.parse "Joe and Jane Donor"
=> {:middle_name=>"", :prefix=>nil, :last_name=>"Donor", :suffix=>nil, :first_name=>"Joe and Jane"}

Name.parse "Joe and Jane Major-Donor"
=> {:middle_name=>"", :prefix=>nil, :last_name=>"Major-Donor", :suffix=>nil, :first_name=>"Joe and Jane"}

Here’s a quick and easy way to track exactly where your signups are coming from, and who referred any given customer, without having to cross-reference your analytics program.

1
2
3
4
5
before_filter: set_referer

def set_referer
  cookies[:referer] = request.env['HTTP_REFERER'] if cookies[:referer].nil?
end

The set_referer method sets up a session variable that keeps the original referrer with your customer, no matter how many pages they click through before signing up.

You can email this variable to yourself when they sign up, or store it in the database to keep track of who came from where.