geocoder 1.2.12 → 1.3.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0ac038477cf014a8e62f7fec0e684f851cb55bbb
4
- data.tar.gz: 3abbf824220bd221ecd033e75c7c14a8ece6057a
3
+ metadata.gz: e7a2b3e33175d20be86a8eaf6c74d6178bc71991
4
+ data.tar.gz: d0dc03b689fbc43f16ae9395c7f743a3dd7876bd
5
5
  SHA512:
6
- metadata.gz: 42d47442e4839e84bcb0d98c28591ddeb1df2c63d19b1400736c1f90523f32e84b80990efb714551592a8614704a234c24533398c81c48052654aaf2f83d3d7f
7
- data.tar.gz: b51c9a638a256db67d025e8ab67001fcb7a482dcae9206931b957952aa215e27c635044c829eecd20043dd901b5a683248155a403baa5f1057954c1711439c3d
6
+ metadata.gz: cb9f5c459af278bd20438a714475dece555b72222c34eab8c8fb61f6ddfc695848d330e9b84f366c8d67e5f253bda7d5e61020ab46382f8fbb40c8b7a9a58e82
7
+ data.tar.gz: ca02902240f5287a570ee05b0bc3b0300708200108b09543763e761ad1f0a2371355ef651471cdf96ce5cdabf104a39aedb04ef684e4f02aa3023911c27d7c4a
data/CHANGELOG.md CHANGED
@@ -3,6 +3,29 @@ Changelog
3
3
 
4
4
  Major changes to Geocoder for each release. Please see the Git log for complete list of changes.
5
5
 
6
+ 1.3.0 (2016 Jan 31)
7
+ -------------------
8
+ * Lazy load lookups to reduce memory footprint (thanks github.com/TrangPham).
9
+ * Add :geoportail_lu lookup (Luxembourg only) (thanks github.com/mdebo).
10
+ * Maxmind local query performance improvement (thanks github.com/vojtad).
11
+ * Remove deprecated Mongo near query methods (please use Mongo-native methods instead).
12
+
13
+ 1.2.14 (2015 Dec 27)
14
+ --------------------
15
+ * Fix bug in :geoip2 lookup (thanks github.com/mromulus).
16
+
17
+ 1.2.13 (2015 Dec 15)
18
+ --------------------
19
+ * Update :telize IP lookup to reflect new URL (thanks github.com/jfredrickson).
20
+ * Add reverse geocode rake task (thanks github.com/FanaHOVA).
21
+ * Fix reversed coordinates array with Mapbox (thanks github.com/marcusat).
22
+ * Fix missing city name in some cases with ESRI (thanks github.com/roybotnik).
23
+ * Prevent re-opening of DB file on every read with :geoip2 (thanks github.com/oogali).
24
+
25
+ 1.2.12 (2015 Oct 29)
26
+ --------------------
27
+ * Fix Ruby 1.9.3 incompatibility (remove non-existent timeout classes) (thanks github.com/roychri).
28
+
6
29
  1.2.11 (2015 Sep 10)
7
30
  --------------------
8
31
  * Fix load issue on Ruby 1.9.3.
data/README.md CHANGED
@@ -9,7 +9,7 @@ _Please note that this README is for the current `HEAD` and may document feature
9
9
  Compatibility
10
10
  -------------
11
11
 
12
- * Supports multiple Ruby versions: Ruby 1.9.3, 2.0.x, 2.1.x, JRuby, and Rubinius.
12
+ * Supports multiple Ruby versions: Ruby 1.9.3, 2.x, JRuby, and Rubinius.
13
13
  * Supports multiple databases: MySQL, PostgreSQL, SQLite, and MongoDB (1.7.0 and higher).
14
14
  * Supports Rails 3 and 4. If you need to use it with Rails 2 please see the `rails2` branch (no longer maintained, limited feature set).
15
15
  * Works very well outside of Rails, you just need to install either the `json` (for MRI) or `json_pure` (for JRuby) gem.
@@ -106,6 +106,10 @@ If you have just added geocoding to an existing application with a lot of object
106
106
 
107
107
  rake geocode:all CLASS=YourModel
108
108
 
