Class: Fullname::Matcher::Core

Inherits:
Object
  • Object
show all
Defined in:
lib/fullname/matcher/core.rb

Defined Under Namespace

Classes: Error

Constant Summary collapse

DEFAULT_MAPPING =
{:first => 'first', :middle => 'middle', :last => 'last', :suffix => 'suffix'}
DEFAULT_OPTIONS =
{
  :skip_match_middle_name => false, # skip match middle name if middle name not provided.
  :skip_match_suffix => false      # skip match suffix if suffix not provided or no column suffix in database.
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(table, mapping = {}, options = {}) ⇒ Core

Returns a new instance of Core.



41
42
43
44
45
46
# File 'lib/fullname/matcher/core.rb', line 41

def initialize(table, mapping = {}, options = {})
  @table        = table
  @mapping      = DEFAULT_MAPPING.merge(mapping)
  @condition    = nil
  @options      = DEFAULT_OPTIONS.merge(options)
end

Instance Attribute Details

#optionsObject

Returns the value of attribute options.



39
40
41
# File 'lib/fullname/matcher/core.rb', line 39

def options
  @options
end

Instance Method Details

#abbr_match?(str1, str2) ⇒ Boolean

2 strings are ‘abbr-match’ed if . they are same, or . one string is one char long and the other starts with it ex: ‘abc edf’ abbr-matches ‘a. e’ or ‘abc edf’, but not ‘abc e’

Returns:

  • (Boolean)


140
141
142
# File 'lib/fullname/matcher/core.rb', line 140

def abbr_match?(str1, str2)
  build_middlename_regexp(str1) =~ str2
end

#get_matches(*args) ⇒ Object Also known as: match_fullname



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/fullname/matcher/core.rb', line 52

def get_matches(*args)
  name = nil
  match_options = {}
  case args.size
  when 1
    name = ::Fullname::Parser.parse_fullname(args[0])
  when 4,5
    name = {:first => args[0], :middle => args[1], :last => args[2], :suffix => args[3]}
    match_options = args.pop if args.size == 5
  else
    raise Error, 'illeagle arguments length of get_matches, must be the length of 1,4,5'
  end
  recursive = match_options.include?(:recursive) ? match_options[:recursive] : true
  return [] if name[:first].nil? || name[:last].nil?
  match_list = match_first_last_and_suffix(name)
  
  # skip validating middlename if @options[:skip_match_middle_name] == true
  # all matched result which middle name is NULL or NON-NULL will be returned
  return match_list if @options[:skip_match_middle_name] && match_list.size > 0
  
  if match_list.size > 0
    # 1. exactly match
    exact_match_list = match_list.select do |r|
      compare_without_dot(r.send(@mapping[:middle]), name[:middle]) && compare_without_dot(r.send(@mapping[:suffix]), name[:suffix])
    end
    return exact_match_list if exact_match_list.size > 0
    
    # 2. if name[:middle] is not NULL, regexp match
    if name[:middle]
      m_re = build_middlename_regexp(name[:middle])
      match_list_with_middlename = match_list.select do |r|
        r_middle_name = r.send(@mapping[:middle])
        r_middle_name && r_middle_name =~ m_re
      end
      return match_list_with_middlename if match_list_with_middlename.size > 0
      # 2.1 fuzzy match: if middlename in DB is NULL, it matches
      match_list_with_middlename = match_list.select{ |r| r.send(@mapping[:middle]).nil? }
      return match_list_with_middlename if match_list_with_middlename.size > 0
      # clear match list if don't match middlename
      match_list = []
    else
      # 2.2 fuzzy match: assume all matches since name[:middle] is NULL
      return match_list
    end        
  end
  
  # if nothing matches, try to search with equivalence of first name
  if match_list.size == 0 && recursive
    firstname_array = ::Fullname::Equivalence.get_name_equivalence(name[:first])
    firstname_array.each do |n|
      match_list += get_matches(n, name[:middle], name[:last], name[:suffix], {:recursive => false})
    end if firstname_array
  end
  
  return match_list
end

#names_match?(n1, style1, n2, style2) ⇒ Boolean

return true if two names (n1 and n2) are same; false otherwise style = :short means the pieces are first/middle/last/suffix; firstname/middlename/lastname/suffix otherwise

Returns:

  • (Boolean)


113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/fullname/matcher/core.rb', line 113

def names_match?(n1, style1, n2, style2)
  f1 = style1 == :short ? n1.first : n1.firstname
  m1 = style1 == :short ? n1.middle : n1.middlename
  l1 = style1 == :short ? n1.last : n1.lastname
  
  f2 = style2 == :short ? n2.first : n2.firstname
  m2 = style2 == :short ? n2.middle : n2.middlename
  l2 = style2 == :short ? n2.last : n2.lastname
  
  # first/last name have to be provided
  return false if l1.nil? || l2.nil? || f1.nil? || f2.nil?
  return false if l1.downcase.strip != l2.downcase.strip
  
  unless @options[:skip_match_suffix]
    s1 = n1.suffix
    s2 = n2.suffix
    return false  if s1 && s2 && compare_without_dot(s1, s2) == false
  end
  
  return false if !abbr_match?(f1, f2)
  m1.nil? or m2.nil? or abbr_match?(m1, m2)
end

#set_condition(c) ⇒ Object



48
49
50
# File 'lib/fullname/matcher/core.rb', line 48

def set_condition(c)
  @condition = c
end