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