151 lines
6.7 KiB
Ruby
151 lines
6.7 KiB
Ruby
module JamRuby
|
|
class GeoIpLocations < ActiveRecord::Base
|
|
|
|
self.table_name = 'geoiplocations'
|
|
CITIES_TABLE = 'cities'
|
|
REGIONS_TABLE = 'regions'
|
|
COUNTRIES_TABLE = 'countries'
|
|
|
|
def self.lookup(locid)
|
|
self.where(locid: locid)
|
|
.limit(1)
|
|
.first
|
|
end
|
|
|
|
def self.createx(locid, countrycode, region, city, postalcode, latitude, longitude, metrocode, areacode)
|
|
c = connection.raw_connection
|
|
c.exec_params("insert into #{self.table_name} (locid, countrycode, region, city, postalcode, latitude, longitude, metrocode, areacode, geog) values($1, $2, $3, $4, $5, $6, $7, $8, $9, ST_SetSRID(ST_MakePoint($7, $6), 4326)::geography)",
|
|
[locid, countrycode, region, city, postalcode, latitude, longitude, metrocode, areacode])
|
|
end
|
|
|
|
def self.i(s)
|
|
return 'NULL' if s.nil? or s.blank?
|
|
return s.to_i
|
|
end
|
|
|
|
def self.import_from_max_mind(file)
|
|
|
|
# File Geo-134
|
|
# Format:
|
|
# locId,country,region,city,postalCode,latitude,longitude,metroCode,areaCode
|
|
|
|
self.transaction do
|
|
self.delete_all
|
|
File.open(file, 'r:ISO-8859-1') do |io|
|
|
s = io.gets.strip # eat the copyright line. gah, why do they have that in their file??
|
|
unless s.eql? 'Copyright (c) 2012 MaxMind LLC. All Rights Reserved.'
|
|
puts s
|
|
puts 'Copyright (c) 2012 MaxMind LLC. All Rights Reserved.'
|
|
raise 'file does not start with expected copyright (line 1): Copyright (c) 2012 MaxMind LLC. All Rights Reserved.'
|
|
end
|
|
|
|
s = io.gets.strip # eat the headers line
|
|
unless s.eql? 'locId,country,region,city,postalCode,latitude,longitude,metroCode,areaCode'
|
|
puts s
|
|
puts 'locId,country,region,city,postalCode,latitude,longitude,metroCode,areaCode'
|
|
raise 'file does not start with expected header (line 2): locId,country,region,city,postalCode,latitude,longitude,metroCode,areaCode'
|
|
end
|
|
|
|
saved_level = ActiveRecord::Base.logger ? ActiveRecord::Base.logger.level : 0
|
|
count = 0
|
|
|
|
stmt = "INSERT INTO #{self.table_name} (locid, countrycode, region, city, postalcode, latitude, longitude, metrocode, areacode) VALUES"
|
|
|
|
vals = ''
|
|
sep = ''
|
|
i = 0
|
|
n = 20
|
|
|
|
csv = ::CSV.new(io, {encoding: 'ISO-8859-1', headers: false})
|
|
csv.each do |row|
|
|
raise "file does not have expected number of columns (9): #{row.length}" unless row.length == 9
|
|
|
|
locid = row[0]
|
|
countrycode = row[1]
|
|
region = row[2]
|
|
city = row[3]
|
|
postalcode = row[4]
|
|
latitude = row[5]
|
|
longitude = row[6]
|
|
metrocode = row[7]
|
|
areacode = row[8]
|
|
|
|
vals = vals+sep+"(#{locid}, '#{countrycode}', '#{region}', #{MaxMindIsp.quote_value(city)}, '#{postalcode}', #{latitude}, #{longitude}, #{i(metrocode)}, '#{areacode}')"
|
|
sep = ','
|
|
i += 1
|
|
|
|
if count == 0 or i >= n then
|
|
self.connection.execute stmt+vals
|
|
count += i
|
|
vals = ''
|
|
sep = ''
|
|
i = 0
|
|
|
|
if ActiveRecord::Base.logger and ActiveRecord::Base.logger.level > 1 then
|
|
ActiveRecord::Base.logger.debug "... logging inserts into #{self.table_name} suspended ..."
|
|
ActiveRecord::Base.logger.level = 1
|
|
end
|
|
|
|
if ActiveRecord::Base.logger and count%10000 < n then
|
|
ActiveRecord::Base.logger.level = saved_level
|
|
ActiveRecord::Base.logger.debug "... inserted #{count} into #{self.table_name} ..."
|
|
ActiveRecord::Base.logger.level = 1
|
|
end
|
|
end
|
|
end
|
|
|
|
if i > 0 then
|
|
self.connection.execute stmt+vals
|
|
count += i
|
|
end
|
|
|
|
if ActiveRecord::Base.logger then
|
|
ActiveRecord::Base.logger.level = saved_level
|
|
ActiveRecord::Base.logger.debug "loaded #{count} records into #{self.table_name}"
|
|
end
|
|
|
|
sts = self.connection.execute "ALTER TABLE #{self.table_name} DROP COLUMN geog;"
|
|
ActiveRecord::Base.logger.debug "DROP COLUMN geog returned sts #{sts.cmd_status}" if ActiveRecord::Base.logger
|
|
# sts.check [we don't care]
|
|
|
|
sts = self.connection.execute "ALTER TABLE #{self.table_name} ADD COLUMN geog geography(point, 4326);"
|
|
ActiveRecord::Base.logger.debug "ADD COLUMN geog returned sts #{sts.cmd_status}" if ActiveRecord::Base.logger
|
|
sts.check
|
|
|
|
sts = self.connection.execute "UPDATE #{self.table_name} SET geog = ST_SetSRID(ST_MakePoint(longitude, latitude), 4326)::geography;"
|
|
ActiveRecord::Base.logger.debug "SET geog returned sts #{sts.cmd_tuples}" if ActiveRecord::Base.logger
|
|
sts.check
|
|
|
|
sts = self.connection.execute "CREATE INDEX #{self.table_name}_geog_gix ON #{self.table_name} USING GIST (geog);"
|
|
ActiveRecord::Base.logger.debug "CREATE INDEX #{self.table_name}_geog_gix returned sts #{sts.cmd_status}" if ActiveRecord::Base.logger
|
|
sts.check
|
|
|
|
sts = self.connection.execute "DELETE FROM #{CITIES_TABLE};"
|
|
ActiveRecord::Base.logger.debug "DELETE FROM #{CITIES_TABLE} returned sts #{sts.cmd_status}" if ActiveRecord::Base.logger
|
|
sts.check
|
|
|
|
sts = self.connection.execute "INSERT INTO #{CITIES_TABLE} (city, region, countrycode) SELECT DISTINCT city, region, countrycode FROM #{self.table_name} WHERE length(city) > 0 AND length(countrycode) > 0;"
|
|
ActiveRecord::Base.logger.debug "INSERT INTO #{CITIES_TABLE} returned sts #{sts.cmd_status}" if ActiveRecord::Base.logger
|
|
sts.check
|
|
|
|
sts = self.connection.execute "DELETE FROM #{REGIONS_TABLE};"
|
|
ActiveRecord::Base.logger.debug "DELETE FROM #{REGIONS_TABLE} returned sts #{sts.cmd_status}" if ActiveRecord::Base.logger
|
|
sts.check
|
|
|
|
sts = self.connection.execute "INSERT INTO #{REGIONS_TABLE} (region, regionname, countrycode) SELECT DISTINCT region, region, countrycode FROM #{CITIES_TABLE};"
|
|
ActiveRecord::Base.logger.debug "INSERT INTO #{REGIONS_TABLE} returned sts #{sts.cmd_status}" if ActiveRecord::Base.logger
|
|
sts.check
|
|
|
|
sts = self.connection.execute "DELETE FROM #{COUNTRIES_TABLE};"
|
|
ActiveRecord::Base.logger.debug "DELETE FROM #{COUNTRIES_TABLE} returned sts #{sts.cmd_status}" if ActiveRecord::Base.logger
|
|
sts.check
|
|
|
|
sts = self.connection.execute "INSERT INTO #{COUNTRIES_TABLE} (countrycode, countryname) SELECT DISTINCT countrycode, countrycode FROM #{REGIONS_TABLE};"
|
|
ActiveRecord::Base.logger.debug "INSERT INTO #{COUNTRIES_TABLE} returned sts #{sts.cmd_status}" if ActiveRecord::Base.logger
|
|
sts.check
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|