geocoder 1.5.0 → 1.6.7
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 +53 -2
- data/LICENSE +1 -1
- data/README.md +23 -46
- data/bin/console +13 -0
- data/examples/autoexpire_cache_redis.rb +2 -0
- data/lib/easting_northing.rb +171 -0
- data/lib/geocoder/cache.rb +4 -0
- data/lib/geocoder/calculations.rb +1 -1
- data/lib/geocoder/configuration.rb +2 -1
- data/lib/geocoder/configuration_hash.rb +4 -4
- data/lib/geocoder/ip_address.rb +15 -1
- data/lib/geocoder/lookup.rb +9 -4
- data/lib/geocoder/lookups/abstract_api.rb +46 -0
- data/lib/geocoder/lookups/baidu_ip.rb +1 -1
- data/lib/geocoder/lookups/ban_data_gouv_fr.rb +14 -1
- data/lib/geocoder/lookups/base.rb +7 -2
- data/lib/geocoder/lookups/bing.rb +2 -1
- data/lib/geocoder/lookups/esri.rb +44 -13
- data/lib/geocoder/lookups/freegeoip.rb +7 -7
- data/lib/geocoder/lookups/geocodio.rb +1 -1
- data/lib/geocoder/lookups/google.rb +7 -2
- data/lib/geocoder/lookups/google_places_details.rb +8 -14
- data/lib/geocoder/lookups/google_places_search.rb +28 -2
- data/lib/geocoder/lookups/google_premier.rb +4 -0
- data/lib/geocoder/lookups/here.rb +28 -22
- data/lib/geocoder/lookups/ip2location.rb +7 -14
- data/lib/geocoder/lookups/ipapi_com.rb +2 -1
- data/lib/geocoder/lookups/ipdata_co.rb +5 -4
- data/lib/geocoder/lookups/ipgeolocation.rb +51 -0
- data/lib/geocoder/lookups/ipinfo_io.rb +2 -11
- data/lib/geocoder/lookups/ipregistry.rb +68 -0
- data/lib/geocoder/lookups/ipstack.rb +2 -2
- data/lib/geocoder/lookups/latlon.rb +1 -2
- data/lib/geocoder/lookups/maxmind.rb +2 -2
- data/lib/geocoder/lookups/maxmind_geoip2.rb +4 -7
- data/lib/geocoder/lookups/maxmind_local.rb +7 -1
- data/lib/geocoder/lookups/nationaal_georegister_nl.rb +38 -0
- data/lib/geocoder/lookups/osmnames.rb +57 -0
- data/lib/geocoder/lookups/pelias.rb +2 -3
- data/lib/geocoder/lookups/pickpoint.rb +1 -1
- data/lib/geocoder/lookups/pointpin.rb +3 -3
- data/lib/geocoder/lookups/smarty_streets.rb +19 -4
- data/lib/geocoder/lookups/telize.rb +3 -3
- data/lib/geocoder/lookups/tencent.rb +59 -0
- data/lib/geocoder/lookups/test.rb +4 -0
- data/lib/geocoder/lookups/uk_ordnance_survey_names.rb +59 -0
- data/lib/geocoder/lookups/yandex.rb +3 -4
- data/lib/geocoder/query.rb +14 -0
- data/lib/geocoder/railtie.rb +1 -1
- data/lib/geocoder/results/abstract_api.rb +146 -0
- data/lib/geocoder/results/baidu.rb +0 -4
- data/lib/geocoder/results/ban_data_gouv_fr.rb +27 -2
- data/lib/geocoder/results/db_ip_com.rb +1 -1
- data/lib/geocoder/results/here.rb +4 -1
- data/lib/geocoder/results/ipgeolocation.rb +59 -0
- data/lib/geocoder/results/ipregistry.rb +304 -0
- data/lib/geocoder/results/nationaal_georegister_nl.rb +62 -0
- data/lib/geocoder/results/nominatim.rb +4 -0
- data/lib/geocoder/results/osmnames.rb +56 -0
- data/lib/geocoder/results/smarty_streets.rb +48 -18
- data/lib/geocoder/results/tencent.rb +72 -0
- data/lib/geocoder/results/uk_ordnance_survey_names.rb +59 -0
- data/lib/geocoder/results/yandex.rb +217 -59
- data/lib/geocoder/sql.rb +4 -4
- data/lib/geocoder/stores/active_record.rb +1 -1
- data/lib/geocoder/util.rb +29 -0
- data/lib/geocoder/version.rb +1 -1
- data/lib/maxmind_database.rb +3 -3
- metadata +24 -18
- data/lib/geocoder/lookups/geocoder_us.rb +0 -51
- data/lib/geocoder/lookups/mapzen.rb +0 -15
- data/lib/geocoder/results/geocoder_us.rb +0 -39
- data/lib/geocoder/results/mapzen.rb +0 -5
- data/lib/hash_recursive_merge.rb +0 -74
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require 'singleton'
|
|
2
2
|
require 'geocoder/configuration_hash'
|
|
3
|
+
require 'geocoder/util'
|
|
3
4
|
|
|
4
5
|
module Geocoder
|
|
5
6
|
|
|
@@ -85,7 +86,7 @@ module Geocoder
|
|
|
85
86
|
end
|
|
86
87
|
|
|
87
88
|
def configure(options)
|
|
88
|
-
@data
|
|
89
|
+
Util.recursive_hash_merge(@data, options)
|
|
89
90
|
end
|
|
90
91
|
|
|
91
92
|
def initialize # :nodoc
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
require 'hash_recursive_merge'
|
|
2
|
-
|
|
3
1
|
module Geocoder
|
|
4
2
|
class ConfigurationHash < Hash
|
|
5
|
-
include HashRecursiveMerge
|
|
6
|
-
|
|
7
3
|
def method_missing(meth, *args, &block)
|
|
8
4
|
has_key?(meth) ? self[meth] : super
|
|
9
5
|
end
|
|
6
|
+
|
|
7
|
+
def respond_to_missing?(meth, include_private = false)
|
|
8
|
+
has_key?(meth) || super
|
|
9
|
+
end
|
|
10
10
|
end
|
|
11
11
|
end
|
data/lib/geocoder/ip_address.rb
CHANGED
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
require 'resolv'
|
|
2
2
|
module Geocoder
|
|
3
3
|
class IpAddress < String
|
|
4
|
+
PRIVATE_IPS = [
|
|
5
|
+
'10.0.0.0/8',
|
|
6
|
+
'172.16.0.0/12',
|
|
7
|
+
'192.168.0.0/16',
|
|
8
|
+
].map { |ip| IPAddr.new(ip) }.freeze
|
|
9
|
+
|
|
10
|
+
def internal?
|
|
11
|
+
loopback? || private?
|
|
12
|
+
end
|
|
4
13
|
|
|
5
14
|
def loopback?
|
|
6
15
|
valid? and !!(self == "0.0.0.0" or self.match(/\A127\./) or self == "::1")
|
|
7
16
|
end
|
|
8
17
|
|
|
18
|
+
def private?
|
|
19
|
+
valid? && PRIVATE_IPS.any? { |ip| ip.include?(self) }
|
|
20
|
+
end
|
|
21
|
+
|
|
9
22
|
def valid?
|
|
10
|
-
|
|
23
|
+
ip = self[/(?<=\[)(.*?)(?=\])/] || self
|
|
24
|
+
!!((ip =~ Resolv::IPv4::Regex) || (ip =~ Resolv::IPv6::Regex))
|
|
11
25
|
end
|
|
12
26
|
end
|
|
13
27
|
end
|
data/lib/geocoder/lookup.rb
CHANGED
|
@@ -32,17 +32,18 @@ module Geocoder
|
|
|
32
32
|
:google_places_search,
|
|
33
33
|
:bing,
|
|
34
34
|
:geocoder_ca,
|
|
35
|
-
:geocoder_us,
|
|
36
35
|
:yandex,
|
|
36
|
+
:nationaal_georegister_nl,
|
|
37
37
|
:nominatim,
|
|
38
38
|
:mapbox,
|
|
39
39
|
:mapquest,
|
|
40
|
-
:
|
|
40
|
+
:uk_ordnance_survey_names,
|
|
41
41
|
:opencagedata,
|
|
42
42
|
:pelias,
|
|
43
43
|
:pickpoint,
|
|
44
44
|
:here,
|
|
45
45
|
:baidu,
|
|
46
|
+
:tencent,
|
|
46
47
|
:geocodio,
|
|
47
48
|
:smarty_streets,
|
|
48
49
|
:postcode_anywhere_uk,
|
|
@@ -51,7 +52,8 @@ module Geocoder
|
|
|
51
52
|
:ban_data_gouv_fr,
|
|
52
53
|
:test,
|
|
53
54
|
:latlon,
|
|
54
|
-
:amap
|
|
55
|
+
:amap,
|
|
56
|
+
:osmnames
|
|
55
57
|
]
|
|
56
58
|
end
|
|
57
59
|
|
|
@@ -61,6 +63,7 @@ module Geocoder
|
|
|
61
63
|
def ip_services
|
|
62
64
|
@ip_services ||= [
|
|
63
65
|
:baidu_ip,
|
|
66
|
+
:abstract_api,
|
|
64
67
|
:freegeoip,
|
|
65
68
|
:geoip2,
|
|
66
69
|
:maxmind,
|
|
@@ -69,11 +72,13 @@ module Geocoder
|
|
|
69
72
|
:pointpin,
|
|
70
73
|
:maxmind_geoip2,
|
|
71
74
|
:ipinfo_io,
|
|
75
|
+
:ipregistry,
|
|
72
76
|
:ipapi_com,
|
|
73
77
|
:ipdata_co,
|
|
74
78
|
:db_ip_com,
|
|
75
79
|
:ipstack,
|
|
76
|
-
:ip2location
|
|
80
|
+
:ip2location,
|
|
81
|
+
:ipgeolocation
|
|
77
82
|
]
|
|
78
83
|
end
|
|
79
84
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'geocoder/lookups/base'
|
|
4
|
+
require 'geocoder/results/abstract_api'
|
|
5
|
+
|
|
6
|
+
module Geocoder::Lookup
|
|
7
|
+
class AbstractApi < Base
|
|
8
|
+
|
|
9
|
+
def name
|
|
10
|
+
"Abstract API"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def required_api_key_parts
|
|
14
|
+
['api_key']
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def supported_protocols
|
|
18
|
+
[:https]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private # ---------------------------------------------------------------
|
|
22
|
+
|
|
23
|
+
def base_query_url(query)
|
|
24
|
+
"#{protocol}://ipgeolocation.abstractapi.com/v1/?"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def query_url_params(query)
|
|
28
|
+
params = {api_key: configuration.api_key}
|
|
29
|
+
|
|
30
|
+
ip_address = query.sanitized_text
|
|
31
|
+
if ip_address.is_a?(String) && ip_address.length > 0
|
|
32
|
+
params[:ip_address] = ip_address
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
params.merge(super)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def results(query, reverse = false)
|
|
39
|
+
if doc = fetch_data(query)
|
|
40
|
+
[doc]
|
|
41
|
+
else
|
|
42
|
+
[]
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -22,7 +22,7 @@ module Geocoder::Lookup
|
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def any_result?(doc)
|
|
25
|
-
doc['features'].any?
|
|
25
|
+
doc['features'] and doc['features'].any?
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def results(query)
|
|
@@ -86,6 +86,12 @@ module Geocoder::Lookup
|
|
|
86
86
|
unless (citycode = query.options[:citycode]).nil? || !code_param_is_valid?(citycode)
|
|
87
87
|
params[:citycode] = citycode.to_s
|
|
88
88
|
end
|
|
89
|
+
unless (lat = query.options[:lat]).nil? || !latitude_is_valid?(lat)
|
|
90
|
+
params[:lat] = lat
|
|
91
|
+
end
|
|
92
|
+
unless (lon = query.options[:lon]).nil? || !longitude_is_valid?(lon)
|
|
93
|
+
params[:lon] = lon
|
|
94
|
+
end
|
|
89
95
|
params
|
|
90
96
|
end
|
|
91
97
|
|
|
@@ -126,5 +132,12 @@ module Geocoder::Lookup
|
|
|
126
132
|
(1..99999).include?(param.to_i)
|
|
127
133
|
end
|
|
128
134
|
|
|
135
|
+
def latitude_is_valid?(param)
|
|
136
|
+
param.to_f <= 90 && param.to_f >= -90
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def longitude_is_valid?(param)
|
|
140
|
+
param.to_f <= 180 && param.to_f >= -180
|
|
141
|
+
end
|
|
129
142
|
end
|
|
130
143
|
end
|
|
@@ -164,7 +164,7 @@ module Geocoder
|
|
|
164
164
|
def cache_key_params(query)
|
|
165
165
|
# omit api_key and token because they may vary among requests
|
|
166
166
|
query_url_params(query).reject do |key,value|
|
|
167
|
-
key.to_s.match
|
|
167
|
+
key.to_s.match(/(key|token)/)
|
|
168
168
|
end
|
|
169
169
|
end
|
|
170
170
|
|
|
@@ -197,6 +197,8 @@ module Geocoder
|
|
|
197
197
|
raise_error(err) or Geocoder.log(:warn, "Geocoding API connection cannot be established.")
|
|
198
198
|
rescue Errno::ECONNREFUSED => err
|
|
199
199
|
raise_error(err) or Geocoder.log(:warn, "Geocoding API connection refused.")
|
|
200
|
+
rescue Geocoder::NetworkError => err
|
|
201
|
+
raise_error(err) or Geocoder.log(:warn, "Geocoding API connection is either unreacheable or reset by the peer")
|
|
200
202
|
rescue Timeout::Error => err
|
|
201
203
|
raise_error(err) or Geocoder.log(:warn, "Geocoding API not responding fast enough " +
|
|
202
204
|
"(use Geocoder.configure(:timeout => ...) to set limit).")
|
|
@@ -209,7 +211,10 @@ module Geocoder
|
|
|
209
211
|
JSON.parse(data)
|
|
210
212
|
end
|
|
211
213
|
rescue
|
|
212
|
-
raise_error(ResponseParseError.new(data))
|
|
214
|
+
unless raise_error(ResponseParseError.new(data))
|
|
215
|
+
Geocoder.log(:warn, "Geocoding API's response was not valid JSON")
|
|
216
|
+
Geocoder.log(:debug, "Raw response: #{data}")
|
|
217
|
+
end
|
|
213
218
|
end
|
|
214
219
|
|
|
215
220
|
##
|
|
@@ -9,6 +9,10 @@ module Geocoder::Lookup
|
|
|
9
9
|
"Esri"
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
+
def supported_protocols
|
|
13
|
+
[:https]
|
|
14
|
+
end
|
|
15
|
+
|
|
12
16
|
private # ---------------------------------------------------------------
|
|
13
17
|
|
|
14
18
|
def base_query_url(query)
|
|
@@ -40,31 +44,58 @@ module Geocoder::Lookup
|
|
|
40
44
|
else
|
|
41
45
|
params[:text] = query.sanitized_text
|
|
42
46
|
end
|
|
43
|
-
|
|
44
|
-
params[:
|
|
47
|
+
|
|
48
|
+
params[:token] = token(query)
|
|
49
|
+
|
|
50
|
+
if for_storage_value = for_storage(query)
|
|
51
|
+
params[:forStorage] = for_storage_value
|
|
52
|
+
end
|
|
45
53
|
params[:sourceCountry] = configuration[:source_country] if configuration[:source_country]
|
|
54
|
+
params[:preferredLabelValues] = configuration[:preferred_label_values] if configuration[:preferred_label_values]
|
|
55
|
+
|
|
46
56
|
params.merge(super)
|
|
47
57
|
end
|
|
48
58
|
|
|
49
|
-
def
|
|
50
|
-
|
|
51
|
-
|
|
59
|
+
def for_storage(query)
|
|
60
|
+
if query.options.has_key?(:for_storage)
|
|
61
|
+
query.options[:for_storage]
|
|
62
|
+
else
|
|
63
|
+
configuration[:for_storage]
|
|
64
|
+
end
|
|
52
65
|
end
|
|
53
66
|
|
|
54
|
-
def
|
|
55
|
-
|
|
67
|
+
def token(query)
|
|
68
|
+
token_instance = if query.options[:token]
|
|
69
|
+
query.options[:token]
|
|
70
|
+
else
|
|
71
|
+
configuration[:token]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
if !valid_token_configured?(token_instance) && configuration.api_key
|
|
75
|
+
token_instance = create_and_save_token!(query)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
token_instance.to_s unless token_instance.nil?
|
|
56
79
|
end
|
|
57
80
|
|
|
58
|
-
def
|
|
59
|
-
|
|
81
|
+
def valid_token_configured?(token_instance)
|
|
82
|
+
!token_instance.nil? && token_instance.active?
|
|
60
83
|
end
|
|
61
84
|
|
|
62
|
-
def
|
|
63
|
-
|
|
85
|
+
def create_and_save_token!(query)
|
|
86
|
+
token_instance = create_token
|
|
87
|
+
|
|
88
|
+
if query.options[:token]
|
|
89
|
+
query.options[:token] = token_instance
|
|
90
|
+
else
|
|
91
|
+
Geocoder.merge_into_lookup_config(:esri, token: token_instance)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
token_instance
|
|
64
95
|
end
|
|
65
96
|
|
|
66
|
-
def
|
|
67
|
-
Geocoder.
|
|
97
|
+
def create_token
|
|
98
|
+
Geocoder::EsriToken.generate_token(*configuration.api_key)
|
|
68
99
|
end
|
|
69
100
|
end
|
|
70
101
|
end
|
|
@@ -7,10 +7,10 @@ module Geocoder::Lookup
|
|
|
7
7
|
def name
|
|
8
8
|
"FreeGeoIP"
|
|
9
9
|
end
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
def supported_protocols
|
|
12
12
|
if configuration[:host]
|
|
13
|
-
[:
|
|
13
|
+
[:https]
|
|
14
14
|
else
|
|
15
15
|
# use https for default host
|
|
16
16
|
[:https]
|
|
@@ -32,8 +32,8 @@ module Geocoder::Lookup
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def results(query)
|
|
35
|
-
# don't look up a loopback address, just return the stored result
|
|
36
|
-
return [reserved_result(query.text)] if query.
|
|
35
|
+
# don't look up a loopback or private address, just return the stored result
|
|
36
|
+
return [reserved_result(query.text)] if query.internal_ip_address?
|
|
37
37
|
# note: Freegeoip.net returns plain text "Not Found" on bad request
|
|
38
38
|
(doc = fetch_data(query)) ? [doc] : []
|
|
39
39
|
end
|
|
@@ -44,8 +44,8 @@ module Geocoder::Lookup
|
|
|
44
44
|
"city" => "",
|
|
45
45
|
"region_code" => "",
|
|
46
46
|
"region_name" => "",
|
|
47
|
-
"
|
|
48
|
-
"
|
|
47
|
+
"metro_code" => "",
|
|
48
|
+
"zip_code" => "",
|
|
49
49
|
"latitude" => "0",
|
|
50
50
|
"longitude" => "0",
|
|
51
51
|
"country_name" => "Reserved",
|
|
@@ -54,7 +54,7 @@ module Geocoder::Lookup
|
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
def host
|
|
57
|
-
configuration[:host] || "freegeoip.
|
|
57
|
+
configuration[:host] || "freegeoip.app"
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
60
|
end
|
|
@@ -44,10 +44,15 @@ module Geocoder::Lookup
|
|
|
44
44
|
super(response) and ['OK', 'ZERO_RESULTS'].include?(status)
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
+
def result_root_attr
|
|
48
|
+
'results'
|
|
49
|
+
end
|
|
50
|
+
|
|
47
51
|
def results(query)
|
|
48
52
|
return [] unless doc = fetch_data(query)
|
|
49
|
-
case doc['status']
|
|
50
|
-
|
|
53
|
+
case doc['status']
|
|
54
|
+
when "OK" # OK status implies >0 results
|
|
55
|
+
return doc[result_root_attr]
|
|
51
56
|
when "OVER_QUERY_LIMIT"
|
|
52
57
|
raise_error(Geocoder::OverQueryLimitError) ||
|
|
53
58
|
Geocoder.log(:warn, "#{name} API error: over query limit.")
|
|
@@ -22,21 +22,15 @@ module Geocoder
|
|
|
22
22
|
"#{protocol}://maps.googleapis.com/maps/api/place/details/json?"
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
def result_root_attr
|
|
26
|
+
'result'
|
|
27
|
+
end
|
|
28
|
+
|
|
25
29
|
def results(query)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return [doc["result"]]
|
|
31
|
-
when "OVER_QUERY_LIMIT"
|
|
32
|
-
raise_error(Geocoder::OverQueryLimitError) || Geocoder.log(:warn, "Google Places Details API error: over query limit.")
|
|
33
|
-
when "REQUEST_DENIED"
|
|
34
|
-
raise_error(Geocoder::RequestDenied) || Geocoder.log(:warn, "Google Places Details API error: request denied.")
|
|
35
|
-
when "INVALID_REQUEST"
|
|
36
|
-
raise_error(Geocoder::InvalidRequest) || Geocoder.log(:warn, "Google Places Details API error: invalid request.")
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
[]
|
|
30
|
+
result = super(query)
|
|
31
|
+
return [result] unless result.is_a? Array
|
|
32
|
+
|
|
33
|
+
result
|
|
40
34
|
end
|
|
41
35
|
|
|
42
36
|
def query_url_google_params(query)
|
|
@@ -18,16 +18,42 @@ module Geocoder
|
|
|
18
18
|
|
|
19
19
|
private
|
|
20
20
|
|
|
21
|
+
def result_root_attr
|
|
22
|
+
'candidates'
|
|
23
|
+
end
|
|
24
|
+
|
|
21
25
|
def base_query_url(query)
|
|
22
|
-
"#{protocol}://maps.googleapis.com/maps/api/place/
|
|
26
|
+
"#{protocol}://maps.googleapis.com/maps/api/place/findplacefromtext/json?"
|
|
23
27
|
end
|
|
24
28
|
|
|
25
29
|
def query_url_google_params(query)
|
|
26
30
|
{
|
|
27
|
-
|
|
31
|
+
input: query.text,
|
|
32
|
+
inputtype: 'textquery',
|
|
33
|
+
fields: fields(query),
|
|
28
34
|
language: query.language || configuration.language
|
|
29
35
|
}
|
|
30
36
|
end
|
|
37
|
+
|
|
38
|
+
def fields(query)
|
|
39
|
+
query_fields = query.options[:fields]
|
|
40
|
+
return format_fields(query_fields) if query_fields
|
|
41
|
+
|
|
42
|
+
default_fields
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def default_fields
|
|
46
|
+
legacy = %w[id reference]
|
|
47
|
+
basic = %w[business_status formatted_address geometry icon name
|
|
48
|
+
photos place_id plus_code types]
|
|
49
|
+
contact = %w[opening_hours]
|
|
50
|
+
atmosphere = %W[price_level rating user_ratings_total]
|
|
51
|
+
format_fields(legacy, basic, contact, atmosphere)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def format_fields(*fields)
|
|
55
|
+
fields.flatten.join(',')
|
|
56
|
+
end
|
|
31
57
|
end
|
|
32
58
|
end
|
|
33
59
|
end
|