109
+ If you need reverse geocoding instead, call the task with REVERSE=true:
110
+
111
+ rake geocode:all CLASS=YourModel REVERSE=true
112
+
109
113
  Geocoder will print warnings if you exceed the rate limit for your geocoding service. Some services — Google notably — enforce a per-second limit in addition to a per-day limit. To avoid exceeding the per-second limit, you can add a `SLEEP` option to pause between requests for a given amount of time. You can also load objects in batches to save memory, for example:
110
114
 
111
115
  rake geocode:all CLASS=YourModel SLEEP=0.25 BATCH=100
@@ -140,6 +144,12 @@ See _Advanced Geocoding_ below for more information about `Geocoder::Result` obj
140
144
  Location-Aware Database Queries
141
145
  -------------------------------
142
146
 
147
+ ### For Mongo-backed models:
148
+
149
+ Please use MongoDB's [geospatial query language](https://docs.mongodb.org/manual/reference/command/geoNear/). Mongoid also provides [a DSL](http://mongoid.github.io/en/mongoid/docs/querying.html#geo_near) for doing near queries.
150
+
151
+ ### For ActiveRecord models:
152
+
143
153
  To find objects by location, use the following scopes:
144
154
 
145
155
  Venue.near('Omaha, NE, US', 20) # venues within 20 miles of Omaha
@@ -149,6 +159,10 @@ To find objects by location, use the following scopes:
149
159
  Venue.geocoded # venues with coordinates
150
160
  Venue.not_geocoded # venues without coordinates
151
161
 
162
+ by default, objects are ordered by distance. To remove the ORDER BY clause use the following:
163
+
164
+ Venue.near('Omaha', 20, :order => false)
165
+
152
166
  With geocoded objects you can do things like this:
153
167
 
154
168
  if obj.geocoded?
@@ -500,6 +514,20 @@ The [Google Places Details API](https://developers.google.com/places/documentati
500
514
  * **Terms of Service**: http://geocoder.us/terms.shtml
501
515
  * **Limitations**: ?
502
516
 
517
+ #### Mapbox (`:mapbox`)
518
+
519
+ * **API key**: required
520
+ * **Dataset**: Uses `mapbox.places` dataset by default. Specific the `mapbox.places-permanent` dataset by setting: `Geocoder.configure(:mapbox => {:dataset => "mapbox.places-permanent"})`
521
+ * **Key signup**: https://www.mapbox.com/pricing/
522
+ * **Quota**: depends on plan
523
+ * **Region**: complete coverage of US and Canada, partial coverage elsewhere (see for details: https://www.mapbox.com/developers/api/geocoding/#coverage)
524
+ * **SSL support**: yes
525
+ * **Languages**: English
526
+ * **Documentation**: https://www.mapbox.com/developers/api/geocoding/
527
+ * **Terms of Service**: https://www.mapbox.com/tos/
528
+ * **Limitations**: For `mapbox.places` dataset, must be displayed on a Mapbox map; Cache results for up to 30 days. For `mapbox.places-permanent` dataset, depends on plan.
529
+ * **Notes**: Currently in public beta.
530
+
503
531
  #### Mapquest (`:mapquest`)
504
532
 
505
533
  * **API key**: required
@@ -609,6 +637,16 @@ Data Science Toolkit provides an API whose reponse format is like Google's but w
609
637
  * **Terms of Service**: http://www.itella.fi/liitteet/palvelutjatuotteet/yhteystietopalvelut/Postinumeropalvelut-Palvelukuvausjakayttoehdot.pdf
610
638
  * **Limitations**: ?
611
639
 
640
+ #### Geoportail.lu (`:geoportail_lu`)
641
+
642
+ * **API key**: none
643
+ * **Quota**: none
644
+ * **Region**: LU
645
+ * **SSL support**: yes
646
+ * **Languages**: en
647
+ * **Documentation**: http://wiki.geoportail.lu/doku.php?id=en:api
648
+ * **Terms of Service**: http://wiki.geoportail.lu/doku.php?id=en:mcg_1
649
+ * **Limitations**: ?
612
650
 
613
651
  #### PostcodeAnywhere Uk (`:postcode_anywhere_uk`)
614
652
 
@@ -653,14 +691,15 @@ This uses the PostcodeAnywhere UK Geocode service, this will geocode any string
653
691
 
654
692
  #### Telize (`:telize`)
655
693
 
656
- * **API key**: none
657
- * **Quota**: none
694
+ * **API key**: required
695
+ * **Quota**: 1,000/day for $7/mo through 100,000/day for $100/mo
658
696
  * **Region**: world
659
- * **SSL support**: no
697
+ * **SSL support**: yes
660
698
  * **Languages**: English
661
- * **Documentation**: http://www.telize.com/
699
+ * **Documentation**: https://market.mashape.com/fcambus/telize
662
700
  * **Terms of Service**: ?
663
701
  * **Limitations**: ?
702
+ * **Notes**: To use Telize set `Geocoder.configure(:ip_lookup => :telize, :api_key => "your_api_key")`.
664
703
 
665
704
  #### MaxMind Legacy Web Services (`:maxmind`)
666
705
 
@@ -895,6 +934,9 @@ Now, any time Geocoder looks up "New York, NY" its results array will contain on
895
934
  ]
896
935
  )
