Module: GoingPostal

Extended by:
GoingPostal
Included in:
GoingPostal
Defined in:
lib/going_postal.rb

Constant Summary collapse

COUNTRIES_WITHOUT_POSTCODES =
Set[
  "AO", # Angola
  "AG", # Antigua and Barbuda
  "AN", # Netherlands Antilles
  "AW", # Aruba
  "BS", # Bahamas
  "BZ", # Belize
  "BJ", # Benin
  "BW", # Botswana
  "BF", # Burkina Faso
  "BI", # Burundi
  "CI", # Côte d’Ivoire
  "CD", # Congo, the Democratic Republic of the
  "CG", # Congo (Brazzaville)
  "CM", # Cameroon
  "CF", # Central African Republic
  "CW", # Curaçao
  "KM", # Comoros
  "CK", # Cook Islands
  "DJ", # Djibouti
  "DM", # Dominica
  "GQ", # Equatorial Guinea
  "ER", # Eritrea
  "FJ", # Fiji
  "GM", # Gambia
  "GH", # Ghana
  "GD", # Grenada
  "GN", # Guinea
  "GY", # Guyana
  "HK", # Hong Kong
  "IE", # Ireland
  "KI", # Kiribati
  "KP", # North Korea
  "MO", # Macau
  "MW", # Malawi
  "ML", # Mali
  "MR", # Mauritania
  "MU", # Mauritius
  "MS", # Montserrat
  "NA", # Namibia
  "NR", # Nauru
  "NU", # Niue
  "PA", # Panama
  "QA", # Qatar
  "RW", # Rwanda
  "KN", # Saint Kitts and Nevis
  "LC", # Saint Lucia
  "ST", # Sao Tome and Principe
  "SC", # Seychelles
  "SL", # Sierra Leone
  "SB", # Solomon Islands
  "SO", # Somalia
  "SR", # Suriname
  "SX", # Sint Maarten
  "SY", # Syria
  "TF", # French Southern and Antarctic Territories
  "TK", # Tokelau
  "TL", # East Timor
  "TO", # Tonga
  "TT", # Trinidad and Tobago
  "TV", # Tuvalu
  "TZ", # Tanzania
  "UG", # Uganda
  "AE", # United Arab Emirates
  "VU", # Vanuatu
  "YE", # Yemen
  "ZW"  # Zimbabwe
]

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.not_required?(country_code) ⇒ Boolean

:call-seq: GoingPostal.not_required?(country_code) -> bool

Returns true if the country spcified by the two letter country code country_code argument does not require postcodes, false otherwise.

Returns:

  • (Boolean)


125
126
127
# File 'lib/going_postal.rb', line 125

def self.not_required?(country_code)
  COUNTRIES_WITHOUT_POSTCODES.include?(country_code.to_s.upcase)
end

.required?(country_code) ⇒ Boolean

:call-seq: GoingPostal.not_required?(country_code) -> bool

Returns true if the country spcified by the two letter country code country_code argument requires postcodes, false otherwise.

Returns:

  • (Boolean)


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

def self.required?(country_code)
  !not_required?(country_code)
end

Instance Method Details

#format_at_postcode(string) ⇒ Object



298
299
300
# File 'lib/going_postal.rb', line 298

def format_at_postcode(string)
  format_ch_postcode(string)
end

#format_au_postcode(string) ⇒ Object Also known as: format_nz_postcode, format_za_postcode



264
265
266
267
# File 'lib/going_postal.rb', line 264

def format_au_postcode(string)
  string = string.to_s.delete(" \t\r\n")
  string if string =~ /^[0-9]{4}$/
end

#format_be_postcode(string) ⇒ Object



290
291
292
# File 'lib/going_postal.rb', line 290

def format_be_postcode(string)
  format_ch_postcode(string)
end

#format_ca_postcode(string) ⇒ Object



255
256
257
258
259
260
261
262
# File 'lib/going_postal.rb', line 255

def format_ca_postcode(string)
  forward_sort_area = string.to_s.upcase.delete(" \t\r\n")
  local_delivery_unit = forward_sort_area.slice!(-3, 3)
  if forward_sort_area =~ /^[A-CEGHJK-NPR-TVXY][0-9][A-CEGHJK-NPR-TV-Z]$/ &&
    local_delivery_unit =~ /[0-9][A-CEGHJK-NPR-TV-Z][0-9]/
    [forward_sort_area, local_delivery_unit].join(" ")
  end
end

#format_ch_postcode(string) ⇒ Object



281
282
283
284
# File 'lib/going_postal.rb', line 281

def format_ch_postcode(string)
  string = string.to_s.delete(" \t\r\n")
  string if string =~ /^[1-9][0-9]{3}$/
end

#format_de_postcode(string) ⇒ Object



313
314
315
316
# File 'lib/going_postal.rb', line 313

def format_de_postcode(string)
  string = string.to_s.upcase.delete(" \t\r\n")
  string if string =~ /^([0]{1}[1-9]{1}|[1-9]{1}[0-9]{1})[0-9]{3}$/
end

#format_dk_postcode(string) ⇒ Object



286
287
288
# File 'lib/going_postal.rb', line 286

def format_dk_postcode(string)
  format_ch_postcode(string)
end

#format_fr_postcode(string) ⇒ Object



328
329
330
# File 'lib/going_postal.rb', line 328

def format_fr_postcode(string)
  format_de_postcode(string)
end

#format_gb_postcode(string) ⇒ Object Also known as: format_uk_postcode



245
246
247
248
249
250
251
252
# File 'lib/going_postal.rb', line 245

