Class: SwissMatch::Street

Inherits:
Object
  • Object
show all
Defined in:
lib/swissmatch/street.rb,
lib/swissmatch/street/version.rb

Overview

Street Parse and handle street names and numbers.

Constant Summary collapse

HouseNumber =

House number formats: ‘12’ ‘12b’ ‘12bis’, ‘12BIS’, ‘12Bis’, ‘12 bis’, … - see development/Noteworthy_things.txt ‘12 B’ ‘12/14’ ‘105-107’ ‘16/2/22’ ‘8-10-12’ ‘16-2/22’ ‘16/2-22’

/\d+(?:\x20?\w{1,2}|(?:\/\d+|-\d+\w{1,2})*)/
FrontHouseNumber =
/\d+(?:\x20?(?!ch|bd|av)\w{1,2}|(?:\/\d+|-\d+\w{1,2})*)/i
MatchStreetAndStreetNumberGerman =
/\A(.*?)(?:(?: |, ?)(#{HouseNumber}))\z/
MatchStreetAndStreetNumberFrench =
/\A(?:(#{FrontHouseNumber}), )(.*?)\z/
MatchBrokenStreetAndNumberGerman =
/\A(.*?)(?:(#{HouseNumber}))\z/
MatchBrokenStreetAndNumberFrench =
/\A(?:(#{FrontHouseNumber})[.,]| )(.*?)\z/
Replacements =

Abbreviations that can be expanded

{
  'ch'    => 'Chemin',
  'chem'  => 'Chemin',
  'rte'   => 'Route',
  'bd'    => 'Boulevard',
  'av'    => 'Avenue',
  'ave'   => 'Avenue',
  'str'   => 'strasse',
  'mte'   => 'Monte',
  's'     => 'san',
}
ReplacementsMatch =

Detect the abbreviations to expand

/\b(?:ch|chem|rte|bd|ave?|mte)(?:\.|\b)|\bs(?:\.|\b)(?!$)|\Bstr(?:\.|\b)/i
NoCapitalize =
{
  'auf'     => 'auf',
  'uf'      => 'uf',   # hurray for swiss german street names :D
  'em'      => 'em',
  'der'     => 'der',
  'die'     => 'die',
  'das'     => 'das',
  'von'     => 'von',
  'nach'    => 'nach',
  'im'      => 'im',
  'in'      => 'in',
  'zum'     => 'zum',
  'zur'     => 'zur',
  'unteren' => 'unteren',
  'oberen'  => 'oberen',

  'd'       => 'd',
  'de'      => 'de',
  'des'     => 'des',
  'du'      => 'du',
  'l'       => 'l',
  'le'      => 'le',
  'la'      => 'la',
  'les'     => 'les',
  'vers'    => 'vers',

  'il'      => 'il',
  'dei'     => 'dei',
  'di'      => 'di',
  'delle'   => 'delle',
  'della'   => 'della',
  'al'      => 'al',
  'alla'    => 'alla',
  'alle'    => 'alle',
  'ai'      => 'ai',
}
Version =

The version of the swissmatch-street gem.

Gem::Version.new("0.0.1")

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, number = nil, number_position = :end, original = nil) ⇒ Street

Returns a new instance of Street.



136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/swissmatch/street.rb', line 136

def initialize(name, number=nil, number_position=:end, original=nil)
  @name             = name
  @number           = number
  @number_position  = number_position
  @original         = original
  @full             = case number_position
    when :end then [name, number].compact.join(" ")
    when :begin then [number, name].compact.join(", ")
    when nil then name.dup
    else raise ArgumentError, "Invalid value for number_position: #{number_position.inspect}"
  end
end

Instance Attribute Details

#fullObject (readonly) Also known as: to_s

Returns the value of attribute full.



134
135
136
# File 'lib/swissmatch/street.rb', line 134

def full
  @full
end

#nameObject (readonly)

Returns the value of attribute name.



134
135
136
# File 'lib/swissmatch/street.rb', line 134

def name
  @name
end

#numberObject (readonly)

Returns the value of attribute number.



134
135
136
# File 'lib/swissmatch/street.rb', line 134

def number
  @number
end

#number_positionObject (readonly)

Returns the value of attribute number_position.



134
135
136
# File 'lib/swissmatch/street.rb', line 134

def number_position
  @number_position
end

#originalObject (readonly)

Returns the value of attribute original.



134
135
136
# File 'lib/swissmatch/street.rb', line 134

def original
  @original
end

Class Method Details

.normalize_name(name) ⇒ Object



106
107
108
109
110
# File 'lib/swissmatch/street.rb', line 106

def self.normalize_name(name)
  name.
    gsub(/\b[\p{Letter}\p{Mark}\p{Connector_Punctuation}]{2,}\b/) { |word| NoCapitalize.fetch(word.downcase) { word.capitalize } }.
    sub(/\b[\p{Letter}\p{Mark}\p{Connector_Punctuation}]{2,}\b/) { |word| word.capitalize } # [\p{Letter}\p{Mark}\p{Connector_Punctuation}] is \p{Word} without digits
end

.normalize_number(number) ⇒ Object



112
113
114
115
116
117
# File 'lib/swissmatch/street.rb', line 112

def self.normalize_number(number)
  return unless number
  normalized = number.downcase.delete('^0-9a-z/()-')

  normalized.empty? ? nil : normalized
end

.normalize_street(street) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/swissmatch/street.rb', line 92

def self.normalize_street(street)
  return '' unless street

  street.strip.
    squeeze(' ').
    gsub(/\s*-\s*/, '-').
    gsub(/\A(#{FrontHouseNumber}) /, '\1, '). # '24 Rue Baulacre'     => '24, Rue Baulacre' - but not '24 bd blabla' -> '24 Boulevard, Blabla'
    gsub(/\s*([.,])(?=\S)/, '\1 ').           # '283,Rte.de Meyrin'   => '283, Rte. de Meyrin; '283 ,Foo' => '283, Foo'
    gsub(ReplacementsMatch) { |m|             # ch., chem., str. etc. => chemin, strasse etc.
      Replacements[m.downcase.chomp('.')]
    }.
    gsub(/\s*n°\s*/, ' ')
end

.parse(street, normalize = false) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/swissmatch/street.rb', line 119

def self.parse(street, normalize=false)
  normalized        = normalize_street(street)
  name, number, pos = case normalized
    when MatchStreetAndStreetNumberGerman then [$1, $2, :end]
    when MatchStreetAndStreetNumberFrench then [$2, $1, :begin]
    when MatchBrokenStreetAndNumberGerman then [$1, $2, :end]
    when MatchBrokenStreetAndNumberFrench then [$2, $1, :begin]
    else [normalized, nil, nil]
  end
  name    = normalize_name(name) if normalize
  number  = normalize_number(number) if normalize

  new(name, number, pos, street)
end

Instance Method Details

#inspectObject



155
156
157
# File 'lib/swissmatch/street.rb', line 155

def inspect
  "#<Street #{self}>"
end

#original_or_fullObject



149
150
151
# File 'lib/swissmatch/street.rb', line 149

def original_or_full
  @original || @full
end