897
936
 
937
+ Note:
938
+ Keys must be strings not symbols when calling `add_stub` or `set_default_stub`. For example `'latitude' =>` not `:latitude =>`.
939
+
898
940
 
899
941
  Command Line Interface
900
942
  ----------------------
@@ -1070,7 +1112,9 @@ If anyone has a more elegant solution to this problem I am very interested in se
1070
1112
  Contributing
1071
1113
  ------------
1072
1114
 
1073
- Contributions are welcome via pull requests on Github. Please respect the following guidelines:
1115
+ Contributions are welcome via Github pull requests. If you are new to the project and looking for a way to get involved, try picking up an issue with a "beginner-task" label. Hints about what needs to be done are usually provided.
1116
+
1117
+ For all contributions, please respect the following guidelines:
1074
1118
 
1075
1119
  * Each pull request should implement ONE feature or bugfix. If you want to add or fix more than one thing, submit more than one pull request.
1076
1120
  * Do not commit changes to files that are irrelevant to your feature or bugfix (eg: `.gitignore`).
@@ -263,7 +263,7 @@ module Geocoder
263
263
  end
264
264
 
265
265
  ##
266
- # Given a start point, distance, and heading (in degrees), provides
266
+ # Given a start point, heading (in degrees), and distance, provides
267
267
  # an endpoint.
268
268
  # The starting point is given in the same way that points are given to all
269
269
  # Geocoder methods that accept points as arguments. It can be:
@@ -125,6 +125,5 @@ module Geocoder
125
125
  end
126
126
  EOS
127
127
  end.join("\n\n"))
128
-
129
128
  end
130
129
  end
@@ -1,3 +1,5 @@
1
+ require "geocoder/lookups/test"
2
+
1
3
  module Geocoder
2
4
  module Lookup
3
5
  extend self
@@ -32,6 +34,7 @@ module Geocoder
32
34
  :geocoder_us,
33
35
  :yandex,
34
36
  :nominatim,
37
+ :mapbox,
35
38
  :mapquest,
36
39
  :opencagedata,
37
40
  :ovi,
@@ -41,6 +44,7 @@ module Geocoder
41
44
  :smarty_streets,
42
45
  :okf,
43
46
  :postcode_anywhere_uk,
47
+ :geoportail_lu,
44
48
  :test
45
49
  ]
46
50
  end
@@ -82,6 +86,8 @@ module Geocoder
82
86
  #
83
87
  def spawn(name)
84
88
  if all_services.include?(name)
89
+ name = name.to_s
90
+ require "geocoder/lookups/#{name}"
85
91
  Geocoder::Lookup.const_get(classify_name(name)).new
86
92
  else
87
93
  valids = all_services.map(&:inspect).join(", ")
@@ -98,7 +104,3 @@ module Geocoder
98
104
  end
99
105
  end
100
106
  end
101
-
102
- Geocoder::Lookup.all_services.each do |name|
103
- require "geocoder/lookups/#{name}"
104
- end
@@ -4,6 +4,8 @@ require 'geocoder/results/geoip2'
4
4
  module Geocoder
5
5
  module Lookup
6
6
  class Geoip2 < Base
