Handle International Addresses in Ruby
- Published
Handle International Addresses in Ruby
You're building an e-commerce site. Everything's going great until a customer from Japan tries to check out and your form is asking them for a "State" and "ZIP code."
Spoiler alert: Japan doesn't use either of those.
Or maybe you're printing shipping labels and discover that the USPS wants certain fields in ALL CAPS for automated sorting, but you have no idea which fields or why.
Welcome to the nightmare that is international address handling.
The problem nobody warns you about
Here's what makes addresses so deceptively difficult:
- The UK calls it a "postcode." Americans call it a "ZIP code." Canadians call it a "postal code."
- Japanese addresses go from largest to smallest (the complete opposite of Western addresses)
- Some countries don't have postal codes at all
- Ireland uses "County" but the US uses "State" and Canada uses "Province" (or sometimes "Territory")
- For automated mail sorting, you need to uppercase specific fields in specific countries
You can spend weeks researching postal systems across 200+ countries, or you can use a library that's already done the work.
That's where Addressing comes in.
What it does
Addressing is a Ruby gem that handles the messy reality of postal addresses worldwide:
- 250+ country definitions with proper translations (powered by CLDR data)
- 200+ address formats so you know which fields to show and in what order
- Subdivisions for 60 countries (states, provinces, prefectures, whatever they call them locally)
- Smart formatting in both HTML and plain text
- Built-in validation for Active Record models
Let's see it in action.
Your first address
Here's a simple example displaying an address:
ruby
address = Addressing::Address.new(country_code: "US",administrative_area: "CA",locality: "Mountain View",address_line1: "1600 Amphitheatre Parkway",given_name: "Sundar",family_name: "Pichai")formatter = Addressing::DefaultFormatter.newputs formatter.format(address)
This outputs properly formatted HTML with fields in the right order for the US, complete with semantic CSS classes. The country name is automatically localized.
No guessing. No hardcoding. Just correct addresses.
Real-world examples
Building a checkout form that works everywhere
Different countries need different fields. Nobody in Japan needs a "State" dropdown, but they absolutely need a "Prefecture" field:
ruby
# Get the address format for Japanformat = Addressing::AddressFormat.get('JP')# Build your form dynamicallyformat.used_fields.each do |field|puts "#{format.label_for(field)}: [input field]"end
Your Japanese customers see the fields they expect. Your UK customers don't see irrelevant fields. Simple.
Rails validation
Your model needs to accept addresses from anywhere:
ruby
class Order < ApplicationRecordvalidates_address_formatend
Done. Postal codes get validated against country-specific patterns. Required fields get enforced. Customers can actually complete checkout.
Printing shipping labels
You're printing labels for international shipments. Some countries require specific fields in ALL CAPS for automated sorting:
ruby
address = Addressing::Address.new(country_code: "US",administrative_area: "CA",locality: "Mountain View",address_line1: "1098 Alta Ave")formatter = Addressing::PostalLabelFormatter.new(origin_country: "FR")puts formatter.format(address)# Output:# 1098 Alta Ave# MOUNTAIN VIEW, CA 94043# ÉTATS-UNIS - UNITED STATES
Notice what happened:
- City and state got uppercased (USPS requirement)
- Country name appears in both French and English (Universal Postal Union recommendation)
- Everything formatted for international mail from France
Zero manual formatting. Zero postal regulation research.
Country selectors in any language
Need a dropdown in the user's language?
ruby
# Get all countries in Japanesecountries = Addressing::Country.list('ja-JP')# => { "JP" => "日本", "US" => "アメリカ合衆国", ... }# Or get detailed infobrazil = Addressing::Country.get('BR')puts brazil.currency_code # "BRL"puts brazil.timezones # All timezones Brazil spans
French users see "États-Unis." Japanese users see "アメリカ合衆国." Automatic.
Cascading location dropdowns
Those forms where selecting a country shows states, then cities:
ruby
# Get all states in Brazilstates = Addressing::Subdivision.all(['BR'])# User selected Ceará? Get municipalitiesmunicipalities = Addressing::Subdivision.all(['BR', 'CE'])# Traverse the hierarchystates.each do |state|state.children.each do |municipality|puts "#{state.name} - #{municipality.name}"endend
The data is hierarchical and translated. You just wire it up.
Why this beats rolling your own
Packaged research. This builds on Google's Address Data Service and the CLDR project—years of work across every country. One bundle install
gets you all of it.
No surprises. You won't discover months into production that Singapore uses six-digit postal codes or that Russia uses Cyrillic addresses.
Stays current. Address formats change. Countries split. Subdivisions get renamed. The gem tracks CLDR updates automatically.
Battle-tested. This ports the PHP addressing library from CommerceGuys, already proven in major e-commerce platforms.
When to use this
E-commerce platforms where wrong addresses mean failed deliveries and lost money.
Booking systems needing accurate location data from international customers.
Multi-tenant SaaS where customers operate across different countries.
Shipping tools generating labels that comply with postal regulations worldwide.
Getting started
Check out Addressing on GitHub for installation and complete documentation.
Add it to your Gemfile, wire up the validators and formatters, and you're done. No more failed deliveries, no more checkout abandonment, no more becoming a postal regulation expert for every market.
Wrong addresses cost real money through failed shipments and frustrated customers. This gem packages up years of research into something you install once and forget about.
It's focused. It solves one problem really well. Sometimes that's exactly what you need.
Next time you're about to add a "State" field to an international form, remember: there's a better way.
Have you dealt with address format nightmares? I'd love to hear about your solutions!