def format_gb_postcode(string)
  out_code = string.to_s.upcase.delete(" \t\r\n")
  in_code = out_code.slice!(-3, 3)
  if out_code =~ /^[A-Z]{1,2}([1-9][0-9A-HJKMNPR-Y]?|0[A-HJKMNPR-Y]?)$/ &&
    in_code =~ /^[0-9][A-HJLNP-Z]{2}$/
    [out_code, in_code].join(" ")
  end
end

#format_lu_postcode(string) ⇒ Object



294
295
296
# File 'lib/going_postal.rb', line 294

def format_lu_postcode(string)
  format_ch_postcode(string)
end

#format_nl_postcode(string) ⇒ Object



302
303
304
305
306
# File 'lib/going_postal.rb', line 302

def format_nl_postcode(string)
  string = string.to_s.upcase.delete(" \t\r\n")
  string.insert(4, " ") if string.length >= 4
  string if string =~ /^[1-9][0-9]{3} (S[BCE-RT-Z]|[A-RT-Z][A-Z])$/
end

#format_no_postcode(string) ⇒ Object



323
324
325
326
# File 'lib/going_postal.rb', line 323

def format_no_postcode(string)
  string = string.to_s.upcase.delete(" \t\r\n")
  string if string =~ /^[0-9]{4}$/
end

#format_non_postcode(string) ⇒ Object Also known as: format_ie_postcode

:stopdoc:



239
240
241
# File 'lib/going_postal.rb', line 239

def format_non_postcode(string)
  nil
end

#format_pl_postcode(string) ⇒ Object



308
309
310
311
# File 'lib/going_postal.rb', line 308

def format_pl_postcode(string)
  match = /^(\d\d)[^\w]*(\d\d\d)$/.match(string)
  match.captures.join("-") if match && match[1] && match[2]
end

#format_postcode(*args) ⇒ Object Also known as: format_post_code, format_zip, format_zipcode, format_zip_code

:call-seq: format_postcode([string[, country_code]]) -> formatted_str or nil

Returns a formatted postcode as a string if string is a valid postcode, nil otherwise.

If calling this method on the GoingPostal module the country_code argument is required and should be a two letter country code.

If the GoingPostal module has been mixed in to a class, and the class has a #country_code method, the country_code argument is optional, defaulting to the value returned by #country_code. If the class also has a #postcode, #post_code, #zipcode, #zip_code, or #zip method, the string argument becomes optional.

Postcodes for unknown countries will simply be stripped of leading and trailing whitespace.

Countries without postcodes will always return nil. – The magic is done calling a formatting method for each country. If no such method exists a default method is called stripping the leading and trailing whitespace. ++



223
224
225
226
227
228
229
230
231
# File 'lib/going_postal.rb', line 223

def format_postcode(*args)
  string, country_code = get_args_for_format_postcode(args)
  method = if GoingPostal.not_required?(country_code)
    :format_non_postcode
  else
    :"format_#{country_code.to_s.downcase}_postcode"
  end
  respond_to?(method) ? __send__(method, string) : string.to_s.strip
end

#format_ro_postcode(string) ⇒ Object



332
333
334
335
# File 'lib/going_postal.rb', line 332

def format_ro_postcode(string)
  string = string.to_s.delete(" \t\r\n")
  string if string =~ /^[0-9]{6}$/
end

#format_se_postcode(string) ⇒ Object



318
319
320
321
# File 'lib/going_postal.rb', line 318

def format_se_postcode(string)
  string = string.to_s.upcase.delete(" \t\r\n")
  string if string =~ /^[1-9]{1}[0-9]{4}$/
end

#format_us_zipcode(string) ⇒ Object Also known as: format_us_postcode



271
272
273
274
275
276
277
278
# File 'lib/going_postal.rb', line 271

def format_us_zipcode(string)
  zip = string.to_s.delete("- \t\r\n")
  plus_four = zip.slice!(5, 4)
  plus_four = nil if plus_four && plus_four.empty?
  if zip =~ /^[0-9]{5}$/ && (plus_four.nil? || plus_four =~ /^[0-9]{4}$/)
    [zip, plus_four].compact.join("-")
  end
end

#postcode?(*args) ⇒ Boolean Also known as: post_code?, zip?, zipcode?, zip_code?, valid_postcode?, valid_post_code?, valid_zip?, valid_zipcode?, valid_zip_code?, postcode_valid?, post_code_valid?, zip_valid?, zipcode_valid?, zip_code_valid?

:call-seq: postcode?([string[, country_code]]) -> formatted_str or false

Returns a formatted postcode as a string if string is a valid postcode, false otherwise.

If calling this method on the GoingPostal module the country_code argument is required and should be a two letter country code.

If the GoingPostal module has been mixed in to a class, and the class has a #country_code method, the country_code argument is optional, defaulting to the value returned by #country_code. If the class also has a #postcode, #post_code, #zipcode, #zip_code, or #zip method, the string argument becomes optional.

Postcodes for unknown countries will always be considered valid, the return value will consist of the input stripped of leading and trailing whitespace.

For countries without postcodes, “” will be returned from in input of “” or nil, false otherwise.

Returns:

  • (Boolean)


162
163
164
165
166
167
168
169
# File 'lib/going_postal.rb', line 162

def postcode?(*args)
  string, country_code = get_args_for_format_postcode(args)
  if GoingPostal.not_required?(country_code)
    string.nil? || string.to_s.empty? ? "" : false
  else
    format_postcode(string, country_code) || false
  end
end