7
+ attr_reader :gem_name
8
+
7
9
  def initialize
8
10
  unless configuration[:file].nil?
9
11
  begin
@@ -12,6 +14,8 @@ module Geocoder
12
14
  rescue LoadError
13
15
  raise "Could not load Maxmind DB dependency. To use the GeoIP2 lookup you must add the #{@gem_name} gem to your Gemfile or have it installed in your system."
14
16
  end
17
+
18
+ @mmdb = db_class.new(configuration[:file].to_s)
15
19
  end
16
20
  super
17
21
  end
@@ -26,13 +30,14 @@ module Geocoder
26
30
 
27
31
  private
28
32
 
33
+ def db_class
34
+ gem_name == 'hive_geoip2' ? Hive::GeoIP2 : MaxMindDB
35
+ end
36
+
29
37
  def results(query)
30
38
  return [] unless configuration[:file]
31
- if @gem_name == 'hive_geoip2'
32
- result = Hive::GeoIP2.lookup(query.to_s, configuration[:file].to_s)
33
- else
34
- result = MaxMindDB.new(configuration[:file].to_s).lookup(query.to_s)
35
- end
39
+
40
+ result = @mmdb.lookup(query.to_s)
36
41
  result.nil? ? [] : [result]
37
42
  end
38
43
  end
@@ -0,0 +1,65 @@
1
+ require 'geocoder/lookups/base'
2
+ require "geocoder/results/geoportail_lu"
3
+
4
+ module Geocoder
5
+ module Lookup
6
+ class GeoportailLu < Base
7
+
8
+ def name
9
+ "Geoportail.lu"
10
+ end
11
+
12
+ def query_url(query)
13
+ url_base_path(query) + url_query_string(query)
14
+ end
15
+
16
+ private
17
+
18
+ def url_base_path(query)
19
+ query.reverse_geocode? ? reverse_geocode_url_base_path : search_url_base_path
20
+ end
21
+
22
+ def search_url_base_path
23
+ "#{protocol}://api.geoportail.lu/geocoder/search?"
24
+ end
25
+
26
+ def reverse_geocode_url_base_path
27
+ "#{protocol}://api.geoportail.lu/geocoder/reverseGeocode?"
28
+ end
29
+
30
+ def query_url_geoportail_lu_params(query)
31
+ query.reverse_geocode? ? reverse_geocode_params(query) : search_params(query)
32
+ end
33
+
34
+ def search_params(query)
35
+ {
36
+ queryString: query.sanitized_text
37
+ }
38
+ end
39
+
40
+ def reverse_geocode_params(query)
41
+ lat_lon = query.coordinates
42
+ {
43
+ lat: lat_lon.first,
44
+ lon: lat_lon.last
45
+ }
46
+ end
47
+
48
+ def query_url_params(query)
49
+ query_url_geoportail_lu_params(query).merge(super)
50
+ end
51
+
52
+ def results(query)
53
+ return [] unless doc = fetch_data(query)
54
+ if doc['success'] == true
55
+ result = doc['results']
56
+ else
57
+ result = []
58
+ raise_error(Geocoder::Error) ||
59
+ warn("Geportail.lu Geocoding API error")
60
+ end
61
+ result
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,53 @@
1
+ require 'geocoder/lookups/base'
2
+ require "geocoder/results/mapbox"
3
+
4
+ module Geocoder::Lookup
5
+ class Mapbox < Base
6
+
7
+ def name
8
+ "Mapbox"
9
+ end
10
+
11
+ def query_url(query)
12
+ "#{protocol}://api.mapbox.com/geocoding/v5/#{dataset}/#{url_query_string(query)}.json?access_token=#{configuration.api_key}"
13
+ end
14
+
15
+ private # ---------------------------------------------------------------
16
+
17
+ def results(query)
18
+ return [] unless data = fetch_data(query)
19
+ if data['features']
20
+ sort_relevant_feature(data['features'])
21
+ elsif data['message'] =~ /Invalid\sToken/
22
+ raise_error(Geocoder::InvalidApiKey, data['message'])
23
+ else
24
+ []
25
+ end
26
+ end
27
+
28
+ def url_query_string(query)
29
+ require 'cgi' unless defined?(CGI) && defined?(CGI.escape)
30
+ if query.reverse_geocode?
31
+ lat,lon = query.coordinates
32
+ "#{CGI.escape lon},#{CGI.escape lat}"
33
+ else
34
+ CGI.escape query.text.to_s
35
+ end
36
+ end
37
+
38
+ def dataset
39
+ configuration[:dataset] || "mapbox.places"
40
+ end
41
+
42
+ def supported_protocols
43
+ [:https]
44
+ end
45
+
46
+ def sort_relevant_feature(features)
47
+ # Sort by descending relevance; Favor original order for equal relevance (eg occurs for reverse geocoding)
48
+ features.sort_by do |feature|
49
+ [feature["relevance"],-features.index(feature)]
50
+ end.reverse
51
+ end
52
+ end
53
+ end
@@ -36,7 +36,7 @@ module Geocoder::Lookup
36
36
  addr = IPAddr.new(query.text).to_i
