simple_geolocation 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +7 -0
- data/Gemfile +4 -0
- data/Rakefile +2 -0
- data/lib/simple_geolocation.rb +7 -0
- data/lib/simple_geolocation/geocoder.rb +39 -0
- data/lib/simple_geolocation/geoworkers/base.rb +27 -0
- data/lib/simple_geolocation/geoworkers/geoip/data/GeoLiteCity.dat +0 -0
- data/lib/simple_geolocation/geoworkers/geoip/geoip.rb +34 -0
- data/lib/simple_geolocation/geoworkers/geokit/geokit.rb +36 -0
- data/lib/simple_geolocation/geoworkers/geoworkers.rb +8 -0
- data/lib/simple_geolocation/geoworkers/geozip/geozip.rb +32 -0
- data/lib/simple_geolocation/location.rb +23 -0
- data/lib/simple_geolocation/utils/remove_accents.rb +61 -0
- data/lib/simple_geolocation/version.rb +3 -0
- data/simple_geolocation.gemspec +31 -0
- data/spec/simple_geolocation_spec.rb +63 -0
- metadata +126 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
require 'active_support/core_ext'
|
2
|
+
require File.join(File.dirname(__FILE__), 'simple_geolocation/utils/remove_accents')
|
3
|
+
module SimpleGeolocation
|
4
|
+
autoload :Geocoder , 'simple_geolocation/geocoder'
|
5
|
+
autoload :Location , 'simple_geolocation/location'
|
6
|
+
autoload :Geoworkers , 'simple_geolocation/geoworkers/geoworkers'
|
7
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module SimpleGeolocation
|
2
|
+
class Geocoder
|
3
|
+
|
4
|
+
attr_reader :success, :raw_location, :location
|
5
|
+
alias :success? :success
|
6
|
+
|
7
|
+
delegate *(Location::ATTRIBUTES + [:completeness]), :to => :location
|
8
|
+
|
9
|
+
def initialize(raw_location)
|
10
|
+
@raw_location = raw_location
|
11
|
+
end
|
12
|
+
|
13
|
+
def ip?
|
14
|
+
!!/^(\d+\.){3}\d+$/.match(@raw_location)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Only brazilian zipcode is supported.
|
18
|
+
def zip?
|
19
|
+
return false if ip?
|
20
|
+
number = @raw_location.to_s.gsub(/(\.|\D|\-|\s)/, '')
|
21
|
+
number.size == 8
|
22
|
+
end
|
23
|
+
|
24
|
+
def address?
|
25
|
+
!ip? && !zip?
|
26
|
+
end
|
27
|
+
|
28
|
+
def geocode!
|
29
|
+
@geoworker = Geoworkers::Base.instantiate_geoworker_based_on(self)
|
30
|
+
@geoworker.process!
|
31
|
+
@location = @geoworker.location
|
32
|
+
end
|
33
|
+
|
34
|
+
def success!
|
35
|
+
@success = true
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module SimpleGeolocation
|
2
|
+
module Geoworkers
|
3
|
+
class Base
|
4
|
+
|
5
|
+
attr_reader :location, :geocoder, :success
|
6
|
+
alias :success? :success
|
7
|
+
|
8
|
+
def initialize(geocoder)
|
9
|
+
@geocoder = geocoder
|
10
|
+
end
|
11
|
+
|
12
|
+
def process!
|
13
|
+
raise NotImplementedError
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.instantiate_geoworker_based_on(geocoder)
|
17
|
+
if geocoder.ip?
|
18
|
+
GeoIP.new(geocoder)
|
19
|
+
elsif geocoder.zip?
|
20
|
+
Geozip.new(geocoder)
|
21
|
+
else
|
22
|
+
Geokit.new(geocoder)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
Binary file
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'geoip'
|
2
|
+
module SimpleGeolocation
|
3
|
+
module Geoworkers
|
4
|
+
class GeoIP < Base
|
5
|
+
|
6
|
+
def process!
|
7
|
+
get_location!
|
8
|
+
geocoder.success! if success?
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def ip_geocoder
|
14
|
+
@ip_geocoder ||= ::GeoIP.new(File.join(File.dirname(__FILE__), 'data', 'GeoLiteCity.dat'))
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_location!
|
18
|
+
result = ip_geocoder.city(geocoder.raw_location)
|
19
|
+
if @success = result && result.city_name.present? && result.region_name.present?
|
20
|
+
@location = Location.new(
|
21
|
+
:lat => result.latitude,
|
22
|
+
:lng => result.longitude,
|
23
|
+
:city => result.city_name,
|
24
|
+
:state => result.region_name,
|
25
|
+
:provider => "geoip"
|
26
|
+
)
|
27
|
+
else
|
28
|
+
Geokit.new(geocoder).process!
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'geokit'
|
2
|
+
module SimpleGeolocation
|
3
|
+
module Geoworkers
|
4
|
+
class Geokit < Base
|
5
|
+
|
6
|
+
def process!
|
7
|
+
get_location!
|
8
|
+
geocoder.success! if success?
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def multi_geocoder
|
14
|
+
@multi_geocoder ||= ::Geokit::Geocoders::MultiGeocoder
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_location!
|
18
|
+
result = multi_geocoder.geocode(geocoder.raw_location.removeaccents)
|
19
|
+
if @success = result.success
|
20
|
+
@location = Location.new(
|
21
|
+
:lat => result.lat,
|
22
|
+
:lng => result.lng,
|
23
|
+
:city => result.city,
|
24
|
+
:state => result.state,
|
25
|
+
:street => result.street_name,
|
26
|
+
:number => result.street_number,
|
27
|
+
:zip => result.zip,
|
28
|
+
:district => result.district,
|
29
|
+
:provider => result.provider
|
30
|
+
)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
module SimpleGeolocation
|
2
|
+
module Geoworkers
|
3
|
+
autoload :Base, 'simple_geolocation/geoworkers/base'
|
4
|
+
autoload :GeoIP, 'simple_geolocation/geoworkers/geoip/geoip'
|
5
|
+
autoload :Geokit, 'simple_geolocation/geoworkers/geokit/geokit'
|
6
|
+
autoload :Geozip, 'simple_geolocation/geoworkers/geozip/geozip'
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'brcep'
|
2
|
+
module SimpleGeolocation
|
3
|
+
module Geoworkers
|
4
|
+
class Geozip < Base
|
5
|
+
|
6
|
+
def process!
|
7
|
+
get_location!
|
8
|
+
geocoder.success! if success?
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def get_location!
|
14
|
+
begin
|
15
|
+
result = ::BuscaEndereco.por_cep(geocoder.raw_location)
|
16
|
+
if @success = result && result.present?
|
17
|
+
street = "#{result.first} #{result.second}"
|
18
|
+
other_location_data = result[2..-1].join(', ')
|
19
|
+
new_raw_location = "#{street}, #{other_location_data}"
|
20
|
+
geokit = Geokit.new(Geocoder.new(new_raw_location))
|
21
|
+
geokit.process!
|
22
|
+
@success = geokit.success?
|
23
|
+
@location = geokit.location
|
24
|
+
end
|
25
|
+
rescue
|
26
|
+
@success = false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SimpleGeolocation
|
2
|
+
class Location
|
3
|
+
ATTRIBUTES = [:lat, :lng, :city, :state, :provider, :zip, :street, :district, :number]
|
4
|
+
attr_accessor *ATTRIBUTES
|
5
|
+
|
6
|
+
def initialize(attributes = {})
|
7
|
+
unknown_attributes = attributes.keys.reject { |k| ATTRIBUTES.include?(k) }
|
8
|
+
raise ArgumentError, "Unknown parameters: #{unknown_attributes.join(', ')}" unless unknown_attributes.empty?
|
9
|
+
attributes.each do |k, v|
|
10
|
+
send("#{k}=", v)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def completeness(attributes = ATTRIBUTES)
|
15
|
+
total = attributes.size
|
16
|
+
used = attributes.reject {|attr| send(attr).blank? }.size
|
17
|
+
return 100 if used >= total
|
18
|
+
(used.to_f / total.to_f * 100.0).to_i
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,61 @@
|
|
1
|
+
class String
|
2
|
+
# The extended characters map used by removeaccents. The accented characters
|
3
|
+
# are coded here using their numerical equivalent to sidestep encoding issues.
|
4
|
+
# These correspond to ISO-8859-1 encoding.
|
5
|
+
ACCENTS_MAPPING = {
|
6
|
+
'E' => [200,201,202,203],
|
7
|
+
'e' => [232,233,234,235],
|
8
|
+
'A' => [192,193,194,195,196,197],
|
9
|
+
'a' => [224,225,226,227,228,229,230],
|
10
|
+
'C' => [199],
|
11
|
+
'c' => [231],
|
12
|
+
'O' => [210,211,212,213,214,216],
|
13
|
+
'o' => [242,243,244,245,246,248],
|
14
|
+
'I' => [204,205,206,207],
|
15
|
+
'i' => [236,237,238,239],
|
16
|
+
'U' => [217,218,219,220],
|
17
|
+
'u' => [249,250,251,252],
|
18
|
+
'N' => [209],
|
19
|
+
'n' => [241],
|
20
|
+
'Y' => [221],
|
21
|
+
'y' => [253,255],
|
22
|
+
'AE' => [306],
|
23
|
+
'ae' => [346],
|
24
|
+
'OE' => [188],
|
25
|
+
'oe' => [189]
|
26
|
+
}
|
27
|
+
|
28
|
+
|
29
|
+
# Remove the accents from the string. Uses String::ACCENTS_MAPPING as the source map.
|
30
|
+
def removeaccents
|
31
|
+
str = String.new(self)
|
32
|
+
String::ACCENTS_MAPPING.each {|letter,accents|
|
33
|
+
packed = accents.pack('U*')
|
34
|
+
rxp = Regexp.new("[#{packed}]", nil)
|
35
|
+
str.gsub!(rxp, letter)
|
36
|
+
}
|
37
|
+
|
38
|
+
str
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
# Convert a string to a format suitable for a URL without ever using escaped characters.
|
43
|
+
# It calls strip, removeaccents, downcase (optional) then removes the spaces (optional)
|
44
|
+
# and finally removes any characters matching the default regexp (/[^-_A-Za-z0-9]/).
|
45
|
+
#
|
46
|
+
# Options
|
47
|
+
#
|
48
|
+
# * :downcase => call downcase on the string (defaults to true)
|
49
|
+
# * :convert_spaces => Convert space to underscore (defaults to false)
|
50
|
+
# * :regexp => The regexp matching characters that will be converting to an empty string (defaults to /[^-_A-Za-z0-9]/)
|
51
|
+
def urlize(options = {})
|
52
|
+
options[:downcase] ||= true
|
53
|
+
options[:convert_spaces] ||= false
|
54
|
+
options[:regexp] ||= /[^-_A-Za-z0-9]/
|
55
|
+
|
56
|
+
str = self.strip.removeaccents
|
57
|
+
str.downcase! if options[:downcase]
|
58
|
+
str.gsub!(/\ /,'_') if options[:convert_spaces]
|
59
|
+
str.gsub(options[:regexp], '')
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "simple_geolocation/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "simple_geolocation"
|
7
|
+
s.version = SimpleGeolocation::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Esdras Mayrink"]
|
10
|
+
s.email = ["falecom@oesdras.com.br"]
|
11
|
+
s.homepage = "http://oesdras.com.br"
|
12
|
+
s.summary = %q{A gem that fetch locations based on IP, ZIP and ordinary address through several existing geolocation gems.}
|
13
|
+
s.description = %q{
|
14
|
+
This gem is used with geolocation in mind, meaning that the main goal is to get a latitude and longitude, but it will return additional data if
|
15
|
+
available. With this gem you can pass an IP number or an ZIP number or an ordinary address and it will try to get as many information as possible
|
16
|
+
about the given argument.
|
17
|
+
}
|
18
|
+
|
19
|
+
s.add_development_dependency "rspec"
|
20
|
+
s.add_dependency "geokit"
|
21
|
+
s.add_dependency "geoip"
|
22
|
+
s.add_dependency "activesupport"
|
23
|
+
s.add_dependency "brcep"
|
24
|
+
|
25
|
+
s.rubyforge_project = "simple_geolocation"
|
26
|
+
|
27
|
+
s.files = `git ls-files`.split("\n")
|
28
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
29
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
30
|
+
s.require_paths = ["lib"]
|
31
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'simple_geolocation')
|
3
|
+
|
4
|
+
describe SimpleGeolocation do
|
5
|
+
|
6
|
+
|
7
|
+
it 'should identify if the given location is an ip' do
|
8
|
+
@geo = SimpleGeolocation::Geocoder.new("74.125.113.105")
|
9
|
+
@geo.ip?.should be_true
|
10
|
+
@geo.zip?.should be_false
|
11
|
+
@geo.address?.should be_false
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should identify if the given location is a zip' do
|
15
|
+
@geo = SimpleGeolocation::Geocoder.new("89237-440")
|
16
|
+
@geo.ip?.should be_false
|
17
|
+
@geo.zip?.should be_true
|
18
|
+
@geo.address?.should be_false
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should identify if the given location is an address' do
|
22
|
+
@geo = SimpleGeolocation::Geocoder.new("Joinville - SC")
|
23
|
+
@geo.ip?.should be_false
|
24
|
+
@geo.address?.should be_true
|
25
|
+
@geo.zip?.should be_false
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should return the location of an user's based on IP" do
|
29
|
+
@geo = SimpleGeolocation::Geocoder.new("74.125.113.105")
|
30
|
+
@geo.ip?.should be_true
|
31
|
+
@geo.geocode!
|
32
|
+
@geo.success?.should be_true
|
33
|
+
@geo.lat.should == 37.41919999999999
|
34
|
+
@geo.lng.should == -122.0574
|
35
|
+
@geo.completeness.should == 55
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should return the location of an ordinary address" do
|
39
|
+
@geo = SimpleGeolocation::Geocoder.new("Rua do Principe, 199, Joinville, SC")
|
40
|
+
@geo.address?.should be_true
|
41
|
+
@geo.geocode!
|
42
|
+
@geo.success?.should be_true
|
43
|
+
@geo.lat.should == -26.30101
|
44
|
+
@geo.lng.should == -48.8452974
|
45
|
+
@geo.completeness.should == 88
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should return the location of a brazilian zipcode (CEP)" do
|
49
|
+
@geo = SimpleGeolocation::Geocoder.new("22640100")
|
50
|
+
@geo.zip?.should be_true
|
51
|
+
@geo.geocode!
|
52
|
+
@geo.success?.should be_true
|
53
|
+
@geo.street.should == "Av. Das Américas"
|
54
|
+
@geo.district.should == "Barra da Tijuca"
|
55
|
+
@geo.state.should == "RJ"
|
56
|
+
@geo.city.should == "Rio De Janeiro"
|
57
|
+
@geo.zip.should == "22640-100"
|
58
|
+
@geo.lat.should == -23.0032808
|
59
|
+
@geo.lng.should == -43.3230295
|
60
|
+
@geo.completeness.should == 88
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
metadata
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: simple_geolocation
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Esdras Mayrink
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-04-04 00:00:00 -03:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: rspec
|
18
|
+
prerelease: false
|
19
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: "0"
|
25
|
+
type: :development
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: geokit
|
29
|
+
prerelease: false
|
30
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
31
|
+
none: false
|
32
|
+
requirements:
|
33
|
+
- - ">="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: "0"
|
36
|
+
type: :runtime
|
37
|
+
version_requirements: *id002
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: geoip
|
40
|
+
prerelease: false
|
41
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: "0"
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id003
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: activesupport
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: "0"
|
58
|
+
type: :runtime
|
59
|
+
version_requirements: *id004
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: brcep
|
62
|
+
prerelease: false
|
63
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: "0"
|
69
|
+
type: :runtime
|
70
|
+
version_requirements: *id005
|
71
|
+
description: "\n This gem is used with geolocation in mind, meaning that the main goal is to get a latitude and longitude, but it will return additional data if\n available. With this gem you can pass an IP number or an ZIP number or an ordinary address and it will try to get as many information as possible\n about the given argument.\n "
|
72
|
+
email:
|
73
|
+
- falecom@oesdras.com.br
|
74
|
+
executables: []
|
75
|
+
|
76
|
+
extensions: []
|
77
|
+
|
78
|
+
extra_rdoc_files: []
|
79
|
+
|
80
|
+
files:
|
81
|
+
- .gitignore
|
82
|
+
- Gemfile
|
83
|
+
- Rakefile
|
84
|
+
- lib/simple_geolocation.rb
|
85
|
+
- lib/simple_geolocation/geocoder.rb
|
86
|
+
- lib/simple_geolocation/geoworkers/base.rb
|
87
|
+
- lib/simple_geolocation/geoworkers/geoip/data/GeoLiteCity.dat
|
88
|
+
- lib/simple_geolocation/geoworkers/geoip/geoip.rb
|
89
|
+
- lib/simple_geolocation/geoworkers/geokit/geokit.rb
|
90
|
+
- lib/simple_geolocation/geoworkers/geoworkers.rb
|
91
|
+
- lib/simple_geolocation/geoworkers/geozip/geozip.rb
|
92
|
+
- lib/simple_geolocation/location.rb
|
93
|
+
- lib/simple_geolocation/utils/remove_accents.rb
|
94
|
+
- lib/simple_geolocation/version.rb
|
95
|
+
- simple_geolocation.gemspec
|
96
|
+
- spec/simple_geolocation_spec.rb
|
97
|
+
has_rdoc: true
|
98
|
+
homepage: http://oesdras.com.br
|
99
|
+
licenses: []
|
100
|
+
|
101
|
+
post_install_message:
|
102
|
+
rdoc_options: []
|
103
|
+
|
104
|
+
require_paths:
|
105
|
+
- lib
|
106
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: "0"
|
112
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: "0"
|
118
|
+
requirements: []
|
119
|
+
|
120
|
+
rubyforge_project: simple_geolocation
|
121
|
+
rubygems_version: 1.5.2
|
122
|
+
signing_key:
|
123
|
+
specification_version: 3
|
124
|
+
summary: A gem that fetch locations based on IP, ZIP and ordinary address through several existing geolocation gems.
|
125
|
+
test_files:
|
126
|
+
- spec/simple_geolocation_spec.rb
|