jam-cloud/ruby/lib/jam_ruby/models/max_mind_geo.rb

128 lines
4.5 KiB
Ruby

require 'csv'
module JamRuby
class MaxMindGeo < ActiveRecord::Base
self.table_name = 'max_mind_geo'
def self.ip_lookup(ip_addy)
addr = MaxMindIsp.ip_address_to_int(ip_addy)
self.where(["ip_start <= ? AND ? <= ip_end", addr, addr])
.limit(1)
.first
end
def self.import_from_max_mind(file)
# File Geo-139
# Format:
# startIpNum,endIpNum,country,region,city,postalCode,latitude,longitude,dmaCode,areaCode
MaxMindGeo.transaction do
MaxMindGeo.delete_all
File.open(file, 'r:ISO-8859-1') do |io|
s = io.gets.strip # eat the headers line
unless s.eql? 'startIpNum,endIpNum,country,region,city,postalCode,latitude,longitude,dmaCode,areaCode'
puts s
puts 'startIpNum,endIpNum,country,region,city,postalCode,latitude,longitude,dmaCode,areaCode'
raise 'file does not start with expected header (line 1): startIpNum,endIpNum,country,region,city,postalCode,latitude,longitude,dmaCode,areaCode'
end
saved_level = ActiveRecord::Base.logger ? ActiveRecord::Base.logger.level : 0
count = 0
stmt = "insert into #{MaxMindGeo.table_name} (country,region,city,lat,lng,ip_start,ip_end) values"
vals = ''
sep = ''
i = 0
n = 20 # going from 20 to 40 only changed things a little bit
csv = ::CSV.new(io, {encoding: 'ISO-8859-1', headers: false})
csv.each do |row|
raise "file does not have expected number of columns (10): #{row.length}" unless row.length == 10
ip_start = MaxMindIsp.ip_address_to_int(MaxMindIsp.strip_quotes(row[0]))
ip_end = MaxMindIsp.ip_address_to_int(MaxMindIsp.strip_quotes(row[1]))
country = row[2]
region = row[3]
city = row[4]
#postalcode = row[5]
lat = row[6]
lng = row[7]
#dmacode = row[8]
#areacode = row[9]
vals = vals+sep+"(#{quote_value(country)},#{quote_value(region)},#{quote_value(city)},#{lat},#{lng},#{ip_start},#{ip_end})"
sep = ','
i += 1
if count == 0 or i >= n then
MaxMindGeo.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 #{MaxMindGeo.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 #{MaxMindGeo.table_name} ..."
ActiveRecord::Base.logger.level = 1
end
end
end
if i > 0 then
MaxMindGeo.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 #{MaxMindGeo.table_name}"
end
end
end
User.find_each { |usr| usr.update_lat_lng }
Band.find_each { |bnd| bnd.update_lat_lng }
end
def self.where_latlng(relation, params, current_user=nil)
if 0 < (distance = params[:distance].to_i)
latlng = []
if location_city = params[:city]
if geo = self.where(:city => params[:city]).limit(1).first
latlng = [geo.lat, geo.lng]
end
elsif current_user
if current_user.lat.nil? || current_user.lng.nil?
if params[:remote_ip] && (geo = self.ip_lookup(params[:remote_ip]))
geo.lat = nil if geo.lat = 0
geo.lng = nil if geo.lng = 0
latlng = [geo.lat, geo.lng] if geo.lat && geo.lng
end
else
latlng = [current_user.lat, current_user.lng]
end
elsif params[:remote_ip] && (geo = self.ip_lookup(params[:remote_ip]))
geo.lat = nil if geo.lat = 0
geo.lng = nil if geo.lng = 0
latlng = [geo.lat, geo.lng] if geo.lat && geo.lng
end
if latlng.present?
relation = relation.where(['lat IS NOT NULL AND lng IS NOT NULL'])
.within(distance, :origin => latlng)
end
end
relation
end
end
end