37
37
  q = "SELECT l.country, l.region, l.city, l.latitude, l.longitude
38
38
  FROM maxmind_geolite_city_location l WHERE l.loc_id = (SELECT b.loc_id FROM maxmind_geolite_city_blocks b
39
- WHERE b.start_ip_num <= #{addr} AND #{addr} <= b.end_ip_num LIMIT 1)"
39
+ WHERE b.start_ip_num <= #{addr} AND #{addr} <= b.end_ip_num)"
40
40
  format_result(q, [:country_name, :region_name, :city_name, :latitude, :longitude])
41
41
  elsif configuration[:package] == :country
42
42
  addr = IPAddr.new(query.text).to_i
@@ -8,13 +8,16 @@ module Geocoder::Lookup
8
8
  "Telize"
9
9
  end
10
10
 
11
+ def required_api_key_parts
12
+ ["key"]
13
+ end
14
+
11
15
  def query_url(query)
12
- "#{protocol}://www.telize.com/geoip/#{query.sanitized_text}"
16
+ "#{protocol}://telize-v1.p.mashape.com/geoip/#{query.sanitized_text}?mashape-key=#{api_key}"
13
17
  end
14
18
 
15
- # currently doesn't support HTTPS
16
19
  def supported_protocols
17
- [:http]
20
+ [:https]
18
21
  end
19
22
 
20
23
  private # ---------------------------------------------------------------
@@ -36,5 +39,9 @@ module Geocoder::Lookup
36
39
  def reserved_result(ip)
37
40
  {"message" => "Input string is not a valid IP address", "code" => 401}
38
41
  end
42
+
43
+ def api_key
44
+ configuration.api_key
45
+ end
39
46
  end
40
47
  end
@@ -4,12 +4,16 @@ module Geocoder::Result
4
4
  class Esri < Base
5
5
 
6
6
  def address
7
- address = reverse_geocode? ? 'Address' : 'Match_addr'
8
- attributes[address]
7
+ address_key = reverse_geocode? ? 'Address' : 'Match_addr'
8
+ attributes[address_key]
9
9
  end
10
10
 
11
11
  def city
12
- attributes['City']
12
+ if !reverse_geocode? && is_city?
13
+ place_name
14
+ else
15
+ attributes['City']
16
+ end
13
17
  end
14
18
 
15
19
  def state_code
@@ -19,8 +23,8 @@ module Geocoder::Result
19
23
  alias_method :state, :state_code
20
24
 
21
25
  def country
22
- country = reverse_geocode? ? "CountryCode" : "Country"
23
- attributes[country]
26
+ country_key = reverse_geocode? ? "CountryCode" : "Country"
27
+ attributes[country_key]
24
28
  end
25
29
 
26
30
  alias_method :country_code, :country
@@ -29,6 +33,15 @@ module Geocoder::Result
29
33
  attributes['Postal']
30
34
  end
31
35
 
36
+ def place_name
37
+ place_name_key = reverse_geocode? ? "Address" : "PlaceName"
38
+ attributes[place_name_key]
39
+ end
40
+
41
+ def place_type
42
+ reverse_geocode? ? "Address" : attributes['Type']
43
+ end
44
+
32
45
  def coordinates
33
46
  [geometry["y"], geometry["x"]]
34
47
  end
@@ -47,5 +60,8 @@ module Geocoder::Result
47
60
  @data['locations'].nil?
48
61
  end
49
62
 
63
+ def is_city?
64
+ ['City', 'State Capital', 'National Capital'].include?(place_type)
65
+ end
50
66
  end
51
- end
67
+ end
@@ -13,35 +13,35 @@ module Geocoder
13
13
  end
14
14
 
15
15
  def latitude
16
- data.fetch('location',{}).fetch('latitude',0.0)
16
+ data.fetch('location', {}).fetch('latitude', 0.0)
17
17
  end
18
18
 
19
19
  def longitude
20
- data.fetch('location',{}).fetch('longitude',0.0)
20
+ data.fetch('location', {}).fetch('longitude', 0.0)
21
21
  end
22
22
 
23
23
  def city
24
- data.fetch('city', {}).fetch('names', {}).fetch('en', '')
24
+ data.fetch('city', {}).fetch('names', {}).fetch(locale, '')
25
25
  end
26
26
 
27
27
  def state
28
- data.fetch('subdivisions',[]).fetch(0,{}).fetch('names',{}).fetch('en','')
28
+ data.fetch('subdivisions', []).fetch(0, {}).fetch('names', {}).fetch(locale, '')
29
29
  end
30
30
 
31
31
  def state_code
32
- data.fetch('subdivisions',[]).fetch(0,{}).fetch('iso_code','')
32
+ data.fetch('subdivisions', []).fetch(0, {}).fetch('iso_code', '')
33
33
  end
34
34
 
35
35
  def country
36
- data.fetch('country', {}).fetch('names',{}).fetch('en','')
36
+ data.fetch('country', {}).fetch('names', {}).fetch(locale, '')
37
37
  end
38
38
 
39
39
  def country_code
40
- data.fetch('country',{}).fetch('iso_code','')
40
+ data.fetch('country', {}).fetch('iso_code', '')
41
41
  end
42
42
 
43
43
  def postal_code
44
- data.fetch('postal',{}).fetch('code','')
44
+ data.fetch('postal', {}).fetch('code', '')
45
45
  end
46
46
 
47
47
  def self.response_attributes
@@ -59,6 +59,10 @@ module Geocoder
59
59
  def data
60
60
  @data.to_hash
61
61
  end
62
+
63
+ def locale
64
+ @locale ||= Geocoder.config[:language].to_s
65
+ end
62
66
  end
63
67
  end
64
68
  end
@@ -0,0 +1,69 @@
1
+ require 'geocoder/results/base'
2
+
3
+ module Geocoder::Result
4
+ class GeoportailLu < Base
5
+
6
+ def coordinates
7
+ geomlonlat['coordinates'].reverse if geolocalized?
8
+ end
9
+
10
+ def address
11
+ full_address
12
+ end
13
+
14
+ def city
15
+ try_to_extract 'locality', detailled_address
16
+ end
17
+
18
+ def state
19
+ 'Luxembourg'
20
+ end
21
+
22
+ def state_code
23
+ 'LU'
24
+ end
25
+
26
+ def postal_code
27
+ try_to_extract 'zip', detailled_address
28
+ end
29
+
30
+ def street_address
31
+ [street_number, street].compact.join(' ')
32
+ end
33
+
34
+ def street_number
35
+ try_to_extract 'postnumber', detailled_address
36
+ end
37
+
38
+ def street
39
+ try_to_extract 'street', detailled_address
40
+ end
41
+
42
+ def full_address
43
+ data['address']
44
+ end
45
+
46
+ def geomlonlat
47
+ data['geomlonlat']
48
+ end
49
+
50
+ def detailled_address
51
+ data['AddressDetails']
52
+ end
53
+
54
+ alias_method :country, :state
55
+ alias_method :province, :state
56
+ alias_method :country_code, :state_code
57
+ alias_method :province_code, :state_code
58
+
59
+ private
60
+
61
+ def geolocalized?
62
+ try_to_extract('coordinates', geomlonlat).present?
63
+ end
64
+
65
+ def try_to_extract(key, nullable_hash)
66
+ nullable_hash.try(:[], key)
67
+ end
68
+ end
69
+ end
@@ -120,5 +120,13 @@ module Geocoder::Result
120
120
  def precision
121
121
  geometry['location_type'] if geometry
122
122
  end
123
+
124
+ def partial_match
125
+ @data['partial_match']
126
+ end
127
+
128
+ def place_id
129
+ @data['place_id']
130
+ end
123
131
  end
124
132
  end
@@ -0,0 +1,55 @@
1
+ require 'geocoder/results/base'
2
+
3
+ module Geocoder::Result
4
+ class Mapbox < Base
5
+
6
+ def latitude
7
+ @latitude ||= @data["geometry"]["coordinates"].last.to_f
8
+ end
9
+
10
+ def longitude
11
+ @longitude ||= @data["geometry"]["coordinates"].first.to_f
12
+ end
13
+
14
+ def coordinates
15
+ [latitude, longitude]
16
+ end
17
+
18
+ def place_name
19
+ @data['text']
20
+ end
21
+
22
+ def street
23
+ @data['properties']['address']
24
+ end
25
+
26
+ def city
27
+ @data['context'].map { |c| c['text'] if c['id'] =~ /place/ }.compact.first
28
+ end
29
+
30
+ def state
31
+ @data['context'].map { |c| c['text'] if c['id'] =~ /region/ }.compact.first
32
+ end
33
+
34
+ alias_method :state_code, :state
35
+
36
+ def postal_code
37
+ @data['context'].map { |c| c['text'] if c['id'] =~ /postcode/ }.compact.first
38
+ end
39
+
40
+ def country
41
+ @data['context'].map { |c| c['text'] if c['id'] =~ /country/ }.compact.first
42
+ end
43
+
44
+ alias_method :country_code, :country
45
+
46
+ def neighborhood
47
+ @data['context'].map { |c| c['text'] if c['id'] =~ /neighborhood/ }.compact.first
48
+ end
49
+
50
+ def address
51
+ [place_name, street, city, state, postal_code, country].compact.join(", ")
52
+ end
53
+ end
54
+ end
55
+
@@ -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
@@ -11,38 +11,6 @@ module Geocoder::Store
11
11
  scope :not_geocoded, lambda {
12
12
  where(geocoder_options[:coordinates] => nil)
13
13
  }
14
-
15
- scope :near, lambda{ |location, *args|
16
- warn "DEPRECATION WARNING: The .near method will be removed for MongoDB-backed models in Geocoder 1.3.0. Please use MongoDB's built-in query language instead."
17
- coords = Geocoder::Calculations.extract_coordinates(location)
18
-
19
- # no results if no lat/lon given
20
- return where(:id => false) unless coords.is_a?(Array)
21
-
22
- radius = args.size > 0 ? args.shift : 20
23
- options = args.size > 0 ? args.shift : {}
24
- options[:units] ||= geocoder_options[:units]
25
-
26
- # Use BSON::OrderedHash if Ruby's hashes are unordered.
27
- # Conditions must be in order required by indexes (see mongo gem).
28
- version = RUBY_VERSION.split('.').map { |i| i.to_i }
29
- empty = version[0] < 2 && version[1] < 9 ? BSON::OrderedHash.new : {}
30
-
31
- conds = empty.clone
32
- field = geocoder_options[:coordinates]
33
- conds[field] = empty.clone
34
- conds[field]["$nearSphere"] = coords.reverse
35
-
36
- if radius
37
- conds[field]["$maxDistance"] = \
38
- Geocoder::Calculations.distance_to_radians(radius, options[:units])
39
- end
40
-
41
- if obj = options[:exclude]
42
- conds[:_id.ne] = obj.id
43
- end
44
- where(conds)
45
- }
46
14
  end
47
15
  end
48
16
 
@@ -56,18 +24,6 @@ module Geocoder::Store
56
24
  coords.is_a?(Array) ? coords.reverse : []
57
25
  end
58
26
 
59
- ##
60
- # Get nearby geocoded objects.
61
- # Takes the same options hash as the near class method (scope).
62
- # Returns nil if the object is not geocoded.
63
- #
64
- def nearbys(radius = 20, options = {})
65
- warn "DEPRECATION WARNING: The #nearbys method will be removed for MongoDB-backed models in Geocoder 1.3.0. Please use MongoDB's built-in query language instead."
66
- return nil unless geocoded?
67
- options.merge!(:exclude => self) unless send(self.class.primary_key).nil?
68
- self.class.near(self, radius, options)
69
- end
70
-
71
27
  ##
72
28
  # Look up coordinates and assign to +latitude+ and +longitude+ attributes
73
29
  # (or other as specified in +geocoded_by+). Returns coordinates (array).
@@ -1,3 +1,3 @@
1
1
  module Geocoder
2
- VERSION = "1.2.12"
2
+ VERSION = "1.3.0"
3
3
  end
@@ -4,13 +4,22 @@ namespace :geocode do
4
4
  class_name = ENV['CLASS'] || ENV['class']
5
5
  sleep_timer = ENV['SLEEP'] || ENV['sleep']
6
6
  batch = ENV['BATCH'] || ENV['batch']
7
+ reverse = ENV['REVERSE'] || ENV['reverse']
7
8
  raise "Please specify a CLASS (model)" unless class_name
8
9
  klass = class_from_string(class_name)
9
10
  batch = batch.to_i unless batch.nil?
11
+ reverse = false unless reverse.to_s.downcase == 'true'
10
12
 
11
- klass.not_geocoded.find_each(batch_size: batch) do |obj|
12
- obj.geocode; obj.save
13
- sleep(sleep_timer.to_f) unless sleep_timer.nil?
13
+ if reverse
14
+ klass.not_reverse_geocoded.find_each(batch_size: batch) do |obj|
15
+ obj.reverse_geocode; obj.save
16
+ sleep(sleep_timer.to_f) unless sleep_timer.nil?
17
+ end
18
+ else
19
+ klass.not_geocoded.find_each(batch_size: batch) do |obj|
20
+ obj.geocode; obj.save
21
+ sleep(sleep_timer.to_f) unless sleep_timer.nil?
22
+ end
14
23
  end
15
24
  end
16
25
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geocoder
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.12
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Reisner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-29 00:00:00.000000000 Z
11
+ date: 2016-01-31 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Provides object geocoding (by street or IP address), reverse geocoding
14
14
  (coordinates to street address), distance queries for ActiveRecord and Mongoid,
@@ -57,10 +57,12 @@ files:
57
57
  - lib/geocoder/lookups/geocoder_us.rb
58
58
  - lib/geocoder/lookups/geocodio.rb
59
59
  - lib/geocoder/lookups/geoip2.rb
60
+ - lib/geocoder/lookups/geoportail_lu.rb
60
61
  - lib/geocoder/lookups/google.rb
61
62
  - lib/geocoder/lookups/google_places_details.rb
62
63
  - lib/geocoder/lookups/google_premier.rb
63
64
  - lib/geocoder/lookups/here.rb
65
+ - lib/geocoder/lookups/mapbox.rb
64
66
  - lib/geocoder/lookups/mapquest.rb
65
67
  - lib/geocoder/lookups/maxmind.rb
66
68
  - lib/geocoder/lookups/maxmind_geoip2.rb
@@ -95,10 +97,12 @@ files:
95
97
  - lib/geocoder/results/geocoder_us.rb
96
98
  - lib/geocoder/results/geocodio.rb
97
99
  - lib/geocoder/results/geoip2.rb
100
+ - lib/geocoder/results/geoportail_lu.rb
98
101
  - lib/geocoder/results/google.rb
99
102
  - lib/geocoder/results/google_places_details.rb
100
103
  - lib/geocoder/results/google_premier.rb
101
104
  - lib/geocoder/results/here.rb
105
+ - lib/geocoder/results/mapbox.rb
102
106
  - lib/geocoder/results/mapquest.rb
103
107
  - lib/geocoder/results/maxmind.rb
104
108
  - lib/geocoder/results/maxmind_geoip2.rb
@@ -146,7 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
146
150
  version: '0'
147
151
  requirements: []
148
152
  rubyforge_project:
149
- rubygems_version: 2.4.5
153
+ rubygems_version: 2.5.1
150
154
  signing_key:
151
155
  specification_version: 4
152
156
  summary: Complete geocoding solution for Ruby.