Module: Utilities::PersonNameMatch

Defined in:
lib/utilities/person_name_match.rb

Class Method Summary collapse

Class Method Details

.normalize(name) ⇒ Object (private)



52
53
54
# File 'lib/utilities/person_name_match.rb', line 52

def self.normalize(name)
  (name || '').downcase.strip.gsub(/\s+/, ' ')
end

.score_first_name_match(person_first_name, parsed_first_name) ⇒ Object

Score how closely a stored first name matches a parsed first name. Parts are compared positionally: 2 points for exact word match, 1 for matching initial.



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/utilities/person_name_match.rb', line 5

def self.score_first_name_match(person_first_name, parsed_first_name)
  p_parts = normalize(parsed_first_name).gsub('.', ' ').split.reject(&:empty?)
  s_parts = normalize(person_first_name).gsub('.', ' ').split.reject(&:empty?)

  return 0 if p_parts.empty?
  return -1 if s_parts.empty?

  score = 0
  [p_parts.length, s_parts.length].min.times do |i|
    if p_parts[i] == s_parts[i]
      score += 2
    elsif p_parts[i][0] == s_parts[i][0]
      score += 1
    end
  end

  score
end

.score_last_name_match(person_last_name, parsed_last_name) ⇒ Object

Score how closely a stored last name matches a parsed last name. 2 points per word in common.



26
27
28
29
30
31
32
33
34
35
36
# File 'lib/utilities/person_name_match.rb', line 26

def self.score_last_name_match(person_last_name, parsed_last_name)
  p_words = normalize(parsed_last_name).split.to_set
  s_words = normalize(person_last_name).split.to_set

  return 0 if p_words.empty?
  return -1 if s_words.empty?

  score = 0
  p_words.each { |w| score += 2 if s_words.include?(w) }
  score
end

.score_match(person_first_name, person_last_name, parsed_first_name, parsed_last_name) ⇒ Object

Combined score: last name weighted 10x over first name.



39
40
41
42
# File 'lib/utilities/person_name_match.rb', line 39

def self.score_match(person_first_name, person_last_name, parsed_first_name, parsed_last_name)
  score_last_name_match(person_last_name, parsed_last_name) * 10 +
    score_first_name_match(person_first_name, parsed_first_name)
end

.sort_by_match(people, parsed_first_name, parsed_last_name) ⇒ Object

Sort people by descending match score against the parsed name. people must respond to #first_name and #last_name.



46
47
48
49
50
# File 'lib/utilities/person_name_match.rb', line 46

def self.sort_by_match(people, parsed_first_name, parsed_last_name)
  people.sort_by do |person|
    -score_match(person.first_name, person.last_name, parsed_first_name, parsed_last_name)
  end
end