# Ruby Geocoding Tutorial ## OpenCage Geocoding API Ruby Tutorial Tutorial for using the OpenCage Geocoding API in Ruby - An API for reverse and forward geocoding using open geo data This is a tutorial for using the [OpenCage geocoding API](https://opencagedata.com/api) in Ruby. ### Topics covered in this tutorial - General Background - Agent skill - Ruby Gems - Reverse geocoding - Forward geocoding - Geocoding a list of places - Running in parallel - Further reading ### Background The code examples below will use your geocoding API key once you [log in](https://opencagedata.com/users/sign_in). #### Before we dive in to the tutorial 1. [Sign up](https://opencagedata.com/users/sign_up) for an OpenCage geocoding API key. 2. Play with the [demo page](https://opencagedata.com/demo), so that you see the actual response the API returns. 3. Browse the [API reference](https://opencagedata.com/api), so you understand the [optional parameters](https://opencagedata.com/api#optional-params), [best practices](https://opencagedata.com/api#bestpractices), [possible response codes](https://opencagedata.com/api#codes), and the [rate limiting](https://opencagedata.com/api#rate-limiting) on free trial accounts. Working with AI? We offer an [Agent Skill](https://github.com/OpenCageData/opencage-skills) to make it easy for AI to quickly learn about our geocoding API. ### Agent Skill / Working with AI Are you developing with AI? We offer [an Agent Skill](https://github.com/OpenCageData/opencage-skills/) that includes [a reference file specifically about developing code to access our API via Ruby](https://github.com/OpenCageData/opencage-skills/blob/master/skills/opencage-geocoding-api/references/ruby.md). ### Ruby gems for accessing the OpenCage Geocoding API There are three Ruby gems you can use: - opencage-geocoder - geokit - Alex Reisner's Rubygeocoder ### Install the Ruby gem [](https://github.com/OpenCageData/ruby-opencage-geocoder/actions) [](https://badge.fury.io/rb/opencage-geocoder) gem install opencage-geocoder [on GitHub](https://github.com/opencagedata/ruby-opencage-geocoder) Or in your Gemfile: source 'https://rubygems.org' gem 'opencage-geocoder' ### Convert latitude, longitude to an address (reverse geocoding) require 'opencage/geocoder' geocoder = OpenCage::Geocoder.new(api_key: 'YOUR-API-KEY') result = geocoder.reverse_geocode(51.5019951, -0.0698806) p result.address # "Reeds Wharf, 33 Mill Street, London SE15, United Kingdom" p result.confidence # 9 ### Address or place name to coordinates (forward geocoding) require 'opencage/geocoder' geocoder = OpenCage::Geocoder.new(api_key: 'YOUR-API-KEY') # no need to URI encode the query, the library takes care of it for us results = geocoder.geocode('82 Clerkenwell Road, London, UK') p results.first.coordinates # [51.52215, -0.10083] p results.first.lat # 51.52215 p results.first.lng # -0.10083 results = geocoder.geocode('Manchester') results.each { |res| p res.address } # "Manchester, England, United Kingdom" # "Manchester, New Hampshire, United States of America" # "Manchester, IA 52057, United States of America" # "Manchester, KY 40962, United States of America" # ... # We want a place in Canada and results in French results = geocoder.geocode('Manchester', countrycode: 'CA', language: 'fr') p results.first.address # "Manchester, NS, Canada" p results.first.components # { # "ISO_3166-1_alpha-2" => "CA", # "ISO_3166-1_alpha-3" => "CAN", # "ISO_3166-2" => ["CA-NS"], # "_category" => "place", # "_normalized_city" => "Manchester" # "_type" => "village", # "state" => "Nouvelle-Écosse", # Nova Scotia # "state_code" => "NS", # "continent" => "North America", # "country" => "Canada", # "country_code" => "ca", # "county" => "Guysborough District Municipality", # "village" => "Manchester" # } p results.first.annotations.dig('currency', 'name') # "Canadian Dollar" p results.first.annotations.dig('currency', 'iso_code') # "CAD" ### Bulk-geocode places This example geocodes each coordinate pair in a file in series. Fill a text file queries.txt with queries: 24.77701,121.02189 31.79261,35.21785 9.54828,44.07715 59.92903,30.32989 Then loop through the file: require 'opencage/geocoder' geocoder = OpenCage::Geocoder.new(api_key: 'YOUR-API-KEY') results = [] File.foreach('queries.txt') do |line| lat, lng = line.chomp.split(',') begin # Use Float() rather than #to_f because it will throw an ArgumentError if # there is an invalid line in the queries.txt file result = geocoder.reverse_geocode(Float(lat), Float(lng)) results.push(result) rescue ArgumentError, OpenCage::Error => error # Stop loop if there is an error puts 'Error: ' + error.message break end end results.each { |r| puts r.address } # 韓國館, 金山十一街, 金山里, Hsinchu 30082, Taiwan # David Hazan 11, NO Jerusalem, Israel # هرجيسا, Jameeco Weyn, Hargeisa, Somalia # Китайское бистро, Apraksin Yard, Михайловский проезд ... ### Running many parallel queries We created two example scripts: - [How to geocode with multithreading](https://github.com/OpenCageData/opencagedata-misc-docs/blob/master/code-samples/ruby-parallel-batch-geocoding.rb) — using Queue and Threads gems - [Geocode spreadsheet file in parallel](https://github.com/OpenCageData/ruby-opencage-geocoder/blob/master/examples/batch.rb) — using CSV and Async gems Before you start geocoding at high volume, please read our [guide to geocoding large datasets](https://opencagedata.com/guides/how-to-geocode-large-datasets) where we explain various strategies and points to consider. ### Install the Ruby gem gem install geocoder [geocoder on GitHub](https://github.com/alexreisner/geocoder) [rubygeocoder.com](http://www.rubygeocoder.com) Or in your Gemfile: source 'https://rubygems.org' gem 'geocoder' ### Geocode an address #!/usr/bin/env ruby require 'geocoder' Geocoder.configure(lookup: :opencagedata, api_key: "YOUR-API-KEY") results = Geocoder.search("57 Erb Street West Waterloo, ON, Canada N2L 6C2") result = results.first puts "#{result.latitude}, #{result.longitude}" # output is 43.463796, -80.52608 ### Geocode coordinates #!/usr/bin/env ruby require 'geocoder' Geocoder.configure(lookup: :opencagedata, api_key: "YOUR-API-KEY") results = Geocoder.search([43.463796, -80.52608], reverse_geocode: true) result = results.first puts result.address # output is "63 Erb Street West, Waterloo, ON N2L 1V4, Canada" ### Install the Ruby gem gem install geokit [geokit on GitHub](https://github.com/geokit/geokit) Or in your Gemfile: source 'https://rubygems.org' gem 'geokit' ### Geocode coordinates require 'geokit' Geokit::Geocoders::OpencageGeocoder.key = 'YOUR-API-KEY' Geokit::Geocoders::provider_order = [:opencage] result = Geokit::Geocoders::MultiGeocoder.geocode("51.2157153, 1.3903743") puts "#{result.provider}: #{result.full_address}" # Output is "opencage: Mill Road, South East, Kent, England, CT14 9BD, GB" ### Geocode an address #!/usr/bin/env ruby require 'geokit' Geokit::Geocoders::OpencageGeocoder.key = 'YOUR-API-KEY' Geokit::Geocoders::provider_order = [:opencage] result = Geokit::Geocoders::MultiGeocoder.geocode("900 Sycamore Drive") puts "#{result.provider}: #{result.latitude}, #{result.longitude}" ### Further Reading - [OpenCage geocoding API Reference](https://opencagedata.com/api) - [Comparing geocoding services](https://opencagedata.com/guides/how-to-compare-and-test-geocoding-services) - [Cleaning / formatting your forward geocoding query](https://opencagedata.com/guides/how-to-format-your-geocoding-query) - [Geocoding more quickly](https://opencagedata.com/guides/how-to-geocode-more-quickly) - [Geocoding large datasets](https://opencagedata.com/guides/how-to-geocode-large-datasets) - [Geocoding and preserving privacy](https://opencagedata.com/guides/how-to-preserve-privacy-by-showing-only-an-imprecise-location) - [Sample address and coordinate lists for testing](https://opencagedata.com/tools/address-lists)