require "geoip" require "ensure/encoding" module Geo end require "geo/instance" require "expectation" module Geo extend Instance # lookup the IP in the GeoLiteCity database on city level. def self.city(ip) # Use some global IP if we are running locally. if !ip || ip == "127.0.0.1" ip = "193.99.144.85" end if city = instance.city(ip) complete_city(city) end end private def self.adjust_encoding(rec) rec.inject({}) do |hsh, (key, value)| if value.is_a?(String) value = value.ensure_encoding('UTF-8', :external_encoding => [Encoding::ISO8859_1, Encoding::UTF_8], :invalid_characters => :transcode ) end hsh.update key => value end end def self.complete_city(city) city = city.to_hash city = adjust_encoding(city) parts = city.values_at :city_name, :region_name, :country_name city_name = parts.grep(/[a-zA-Z]/).join(", ") parts = city.values_at :continent_code, :country_code2, :region_name region_code = parts.grep(/[a-zA-Z]/).join(".") parts = city.values_at :continent_code, :country_code2 country_code = parts.grep(/[a-zA-Z]/).join(".") city.update name: city_name, region_code: region_code, country_code: country_code end public def self.cities(pattern=nil, &block) expect! pattern => [ nil, Regexp, String ] pattern = Regexp.compile("^" + Regexp.escape(pattern) + "$") if pattern.is_a?(String) ary = [] collect = block || ary.method(:push) instance.each do |rec| next if pattern && rec.city_name !~ pattern collect.call complete_city(rec) end block ? self : ary end private # quietly and silence_stream are taken from activesupport def self.quietly silence_stream(STDOUT) do silence_stream(STDERR) do yield end end end def self.silence_stream(stream) old_stream = stream.dup stream.reopen(RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ ? 'NUL:' : '/dev/null') stream.sync = true yield ensure stream.reopen(old_stream) end end