geocoder 1.2.6 → 1.6.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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +189 -1
- data/LICENSE +1 -1
- data/README.md +387 -755
- data/examples/autoexpire_cache_redis.rb +5 -3
- data/examples/reverse_geocode_job.rb +40 -0
- data/lib/generators/geocoder/config/templates/initializer.rb +17 -16
- data/lib/generators/geocoder/maxmind/geolite_city_generator.rb +2 -0
- data/lib/generators/geocoder/maxmind/geolite_country_generator.rb +2 -0
- data/lib/generators/geocoder/maxmind/templates/migration/geolite_city.rb +1 -1
- data/lib/generators/geocoder/maxmind/templates/migration/geolite_country.rb +1 -1
- data/lib/generators/geocoder/migration_version.rb +15 -0
- data/lib/geocoder/cache.rb +6 -2
- data/lib/geocoder/calculations.rb +30 -38
- data/lib/geocoder/cli.rb +2 -2
- data/lib/geocoder/configuration.rb +18 -5
- data/lib/geocoder/esri_token.rb +38 -0
- data/lib/geocoder/exceptions.rb +19 -0
- data/lib/geocoder/ip_address.rb +16 -11
- data/lib/geocoder/kernel_logger.rb +25 -0
- data/lib/geocoder/logger.rb +47 -0
- data/lib/geocoder/lookup.rb +31 -12
- data/lib/geocoder/lookups/amap.rb +63 -0
- data/lib/geocoder/lookups/baidu.rb +17 -9
- data/lib/geocoder/lookups/baidu_ip.rb +7 -31
- data/lib/geocoder/lookups/ban_data_gouv_fr.rb +143 -0
- data/lib/geocoder/lookups/base.rb +73 -25
- data/lib/geocoder/lookups/bing.rb +38 -15
- data/lib/geocoder/lookups/db_ip_com.rb +52 -0
- data/lib/geocoder/lookups/dstk.rb +4 -2
- data/lib/geocoder/lookups/esri.rb +55 -8
- data/lib/geocoder/lookups/freegeoip.rb +18 -5
- data/lib/geocoder/lookups/geocoder_ca.rb +5 -6
- data/lib/geocoder/lookups/geocodio.rb +8 -8
- data/lib/geocoder/lookups/geoip2.rb +10 -5
- data/lib/geocoder/lookups/geoportail_lu.rb +65 -0
- data/lib/geocoder/lookups/google.rb +37 -9
- data/lib/geocoder/lookups/google_places_details.rb +9 -9
- data/lib/geocoder/lookups/google_places_search.rb +33 -0
- data/lib/geocoder/lookups/google_premier.rb +11 -1
- data/lib/geocoder/lookups/here.rb +29 -23
- data/lib/geocoder/lookups/ip2location.rb +67 -0
- data/lib/geocoder/lookups/ipapi_com.rb +82 -0
- data/lib/geocoder/lookups/ipdata_co.rb +62 -0
- data/lib/geocoder/lookups/ipgeolocation.rb +51 -0
- data/lib/geocoder/lookups/ipinfo_io.rb +44 -0
- data/lib/geocoder/lookups/ipregistry.rb +68 -0
- data/lib/geocoder/lookups/ipstack.rb +63 -0
- data/lib/geocoder/lookups/latlon.rb +59 -0
- data/lib/geocoder/lookups/location_iq.rb +50 -0
- data/lib/geocoder/lookups/mapbox.rb +59 -0
- data/lib/geocoder/lookups/mapquest.rb +7 -9
- data/lib/geocoder/lookups/maxmind.rb +7 -7
- data/lib/geocoder/lookups/maxmind_geoip2.rb +70 -0
- data/lib/geocoder/lookups/maxmind_local.rb +9 -2
- data/lib/geocoder/lookups/nominatim.rb +18 -6
- data/lib/geocoder/lookups/opencagedata.rb +16 -9
- data/lib/geocoder/lookups/osmnames.rb +57 -0
- data/lib/geocoder/lookups/pelias.rb +63 -0
- data/lib/geocoder/lookups/pickpoint.rb +41 -0
- data/lib/geocoder/lookups/pointpin.rb +14 -13
- data/lib/geocoder/lookups/postcode_anywhere_uk.rb +7 -8
- data/lib/geocoder/lookups/postcodes_io.rb +31 -0
- data/lib/geocoder/lookups/smarty_streets.rb +23 -5
- data/lib/geocoder/lookups/telize.rb +42 -7
- data/lib/geocoder/lookups/tencent.rb +59 -0
- data/lib/geocoder/lookups/yandex.rb +17 -9
- data/lib/geocoder/models/active_record.rb +4 -3
- data/lib/geocoder/models/mongo_base.rb +0 -2
- data/lib/geocoder/query.rb +15 -1
- data/lib/geocoder/railtie.rb +1 -1
- data/lib/geocoder/request.rb +103 -14
- data/lib/geocoder/results/amap.rb +87 -0
- data/lib/geocoder/results/baidu.rb +10 -14
- data/lib/geocoder/results/ban_data_gouv_fr.rb +257 -0
- data/lib/geocoder/results/base.rb +13 -1
- data/lib/geocoder/results/bing.rb +5 -1
- data/lib/geocoder/results/db_ip_com.rb +58 -0
- data/lib/geocoder/results/esri.rb +30 -6
- data/lib/geocoder/results/freegeoip.rb +2 -7
- data/lib/geocoder/results/geocoder_ca.rb +3 -3
- data/lib/geocoder/results/geocodio.rb +15 -3
- data/lib/geocoder/results/geoip2.rb +37 -25
- data/lib/geocoder/results/geoportail_lu.rb +71 -0
- data/lib/geocoder/results/google.rb +26 -0
- data/lib/geocoder/results/google_places_details.rb +4 -0
- data/lib/geocoder/results/google_places_search.rb +52 -0
- data/lib/geocoder/results/here.rb +21 -1
- data/lib/geocoder/results/ip2location.rb +22 -0
- data/lib/geocoder/results/ipapi_com.rb +45 -0
- data/lib/geocoder/results/ipdata_co.rb +40 -0
- data/lib/geocoder/results/ipgeolocation.rb +59 -0
- data/lib/geocoder/results/ipinfo_io.rb +48 -0
- data/lib/geocoder/results/ipregistry.rb +308 -0
- data/lib/geocoder/results/ipstack.rb +60 -0
- data/lib/geocoder/results/latlon.rb +71 -0
- data/lib/geocoder/results/location_iq.rb +6 -0
- data/lib/geocoder/results/mapbox.rb +57 -0
- data/lib/geocoder/results/mapquest.rb +5 -8
- data/lib/geocoder/results/maxmind.rb +0 -5
- data/lib/geocoder/results/maxmind_geoip2.rb +9 -0
- data/lib/geocoder/results/maxmind_local.rb +0 -5
- data/lib/geocoder/results/nominatim.rb +18 -3
- data/lib/geocoder/results/opencagedata.rb +20 -2
- data/lib/geocoder/results/osmnames.rb +56 -0
- data/lib/geocoder/results/pelias.rb +58 -0
- data/lib/geocoder/results/pickpoint.rb +6 -0
- data/lib/geocoder/results/pointpin.rb +0 -4
- data/lib/geocoder/results/postcodes_io.rb +40 -0
- data/lib/geocoder/results/smarty_streets.rb +55 -19
- data/lib/geocoder/results/telize.rb +0 -5
- data/lib/geocoder/results/tencent.rb +72 -0
- data/lib/geocoder/results/test.rb +1 -1
- data/lib/geocoder/results/yandex.rb +57 -7
- data/lib/geocoder/sql.rb +9 -6
- data/lib/geocoder/stores/active_record.rb +49 -10
- data/lib/geocoder/stores/base.rb +2 -14
- data/lib/geocoder/stores/mongo_base.rb +0 -31
- data/lib/geocoder/version.rb +1 -1
- data/lib/geocoder.rb +2 -1
- data/lib/hash_recursive_merge.rb +1 -2
- data/lib/maxmind_database.rb +4 -4
- data/lib/tasks/geocoder.rake +29 -4
- metadata +56 -159
- data/.gitignore +0 -6
- data/.travis.yml +0 -31
- data/Rakefile +0 -25
- data/gemfiles/Gemfile.mongoid-2.4.x +0 -16
- data/lib/geocoder/lookups/geocoder_us.rb +0 -39
- data/lib/geocoder/lookups/okf.rb +0 -43
- data/lib/geocoder/lookups/ovi.rb +0 -62
- data/lib/geocoder/lookups/yahoo.rb +0 -88
- data/lib/geocoder/results/geocoder_us.rb +0 -39
- data/lib/geocoder/results/okf.rb +0 -106
- data/lib/geocoder/results/ovi.rb +0 -62
- data/lib/geocoder/results/yahoo.rb +0 -55
- data/lib/oauth_util.rb +0 -112
- data/test/fixtures/baidu_invalid_key +0 -1
- data/test/fixtures/baidu_ip_202_198_16_3 +0 -19
- data/test/fixtures/baidu_ip_invalid_key +0 -1
- data/test/fixtures/baidu_ip_no_results +0 -1
- data/test/fixtures/baidu_no_results +0 -1
- data/test/fixtures/baidu_reverse +0 -1
- data/test/fixtures/baidu_shanghai_pearl_tower +0 -12
- data/test/fixtures/bing_invalid_key +0 -1
- data/test/fixtures/bing_madison_square_garden +0 -40
- data/test/fixtures/bing_no_results +0 -16
- data/test/fixtures/bing_reverse +0 -42
- data/test/fixtures/cloudmade_invalid_key +0 -1
- data/test/fixtures/cloudmade_madison_square_garden +0 -1
- data/test/fixtures/cloudmade_no_results +0 -1
- data/test/fixtures/esri_madison_square_garden +0 -59
- data/test/fixtures/esri_no_results +0 -8
- data/test/fixtures/esri_reverse +0 -21
- data/test/fixtures/freegeoip_74_200_247_59 +0 -12
- data/test/fixtures/freegeoip_no_results +0 -1
- data/test/fixtures/geocoder_ca_madison_square_garden +0 -1
- data/test/fixtures/geocoder_ca_no_results +0 -1
- data/test/fixtures/geocoder_ca_reverse +0 -34
- data/test/fixtures/geocoder_us_madison_square_garden +0 -1
- data/test/fixtures/geocoder_us_no_results +0 -1
- data/test/fixtures/geocodio_1101_pennsylvania_ave +0 -1
- data/test/fixtures/geocodio_bad_api_key +0 -3
- data/test/fixtures/geocodio_invalid +0 -4
- data/test/fixtures/geocodio_no_results +0 -1
- data/test/fixtures/geocodio_over_query_limit +0 -4
- data/test/fixtures/google_garbage +0 -456
- data/test/fixtures/google_madison_square_garden +0 -57
- data/test/fixtures/google_no_city_data +0 -44
- data/test/fixtures/google_no_locality +0 -51
- data/test/fixtures/google_no_results +0 -4
- data/test/fixtures/google_over_limit +0 -4
- data/test/fixtures/google_places_details_invalid_request +0 -4
- data/test/fixtures/google_places_details_madison_square_garden +0 -120
- data/test/fixtures/google_places_details_no_results +0 -4
- data/test/fixtures/google_places_details_no_reviews +0 -60
- data/test/fixtures/google_places_details_no_types +0 -66
- data/test/fixtures/here_madison_square_garden +0 -72
- data/test/fixtures/here_no_results +0 -8
- data/test/fixtures/mapquest_error +0 -16
- data/test/fixtures/mapquest_invalid_api_key +0 -16
- data/test/fixtures/mapquest_invalid_request +0 -16
- data/test/fixtures/mapquest_madison_square_garden +0 -52
- data/test/fixtures/mapquest_no_results +0 -16
- data/test/fixtures/maxmind_24_24_24_21 +0 -1
- data/test/fixtures/maxmind_24_24_24_22 +0 -1
- data/test/fixtures/maxmind_24_24_24_23 +0 -1
- data/test/fixtures/maxmind_24_24_24_24 +0 -1
- data/test/fixtures/maxmind_74_200_247_59 +0 -1
- data/test/fixtures/maxmind_invalid_key +0 -1
- data/test/fixtures/maxmind_no_results +0 -1
- data/test/fixtures/nominatim_madison_square_garden +0 -150
- data/test/fixtures/nominatim_no_results +0 -1
- data/test/fixtures/nominatim_over_limit +0 -1
- data/test/fixtures/okf_kirstinmaki +0 -67
- data/test/fixtures/okf_no_results +0 -4
- data/test/fixtures/opencagedata_invalid_api_key +0 -25
- data/test/fixtures/opencagedata_invalid_request +0 -26
- data/test/fixtures/opencagedata_madison_square_garden +0 -73
- data/test/fixtures/opencagedata_no_results +0 -29
- data/test/fixtures/opencagedata_over_limit +0 -31
- data/test/fixtures/ovi_madison_square_garden +0 -72
- data/test/fixtures/ovi_no_results +0 -8
- data/test/fixtures/pointpin_10_10_10_10 +0 -1
- data/test/fixtures/pointpin_555_555_555_555 +0 -1
- data/test/fixtures/pointpin_80_111_555_555 +0 -1
- data/test/fixtures/pointpin_no_results +0 -1
- data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_WR26NJ +0 -1
- data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_generic_error +0 -1
- data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_hampshire +0 -1
- data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_key_limit_exceeded +0 -1
- data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_no_results +0 -1
- data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_romsey +0 -1
- data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_unknown_key +0 -1
- data/test/fixtures/smarty_streets_11211 +0 -1
- data/test/fixtures/smarty_streets_madison_square_garden +0 -47
- data/test/fixtures/smarty_streets_no_results +0 -1
- data/test/fixtures/telize_10_10_10_10 +0 -1
- data/test/fixtures/telize_555_555_555_555 +0 -4
- data/test/fixtures/telize_74_200_247_59 +0 -1
- data/test/fixtures/telize_no_results +0 -1
- data/test/fixtures/yahoo_error +0 -1
- data/test/fixtures/yahoo_invalid_key +0 -2
- data/test/fixtures/yahoo_madison_square_garden +0 -52
- data/test/fixtures/yahoo_no_results +0 -10
- data/test/fixtures/yahoo_over_limit +0 -2
- data/test/fixtures/yandex_canada_rue_dupuis_14 +0 -446
- data/test/fixtures/yandex_invalid_key +0 -1
- data/test/fixtures/yandex_kremlin +0 -48
- data/test/fixtures/yandex_new_york +0 -1
- data/test/fixtures/yandex_no_city_and_town +0 -112
- data/test/fixtures/yandex_no_results +0 -16
- data/test/integration/http_client_test.rb +0 -31
- data/test/mongoid_test_helper.rb +0 -43
- data/test/test_helper.rb +0 -416
- data/test/unit/active_record_test.rb +0 -16
- data/test/unit/cache_test.rb +0 -37
- data/test/unit/calculations_test.rb +0 -220
- data/test/unit/configuration_test.rb +0 -55
- data/test/unit/error_handling_test.rb +0 -56
- data/test/unit/geocoder_test.rb +0 -78
- data/test/unit/https_test.rb +0 -17
- data/test/unit/ip_address_test.rb +0 -27
- data/test/unit/lookup_test.rb +0 -153
- data/test/unit/lookups/bing_test.rb +0 -68
- data/test/unit/lookups/dstk_test.rb +0 -26
- data/test/unit/lookups/esri_test.rb +0 -48
- data/test/unit/lookups/freegeoip_test.rb +0 -27
- data/test/unit/lookups/geocoder_ca_test.rb +0 -17
- data/test/unit/lookups/geocodio_test.rb +0 -55
- data/test/unit/lookups/geoip2_test.rb +0 -27
- data/test/unit/lookups/google_places_details_test.rb +0 -122
- data/test/unit/lookups/google_premier_test.rb +0 -22
- data/test/unit/lookups/google_test.rb +0 -84
- data/test/unit/lookups/mapquest_test.rb +0 -60
- data/test/unit/lookups/maxmind_local_test.rb +0 -28
- data/test/unit/lookups/maxmind_test.rb +0 -63
- data/test/unit/lookups/nominatim_test.rb +0 -31
- data/test/unit/lookups/okf_test.rb +0 -38
- data/test/unit/lookups/opencagedata_test.rb +0 -64
- data/test/unit/lookups/pointpin_test.rb +0 -30
- data/test/unit/lookups/postcode_anywhere_uk_test.rb +0 -70
- data/test/unit/lookups/smarty_streets_test.rb +0 -71
- data/test/unit/lookups/telize_test.rb +0 -36
- data/test/unit/lookups/yahoo_test.rb +0 -35
- data/test/unit/method_aliases_test.rb +0 -26
- data/test/unit/model_test.rb +0 -38
- data/test/unit/mongoid_test.rb +0 -47
- data/test/unit/near_test.rb +0 -87
- data/test/unit/oauth_util_test.rb +0 -31
- data/test/unit/proxy_test.rb +0 -37
- data/test/unit/query_test.rb +0 -52
- data/test/unit/rake_task_test.rb +0 -21
- data/test/unit/request_test.rb +0 -35
- data/test/unit/result_test.rb +0 -72
- data/test/unit/test_mode_test.rb +0 -70
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require 'geocoder/results/base'
|
|
2
|
+
|
|
3
|
+
module Geocoder::Result
|
|
4
|
+
class Osmnames < Base
|
|
5
|
+
def address
|
|
6
|
+
@data['display_name']
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def coordinates
|
|
10
|
+
[@data['lat'].to_f, @data['lon'].to_f]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def viewport
|
|
14
|
+
west, south, east, north = @data['boundingbox'].map(&:to_f)
|
|
15
|
+
[south, west, north, east]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def state
|
|
19
|
+
@data['state']
|
|
20
|
+
end
|
|
21
|
+
alias_method :state_code, :state
|
|
22
|
+
|
|
23
|
+
def place_class
|
|
24
|
+
@data['class']
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def place_type
|
|
28
|
+
@data['type']
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def postal_code
|
|
32
|
+
''
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def country_code
|
|
36
|
+
@data['country_code']
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def country
|
|
40
|
+
@data['country']
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.response_attributes
|
|
44
|
+
%w[house_number street city name osm_id osm_type boundingbox place_rank
|
|
45
|
+
importance county rank name_suffix]
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
response_attributes.each do |a|
|
|
49
|
+
unless method_defined?(a)
|
|
50
|
+
define_method a do
|
|
51
|
+
@data[a]
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require 'geocoder/results/base'
|
|
2
|
+
|
|
3
|
+
module Geocoder::Result
|
|
4
|
+
class Pelias < Base
|
|
5
|
+
def address(format = :full)
|
|
6
|
+
properties['label']
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def city
|
|
10
|
+
locality
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def coordinates
|
|
14
|
+
geometry['coordinates'].reverse
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def country_code
|
|
18
|
+
properties['country_a']
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def postal_code
|
|
22
|
+
properties['postalcode'].to_s
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def province
|
|
26
|
+
state
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def state
|
|
30
|
+
properties['region']
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def state_code
|
|
34
|
+
properties['region_a']
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.response_attributes
|
|
38
|
+
%w[county confidence country gid id layer localadmin locality neighborhood]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
response_attributes.each do |a|
|
|
42
|
+
define_method a do
|
|
43
|
+
properties[a]
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def geometry
|
|
50
|
+
@data.fetch('geometry', {})
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def properties
|
|
54
|
+
@data.fetch('properties', {})
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require 'geocoder/results/base'
|
|
2
|
+
|
|
3
|
+
module Geocoder::Result
|
|
4
|
+
class PostcodesIo < Base
|
|
5
|
+
|
|
6
|
+
def coordinates
|
|
7
|
+
[@data['latitude'].to_f, @data['longitude'].to_f]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def quality
|
|
11
|
+
@data['quality']
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def postal_code
|
|
15
|
+
@data['postcode']
|
|
16
|
+
end
|
|
17
|
+
alias address postal_code
|
|
18
|
+
|
|
19
|
+
def city
|
|
20
|
+
@data['admin_ward']
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def county
|
|
24
|
+
@data['admin_county']
|
|
25
|
+
end
|
|
26
|
+
alias state county
|
|
27
|
+
|
|
28
|
+
def state_code
|
|
29
|
+
@data['codes']['admin_county']
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def country
|
|
33
|
+
'United Kingdom'
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def country_code
|
|
37
|
+
'UK'
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -3,57 +3,89 @@ require 'geocoder/lookups/base'
|
|
|
3
3
|
module Geocoder::Result
|
|
4
4
|
class SmartyStreets < Base
|
|
5
5
|
def coordinates
|
|
6
|
-
%w(latitude longitude).map do |i|
|
|
6
|
+
result = %w(latitude longitude).map do |i|
|
|
7
7
|
zipcode_endpoint? ? zipcodes.first[i] : metadata[i]
|
|
8
8
|
end
|
|
9
|
+
|
|
10
|
+
if result.compact.empty?
|
|
11
|
+
nil
|
|
12
|
+
else
|
|
13
|
+
result
|
|
14
|
+
end
|
|
9
15
|
end
|
|
10
16
|
|
|
11
17
|
def address
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
parts =
|
|
19
|
+
if international_endpoint?
|
|
20
|
+
(1..12).map { |i| @data["address#{i}"] }
|
|
21
|
+
else
|
|
22
|
+
[
|
|
23
|
+
delivery_line_1,
|
|
24
|
+
delivery_line_2,
|
|
25
|
+
last_line
|
|
26
|
+
]
|
|
27
|
+
end
|
|
28
|
+
parts.select{ |i| i.to_s != "" }.join(" ")
|
|
17
29
|
end
|
|
18
30
|
|
|
19
31
|
def state
|
|
20
|
-
|
|
21
|
-
|
|
32
|
+
if international_endpoint?
|
|
33
|
+
components['administrative_area']
|
|
34
|
+
elsif zipcode_endpoint?
|
|
35
|
+
city_states.first['state']
|
|
36
|
+
else
|
|
22
37
|
components['state_abbreviation']
|
|
38
|
+
end
|
|
23
39
|
end
|
|
24
40
|
|
|
25
41
|
def state_code
|
|
26
|
-
|
|
27
|
-
|
|
42
|
+
if international_endpoint?
|
|
43
|
+
components['administrative_area']
|
|
44
|
+
elsif zipcode_endpoint?
|
|
45
|
+
city_states.first['state_abbreviation']
|
|
46
|
+
else
|
|
28
47
|
components['state_abbreviation']
|
|
48
|
+
end
|
|
29
49
|
end
|
|
30
50
|
|
|
31
51
|
def country
|
|
32
|
-
|
|
33
|
-
|
|
52
|
+
international_endpoint? ?
|
|
53
|
+
components['country_iso_3'] :
|
|
54
|
+
"United States"
|
|
34
55
|
end
|
|
35
56
|
|
|
36
57
|
def country_code
|
|
37
|
-
|
|
38
|
-
|
|
58
|
+
international_endpoint? ?
|
|
59
|
+
components['country_iso_3'] :
|
|
60
|
+
"US"
|
|
39
61
|
end
|
|
40
62
|
|
|
41
63
|
## Extra methods not in base.rb ------------------------
|
|
42
64
|
|
|
43
65
|
def street
|
|
44
|
-
|
|
66
|
+
international_endpoint? ?
|
|
67
|
+
components['thoroughfare_name'] :
|
|
68
|
+
components['street_name']
|
|
45
69
|
end
|
|
46
70
|
|
|
47
71
|
def city
|
|
48
|
-
|
|
49
|
-
|
|
72
|
+
if international_endpoint?
|
|
73
|
+
components['locality']
|
|
74
|
+
elsif zipcode_endpoint?
|
|
75
|
+
city_states.first['city']
|
|
76
|
+
else
|
|
50
77
|
components['city_name']
|
|
78
|
+
end
|
|
51
79
|
end
|
|
52
80
|
|
|
53
81
|
def zipcode
|
|
54
|
-
|
|
55
|
-
|
|
82
|
+
if international_endpoint?
|
|
83
|
+
components['postal_code']
|
|
84
|
+
elsif zipcode_endpoint?
|
|
85
|
+
zipcodes.first['zipcode']
|
|
86
|
+
else
|
|
56
87
|
components['zipcode']
|
|
88
|
+
end
|
|
57
89
|
end
|
|
58
90
|
alias_method :postal_code, :zipcode
|
|
59
91
|
|
|
@@ -72,6 +104,10 @@ module Geocoder::Result
|
|
|
72
104
|
zipcodes.any?
|
|
73
105
|
end
|
|
74
106
|
|
|
107
|
+
def international_endpoint?
|
|
108
|
+
!@data['address1'].nil?
|
|
109
|
+
end
|
|
110
|
+
|
|
75
111
|
[
|
|
76
112
|
:delivery_line_1,
|
|
77
113
|
:delivery_line_2,
|
|
@@ -3,11 +3,6 @@ require 'geocoder/results/base'
|
|
|
3
3
|
module Geocoder::Result
|
|
4
4
|
class Telize < Base
|
|
5
5
|
|
|
6
|
-
def address(format = :full)
|
|
7
|
-
s = state_code.to_s == "" ? "" : ", #{state_code}"
|
|
8
|
-
"#{city}#{s} #{postal_code}, #{country}".sub(/^[ ,]*/, "")
|
|
9
|
-
end
|
|
10
|
-
|
|
11
6
|
def city
|
|
12
7
|
@data['city']
|
|
13
8
|
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
require 'geocoder/results/base'
|
|
2
|
+
|
|
3
|
+
module Geocoder::Result
|
|
4
|
+
class Tencent < Base
|
|
5
|
+
|
|
6
|
+
def coordinates
|
|
7
|
+
['lat', 'lng'].map{ |i| @data['location'][i] }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def address
|
|
11
|
+
"#{province}#{city}#{district}#{street}#{street_number}"
|
|
12
|
+
|
|
13
|
+
#@data['title'] or @data['address']
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# NOTE: The Tencent reverse geocoding API has the field named
|
|
17
|
+
# 'address_component' compared to 'address_components' in the
|
|
18
|
+
# regular geocoding API.
|
|
19
|
+
def province
|
|
20
|
+
@data['address_components'] and (@data['address_components']['province']) or
|
|
21
|
+
(@data['address_component'] and @data['address_component']['province']) or
|
|
22
|
+
""
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
alias_method :state, :province
|
|
26
|
+
|
|
27
|
+
def city
|
|
28
|
+
@data['address_components'] and (@data['address_components']['city']) or
|
|
29
|
+
(@data['address_component'] and @data['address_component']['city']) or
|
|
30
|
+
""
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def district
|
|
34
|
+
@data['address_components'] and (@data['address_components']['district']) or
|
|
35
|
+
(@data['address_component'] and @data['address_component']['district']) or
|
|
36
|
+
""
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def street
|
|
40
|
+
@data['address_components'] and (@data['address_components']['street']) or
|
|
41
|
+
(@data['address_component'] and @data['address_component']['street']) or
|
|
42
|
+
""
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def street_number
|
|
46
|
+
@data['address_components'] and (@data['address_components']['street_number']) or
|
|
47
|
+
(@data['address_component'] and @data['address_component']['street_number']) or
|
|
48
|
+
""
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def address_components
|
|
52
|
+
@data['address_components'] or @data['address_component']
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def state_code
|
|
56
|
+
""
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def postal_code
|
|
60
|
+
""
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def country
|
|
64
|
+
"China"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def country_code
|
|
68
|
+
"CN"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -15,7 +15,7 @@ module Geocoder
|
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
%w[
|
|
18
|
+
%w[coordinates neighborhood city state state_code sub_state
|
|
19
19
|
sub_state_code province province_code postal_code country
|
|
20
20
|
country_code address street_address street_number route geometry].each do |attr|
|
|
21
21
|
add_result_attribute(attr)
|
|
@@ -12,9 +12,10 @@ module Geocoder::Result
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def city
|
|
15
|
-
if state.empty? and address_details.has_key? 'Locality'
|
|
15
|
+
if state.empty? and address_details and address_details.has_key? 'Locality'
|
|
16
16
|
address_details['Locality']['LocalityName']
|
|
17
|
-
elsif sub_state.empty? and address_details
|
|
17
|
+
elsif sub_state.empty? and address_details and address_details.has_key? 'AdministrativeArea' and
|
|
18
|
+
address_details['AdministrativeArea'].has_key? 'Locality'
|
|
18
19
|
address_details['AdministrativeArea']['Locality']['LocalityName']
|
|
19
20
|
elsif not sub_state_city.empty?
|
|
20
21
|
sub_state_city
|
|
@@ -24,15 +25,23 @@ module Geocoder::Result
|
|
|
24
25
|
end
|
|
25
26
|
|
|
26
27
|
def country
|
|
27
|
-
address_details
|
|
28
|
+
if address_details
|
|
29
|
+
address_details['CountryName']
|
|
30
|
+
else
|
|
31
|
+
""
|
|
32
|
+
end
|
|
28
33
|
end
|
|
29
34
|
|
|
30
35
|
def country_code
|
|
31
|
-
address_details
|
|
36
|
+
if address_details
|
|
37
|
+
address_details['CountryNameCode']
|
|
38
|
+
else
|
|
39
|
+
""
|
|
40
|
+
end
|
|
32
41
|
end
|
|
33
42
|
|
|
34
43
|
def state
|
|
35
|
-
if address_details['AdministrativeArea']
|
|
44
|
+
if address_details and address_details['AdministrativeArea']
|
|
36
45
|
address_details['AdministrativeArea']['AdministrativeAreaName']
|
|
37
46
|
else
|
|
38
47
|
""
|
|
@@ -40,7 +49,7 @@ module Geocoder::Result
|
|
|
40
49
|
end
|
|
41
50
|
|
|
42
51
|
def sub_state
|
|
43
|
-
if !state.empty? and address_details['AdministrativeArea']['SubAdministrativeArea']
|
|
52
|
+
if !state.empty? and address_details and address_details['AdministrativeArea']['SubAdministrativeArea']
|
|
44
53
|
address_details['AdministrativeArea']['SubAdministrativeArea']['SubAdministrativeAreaName']
|
|
45
54
|
else
|
|
46
55
|
""
|
|
@@ -59,6 +68,14 @@ module Geocoder::Result
|
|
|
59
68
|
address_details['Locality']['Premise']['PremiseName']
|
|
60
69
|
end
|
|
61
70
|
|
|
71
|
+
def street
|
|
72
|
+
thoroughfare_data && thoroughfare_data['ThoroughfareName']
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def street_number
|
|
76
|
+
thoroughfare_data && thoroughfare_data['Premise'] && thoroughfare_data['Premise']['PremiseNumber']
|
|
77
|
+
end
|
|
78
|
+
|
|
62
79
|
def kind
|
|
63
80
|
@data['GeoObject']['metaDataProperty']['GeocoderMetaData']['kind']
|
|
64
81
|
end
|
|
@@ -67,14 +84,47 @@ module Geocoder::Result
|
|
|
67
84
|
@data['GeoObject']['metaDataProperty']['GeocoderMetaData']['precision']
|
|
68
85
|
end
|
|
69
86
|
|
|
87
|
+
def viewport
|
|
88
|
+
envelope = @data['GeoObject']['boundedBy']['Envelope'] || fail
|
|
89
|
+
east, north = envelope['upperCorner'].split(' ').map(&:to_f)
|
|
90
|
+
west, south = envelope['lowerCorner'].split(' ').map(&:to_f)
|
|
91
|
+
[south, west, north, east]
|
|
92
|
+
end
|
|
93
|
+
|
|
70
94
|
private # ----------------------------------------------------------------
|
|
71
95
|
|
|
96
|
+
def thoroughfare_data
|
|
97
|
+
locality_data && locality_data['Thoroughfare']
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def locality_data
|
|
101
|
+
dependent_locality && subadmin_locality && admin_locality
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def admin_locality
|
|
105
|
+
address_details && address_details['AdministrativeArea'] &&
|
|
106
|
+
address_details['AdministrativeArea']['Locality']
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def subadmin_locality
|
|
110
|
+
address_details && address_details['AdministrativeArea'] &&
|
|
111
|
+
address_details['AdministrativeArea']['SubAdministrativeArea'] &&
|
|
112
|
+
address_details['AdministrativeArea']['SubAdministrativeArea']['Locality']
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def dependent_locality
|
|
116
|
+
address_details && address_details['AdministrativeArea'] &&
|
|
117
|
+
address_details['AdministrativeArea']['SubAdministrativeArea'] &&
|
|
118
|
+
address_details['AdministrativeArea']['SubAdministrativeArea']['Locality'] &&
|
|
119
|
+
address_details['AdministrativeArea']['SubAdministrativeArea']['Locality']['DependentLocality']
|
|
120
|
+
end
|
|
121
|
+
|
|
72
122
|
def address_details
|
|
73
123
|
@data['GeoObject']['metaDataProperty']['GeocoderMetaData']['AddressDetails']['Country']
|
|
74
124
|
end
|
|
75
125
|
|
|
76
126
|
def sub_state_city
|
|
77
|
-
if !sub_state.empty? and address_details['AdministrativeArea']['SubAdministrativeArea'].has_key? 'Locality'
|
|
127
|
+
if !sub_state.empty? and address_details and address_details['AdministrativeArea']['SubAdministrativeArea'].has_key? 'Locality'
|
|
78
128
|
address_details['AdministrativeArea']['SubAdministrativeArea']['Locality']['LocalityName'] || ""
|
|
79
129
|
else
|
|
80
130
|
""
|
data/lib/geocoder/sql.rb
CHANGED
|
@@ -4,8 +4,8 @@ module Geocoder
|
|
|
4
4
|
|
|
5
5
|
##
|
|
6
6
|
# Distance calculation for use with a database that supports POWER(),
|
|
7
|
-
# SQRT(), PI(), and trigonometric functions SIN(), COS(), ASIN(),
|
|
8
|
-
# ATAN2()
|
|
7
|
+
# SQRT(), PI(), and trigonometric functions SIN(), COS(), ASIN(),
|
|
8
|
+
# ATAN2().
|
|
9
9
|
#
|
|
10
10
|
# Based on the excellent tutorial at:
|
|
11
11
|
# http://www.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL
|
|
@@ -44,13 +44,13 @@ module Geocoder
|
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
def within_bounding_box(sw_lat, sw_lng, ne_lat, ne_lng, lat_attr, lon_attr)
|
|
47
|
-
spans = "#{lat_attr} BETWEEN #{sw_lat} AND #{ne_lat} AND "
|
|
47
|
+
spans = "#{lat_attr} BETWEEN #{sw_lat.to_f} AND #{ne_lat.to_f} AND "
|
|
48
48
|
# handle box that spans 180 longitude
|
|
49
49
|
if sw_lng.to_f > ne_lng.to_f
|
|
50
|
-
spans + "#{lon_attr} BETWEEN #{sw_lng} AND 180 OR " +
|
|
51
|
-
"#{lon_attr} BETWEEN -180 AND #{ne_lng}"
|
|
50
|
+
spans + "(#{lon_attr} BETWEEN #{sw_lng.to_f} AND 180 OR " +
|
|
51
|
+
"#{lon_attr} BETWEEN -180 AND #{ne_lng.to_f})"
|
|
52
52
|
else
|
|
53
|
-
spans + "#{lon_attr} BETWEEN #{sw_lng} AND #{ne_lng}"
|
|
53
|
+
spans + "#{lon_attr} BETWEEN #{sw_lng.to_f} AND #{ne_lng.to_f}"
|
|
54
54
|
end
|
|
55
55
|
end
|
|
56
56
|
|
|
@@ -59,6 +59,9 @@ module Geocoder
|
|
|
59
59
|
# and an options hash which must include a :bearing value
|
|
60
60
|
# (:linear or :spherical).
|
|
61
61
|
#
|
|
62
|
+
# For use with a database that supports MOD() and trigonometric functions
|
|
63
|
+
# SIN(), COS(), ASIN(), ATAN2().
|
|
64
|
+
#
|
|
62
65
|
# Based on:
|
|
63
66
|
# http://www.beginningspatial.com/calculating_bearing_one_point_another
|
|
64
67
|
#
|
|
@@ -28,6 +28,11 @@ module Geocoder::Store
|
|
|
28
28
|
"OR #{table_name}.#{geocoder_options[:longitude]} IS NULL")
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
# scope: not-reverse geocoded objects
|
|
32
|
+
scope :not_reverse_geocoded, lambda {
|
|
33
|
+
where("#{table_name}.#{geocoder_options[:fetched_address]} IS NULL")
|
|
34
|
+
}
|
|
35
|
+
|
|
31
36
|
##
|
|
32
37
|
# Find all objects within a radius of the given location.
|
|
33
38
|
# Location may be either a string to geocode or an array of
|
|
@@ -55,7 +60,7 @@ module Geocoder::Store
|
|
|
55
60
|
# corner followed by the northeast corner of the box
|
|
56
61
|
# (<tt>[[sw_lat, sw_lon], [ne_lat, ne_lon]]</tt>).
|
|
57
62
|
#
|
|
58
|
-
scope :within_bounding_box, lambda{
|
|
63
|
+
scope :within_bounding_box, lambda{ |*bounds|
|
|
59
64
|
sw_lat, sw_lng, ne_lat, ne_lng = bounds.flatten if bounds
|
|
60
65
|
if sw_lat && sw_lng && ne_lat && ne_lng
|
|
61
66
|
where(Geocoder::Sql.within_bounding_box(
|
|
@@ -82,8 +87,6 @@ module Geocoder::Store
|
|
|
82
87
|
end
|
|
83
88
|
end
|
|
84
89
|
|
|
85
|
-
private # ----------------------------------------------------------------
|
|
86
|
-
|
|
87
90
|
##
|
|
88
91
|
# Get options hash suitable for passing to ActiveRecord.find to get
|
|
89
92
|
# records within a radius (in kilometers) of the given point.
|
|
@@ -126,18 +129,31 @@ module Geocoder::Store
|
|
|
126
129
|
distance_column = options.fetch(:distance_column) { 'distance' }
|
|
127
130
|
bearing_column = options.fetch(:bearing_column) { 'bearing' }
|
|
128
131
|
|
|
129
|
-
|
|
132
|
+
# If radius is a DB column name, bounding box should include
|
|
133
|
+
# all rows within the maximum radius appearing in that column.
|
|
134
|
+
# Note: performance is dependent on variability of radii.
|
|
135
|
+
bb_radius = radius.is_a?(Symbol) ? maximum(radius) : radius
|
|
136
|
+
b = Geocoder::Calculations.bounding_box([latitude, longitude], bb_radius, options)
|
|
130
137
|
args = b + [
|
|
131
138
|
full_column_name(latitude_attribute),
|
|
132
139
|
full_column_name(longitude_attribute)
|
|
133
140
|
]
|
|
134
141
|
bounding_box_conditions = Geocoder::Sql.within_bounding_box(*args)
|
|
135
142
|
|
|
136
|
-
if
|
|
143
|
+
if using_unextended_sqlite?
|
|
137
144
|
conditions = bounding_box_conditions
|
|
138
145
|
else
|
|
139
146
|
min_radius = options.fetch(:min_radius, 0).to_f
|
|
140
|
-
|
|
147
|
+
# if radius is a DB column name,
|
|
148
|
+
# find rows between min_radius and value in column
|
|
149
|
+
if radius.is_a?(Symbol)
|
|
150
|
+
c = "BETWEEN ? AND #{radius}"
|
|
151
|
+
a = [min_radius]
|
|
152
|
+
else
|
|
153
|
+
c = "BETWEEN ? AND ?"
|
|
154
|
+
a = [min_radius, radius]
|
|
155
|
+
end
|
|
156
|
+
conditions = [bounding_box_conditions + " AND (#{distance}) " + c] + a
|
|
141
157
|
end
|
|
142
158
|
{
|
|
143
159
|
:select => select_clause(options[:select],
|
|
@@ -155,7 +171,7 @@ module Geocoder::Store
|
|
|
155
171
|
# capabilities (trig functions?).
|
|
156
172
|
#
|
|
157
173
|
def distance_sql(latitude, longitude, options = {})
|
|
158
|
-
method_prefix =
|
|
174
|
+
method_prefix = using_unextended_sqlite? ? "approx" : "full"
|
|
159
175
|
Geocoder::Sql.send(
|
|
160
176
|
method_prefix + "_distance",
|
|
161
177
|
latitude, longitude,
|
|
@@ -174,7 +190,7 @@ module Geocoder::Store
|
|
|
174
190
|
options[:bearing] = Geocoder.config.distances
|
|
175
191
|
end
|
|
176
192
|
if options[:bearing]
|
|
177
|
-
method_prefix =
|
|
193
|
+
method_prefix = using_unextended_sqlite? ? "approx" : "full"
|
|
178
194
|
Geocoder::Sql.send(
|
|
179
195
|
method_prefix + "_bearing",
|
|
180
196
|
latitude, longitude,
|
|
@@ -220,8 +236,20 @@ module Geocoder::Store
|
|
|
220
236
|
conditions
|
|
221
237
|
end
|
|
222
238
|
|
|
239
|
+
def using_unextended_sqlite?
|
|
240
|
+
using_sqlite? && !using_sqlite_with_extensions?
|
|
241
|
+
end
|
|
242
|
+
|
|
223
243
|
def using_sqlite?
|
|
224
|
-
connection.adapter_name.match(/sqlite/i)
|
|
244
|
+
!!connection.adapter_name.match(/sqlite/i)
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def using_sqlite_with_extensions?
|
|
248
|
+
connection.adapter_name.match(/sqlite/i) &&
|
|
249
|
+
defined?(::SqliteExt) &&
|
|
250
|
+
%W(MOD POWER SQRT PI SIN COS ASIN ATAN2).all?{ |fn_name|
|
|
251
|
+
connection.raw_connection.function_created?(fn_name)
|
|
252
|
+
}
|
|
225
253
|
end
|
|
226
254
|
|
|
227
255
|
def using_postgres?
|
|
@@ -239,7 +267,7 @@ module Geocoder::Store
|
|
|
239
267
|
# Value which can be passed to where() to produce no results.
|
|
240
268
|
#
|
|
241
269
|
def false_condition
|
|
242
|
-
|
|
270
|
+
using_unextended_sqlite? ? 0 : "false"
|
|
243
271
|
end
|
|
244
272
|
|
|
245
273
|
##
|
|
@@ -251,6 +279,17 @@ module Geocoder::Store
|
|
|
251
279
|
end
|
|
252
280
|
end
|
|
253
281
|
|
|
282
|
+
##
|
|
283
|
+
# Get nearby geocoded objects.
|
|
284
|
+
# Takes the same options hash as the near class method (scope).
|
|
285
|
+
# Returns nil if the object is not geocoded.
|
|
286
|
+
#
|
|
287
|
+
def nearbys(radius = 20, options = {})
|
|
288
|
+
return nil unless geocoded?
|
|
289
|
+
options.merge!(:exclude => self) unless send(self.class.primary_key).nil?
|
|
290
|
+
self.class.near(self, radius, options)
|
|
291
|
+
end
|
|
292
|
+
|
|
254
293
|
##
|
|
255
294
|
# Look up coordinates and assign to +latitude+ and +longitude+ attributes
|
|
256
295
|
# (or other as specified in +geocoded_by+). Returns coordinates (array).
|