Last active
January 13, 2021 02:45
-
-
Save dpneumo/faf5883486cbb2e5994eb71306542623 to your computer and use it in GitHub Desktop.
Geocode an address hash with Google geocode api
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
I needed a tool to add latitude and longitude to seeds.rb in a Rails application. | |
geocoder.rb uses the Google geocode api. An apikey is required. For limited use it is free. The apikey should be protected from prying eyes. (encryption, .gitignore, ...) | |
Geocoder#geocode takes an address string in canonical form ( "#{number} #{street} #{city} #{state}" ) as input. It returns latitude and longitude as a hash: { lat: 30.0000, lng: -90.000 } | |
seed_geocoder.rb extracts the address string from seeds.rb, requests the geocode hash from the Geocoder obj and writes the newseeds.rb file. | |
The newseeds file does need some minor additional work to make it a functional seeds.rb. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class CanonicalAddress | |
def initialize( city: 'Arlington', state: 'TX') | |
@city = city | |
@state = state | |
end | |
def strng(addr_hash) | |
number = addr_hash.fetch('number') | |
street = addr_hash.fetch('street') | |
city = addr_hash.fetch('city', @city) | |
state = addr_hash.fetch('state', @state) | |
"#{number} #{street} #{city} #{state}" | |
end | |
def hsh(addr_hash) | |
addr_hash.merge({city: @city, state: state}) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'json' | |
require 'httparty' | |
class Geocoder | |
include HTTParty | |
URL_GC = "https://maps.googleapis.com/maps/api/geocode/" | |
attr_reader :url, :fmt, :keyfile | |
def initialize( url: URL_GC, fmt: 'json', keyfile: 'apikey.txt') | |
@url = url | |
@fmt = fmt | |
@keyfile = keyfile | |
end | |
def geocode(address) | |
request = req(address) | |
response = HTTParty.get(request) | |
extract_coordinates(response) | |
end | |
private | |
def req(address) | |
URL_GC+fmt+"?address=#{ address }&key= "#{ apikey }" | |
end | |
def extract_coordinates(response) | |
JSON.parse(response.body)["results"].first["geometry"]["location"] | |
end | |
def apikey | |
File.open(keyfile) {|f| key = f.read } | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[ | |
{"number"=>100, "street"=>"Howler Dr", "lat"=>31.0000000, "lng"=>-97.0000000}, | |
{"number"=>202, "street"=>"Johnson Ave", city: "Fort Worth", "lat"=>32.0000000, "lng"=>-97.0000000}, | |
{"number"=>303, "street"=>"Main St", city: "Dallas", state: "TX", "lat"=>32.0000000, "lng"=>-97.0000000}, | |
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require_relative 'seed_geocoder' | |
sg = SeedGeocoder.new( app: '../wwna_roster', | |
matchr: %r{number: 6004} ) | |
sg.geocode_seeds |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'yaml' | |
require_relative 'geocoder' | |
require_relative 'canonical_address' | |
class SeedGeocoder | |
attr_reader :c_addr, :geocoder | |
def initialize( app: '../my_app', | |
src: 'db/seeds.rb', | |
dest: 'db/newseeds.rb', | |
matchr: %r{number:}, | |
geocoder: Geocoder ) | |
@app = app | |
@src = src | |
@dest = dest | |
@c_addr = CanonicalAddress.new | |
@geocoder = geocoder.new | |
end | |
def geocode_seeds | |
write(geocoded_seeds) | |
end | |
private | |
def write(seeds) | |
return unless seeds | |
File.open(dest, 'w') do |f| | |
f.puts "[\n" | |
seeds.each do |seed| | |
f.puts " #{seed.to_s},\n" | |
end | |
f.puts "]\n" | |
end | |
end | |
def geocoded_seeds | |
File.foreach(src).map do |line| | |
next unless matchr =~ line | |
addr = YAML.load(line) | |
addr.merge geocoder.geocode(canonical addr) | |
end.compact | |
end | |
def canonical(addr_hash) | |
c_addr.strng(addr_hash) | |
end | |
def src | |
@app + '/' + @src | |
end | |
def dest | |
@app + '/' + @dest | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This file should contain all the record creation needed to seed the database with its default values. | |
# The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup). | |
# | |
# Examples: | |
# | |
# movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) | |
# Character.create(name: 'Luke', movie: movies.first) | |
House.create([ | |
{ number: 100, street: 'Howler Dr' }, | |
{ number: 202, street: 'Johnson Ave', city: 'Fort Worth' }, | |
{ number: 303, street: 'Main St', city: 'Dallas', state: 'TX' } | |
]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment