Google 地图 - 将其设置为与 Rails 一起使用 5 - 地理编码器不是地理编码
Google maps - setting it up to work with Rails 5 - geocoder not geocoding
我已经尝试了 4 年多,试图找出一种在我的 Rails 应用程序中使用 google 地图的方法。我目前正在尝试 Rails 5.
我最近 post 编辑了这篇求救信。我收到的建议对我没有用,所以我现在再次尝试看看是否有人可能知道一些事情。
我有组织和地址模型。
协会是:
组织
has_many :addresses, as: :addressable
accepts_nested_attributes_for :addresses, reject_if: :all_blank, allow_destroy: true
地址
belongs_to :addressable, :polymorphic => true, optional: true
我不再尝试使用 gmaps4rails gem 来解决这个问题。我从我的 gem 文件中删除了它。不过我还有地理编码器 gem。
在我的地址控制器中,我有
def index
@addresses = Address.all
end
def show
end
在我的组织控制器中,我有
def index
@organisations = Organisation.all
authorize @organisations
end
def show
@addresses = @organisation.addresses.all
end
在我的组织视图中,我有
<%= render 'contacts/addresses/map' %>
在我的地址视图中,我有
<%= javascript_tag do %>
var addresses = <%= raw @addresses.to_json %>;
<% end %>
<script src="https://maps.googleapis.com/maps/api/js?key=<%= ENV["GOOGLE_MAPS_API_KEY"] %>&callback=initMap"
async defer></script>
在我的address.js中,我有
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4
});
var bounds = new google.maps.LatLngBounds();
var n = addresses.length;
for (var i = 0; i < n; i++) {
var address = new google.maps.Marker({
position: {lat: parseFloat(addresses[i].latitude), lng: parseFloat(addresses[i].longitude)},
title: addresses[i].name,
map: map
});
bounds.extend(address.position);
}
map.fitBounds(bounds);
}
虽然缩放设置似乎不起作用,但如果我从控制台设置纬度和经度字段,这实际上会呈现地图。
如果我不在控制台中手动设置这些字段,我会收到一条错误消息:
js?key=.....&callback=initMap:42 Uncaught RangeError: Maximum call stack size exceeded
这post Uncaught RangeError: Maximum call stack size exceeded Google maps when I try to set bounds表明问题是由于lat/lng坐标没有传递给js造成的。这解释了我的问题,因为我的控制台显示这些属性被保存为 nil。
在我的地址模型中我有:
class Address < ApplicationRecord
geocoded_by :full_address # can also be an IP address
# --------------- associations
belongs_to :addressable, :polymorphic => true, optional: true
# --------------- scopes
# --------------- validations
# --------------- class methods
def unit_line
if self.unit.present?
['Unit', unit.titlecase].join(' ')
end
end
def first_line
[street_number, street.titlecase].join(' ')
end
def middle_line
if self.building.present?
['Building', building.titlecase].join(' ')
end
end
def last_line
[city.titlecase, region.upcase, zip].join(' ')
end
# def country_name
# # self.country = ISO3166::Country[country]
# # country.translations[I18n.locale.to_s] || country.name
# # iso_country = ISO3166::Country.find_by_name(country) # `country` should be name like 'Australia'
# # iso_country.translations[I18n.locale.to_s] || iso_country.name
# end
# def country_name
# self.country = ISO3166::Country[country]
# country.translations[I18n.locale.to_s] || country.name
# end
def country_name
country = self.country
ISO3166::Country[country]
end
def full_address
[self.unit_line, first_line, middle_line, last_line, country_name].compact.join("<br>").html_safe
end
# --------------- callbacks
after_create :geocode#, if self.full_address.changed?
我也试过:
after_validation :geocode
# --------------- instance methods
# --------------- private methods
end
我的地址 table 具有纬度和经度的十进制属性。我正在使用地理编码器 gem 并希望在创建后对地址进行地理编码。
我有一个 geocoder.rb 的初始化器:
Geocoder.configure(
# Geocoding options
:timeout => 3, # geocoding service timeout (secs)
:lookup => :google, # name of geocoding service (symbol)
:language => :en, # ISO-639 language code
:use_https => true, # use HTTPS for lookup requests? (if supported)
# :http_proxy => nil, # HTTP proxy server (user:pass@host:port)
# :https_proxy => nil, # HTTPS proxy server (user:pass@host:port)
:api_key => nil, # API key for geocoding service
# :cache => nil, # cache object (must respond to #[], #[]=, and #keys)
# :cache_prefix => "geocoder:", # prefix (string) to use for all cache keys
# exceptions that should not be rescued by default
# (if you want to implement custom error handling);
# supports SocketError and TimeoutError
# :always_raise => [],
# calculation options
:units => :km, # :km for kilometers or :mi for miles
# :distances => :linear # :spherical or :linear
)
任何人都可以看到我需要做什么才能让它工作吗?
尽管对我的 address.rb 进行了验证后请求地理编码,但我的 lat/lng 属性没有更新坐标。
控制台输出
a = Address.first
Address Load (30.2ms) SELECT "addresses".* FROM "addresses" ORDER BY "addresses"."id" ASC LIMIT [["LIMIT", 1]]
=> #<Address id: 8, unit: "16", building: "asdf", street_number: "15", street: "Johnston Street", city: "Balmain East", region: "NSW", zip: "2041", country: "AU", time_zone: "Midway Island", addressable_id: 1, addressable_type: "Organisation", description: "registered_office", created_at: "2016-11-10 00:16:50", updated_at: "2016-11-10 00:16:50", latitude: nil, longitude: nil>
Eric 的建议
我尝试采纳 Eric 的建议来触发地理编码,但它没有更新 lat/lng 坐标。
Address.where(latitude: nil).or(Address.where(longitude: nil)).each{|marker| marker.save}
Address Load (16.3ms) SELECT "addresses".* FROM "addresses" WHERE ("addresses"."latitude" IS NULL OR "addresses"."longitude" IS NULL)
(2.0ms) BEGIN
(0.8ms) COMMIT
=> [#<Address id: 8, unit: "1", building: "asdf", street_number: "10", street: "Darling Street", city: "Balmain", region: "NSW", zip: "2041", country: "AU", time_zone: "Midway Island", addressable_id: 1, addressable_type: "Organisation", description: "registered_office", created_at: "2016-11-10 00:16:50", updated_at: "2016-11-10 00:16:50", latitude: nil, longitude: nil>]
像往常一样,从简单开始,慢慢添加更多代码。
我使用了之前 .
中的基本 Rails 应用程序
我将 gem 'geocoder'
添加到 Gemfile。
在bundle install
之后,我添加了
geocoded_by :name # can also be an IP address
after_validation :geocode
到我的标记 class,它已经将纬度和经度定义为 :decimal 属性。
在rails c
中:
Marker.create(:name => 'New Dehli')
Marker.create(:name => 'New-York')
完成,它们出现在地图上了!
注意:如果由于某种原因某些标记没有坐标,地图将不会显示,您将在 js 控制台中收到 "too much recursion" 错误。
为避免这种情况,您可以通过在模型中启用 after_validation :geocode
并在控制台中启动它来确保所有标记都有坐标:
Marker.where(latitude: nil).or(Marker.where(longitude: nil)).each{|marker| marker.save}
保存标记会触发验证,而验证会触发地理编码。
如果出于某种原因您仍然有非地理编码标记,请将您的 js 更改为:
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4
});
var bounds = new google.maps.LatLngBounds();
var n = markers.length;
for (var i = 0; i < n; i++) {
var lat = markers[i].latitude;
var lng = markers[i].longitude;
if (lat == null || lng ==null){
console.log(markers[i].name + " doesn't have coordinates");
}else {
var marker = new google.maps.Marker({
position: {lat: parseFloat(lat), lng: parseFloat(lng)},
title: markers[i].name,
map: map
});
bounds.extend(marker.position);
}
}
map.fitBounds(bounds);
}
我已经尝试了 4 年多,试图找出一种在我的 Rails 应用程序中使用 google 地图的方法。我目前正在尝试 Rails 5.
我最近 post 编辑了这篇求救信。我收到的建议对我没有用,所以我现在再次尝试看看是否有人可能知道一些事情。
我有组织和地址模型。
协会是:
组织
has_many :addresses, as: :addressable
accepts_nested_attributes_for :addresses, reject_if: :all_blank, allow_destroy: true
地址
belongs_to :addressable, :polymorphic => true, optional: true
我不再尝试使用 gmaps4rails gem 来解决这个问题。我从我的 gem 文件中删除了它。不过我还有地理编码器 gem。
在我的地址控制器中,我有
def index
@addresses = Address.all
end
def show
end
在我的组织控制器中,我有
def index
@organisations = Organisation.all
authorize @organisations
end
def show
@addresses = @organisation.addresses.all
end
在我的组织视图中,我有
<%= render 'contacts/addresses/map' %>
在我的地址视图中,我有
<%= javascript_tag do %>
var addresses = <%= raw @addresses.to_json %>;
<% end %>
<script src="https://maps.googleapis.com/maps/api/js?key=<%= ENV["GOOGLE_MAPS_API_KEY"] %>&callback=initMap"
async defer></script>
在我的address.js中,我有
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4
});
var bounds = new google.maps.LatLngBounds();
var n = addresses.length;
for (var i = 0; i < n; i++) {
var address = new google.maps.Marker({
position: {lat: parseFloat(addresses[i].latitude), lng: parseFloat(addresses[i].longitude)},
title: addresses[i].name,
map: map
});
bounds.extend(address.position);
}
map.fitBounds(bounds);
}
虽然缩放设置似乎不起作用,但如果我从控制台设置纬度和经度字段,这实际上会呈现地图。
如果我不在控制台中手动设置这些字段,我会收到一条错误消息:
js?key=.....&callback=initMap:42 Uncaught RangeError: Maximum call stack size exceeded
这post Uncaught RangeError: Maximum call stack size exceeded Google maps when I try to set bounds表明问题是由于lat/lng坐标没有传递给js造成的。这解释了我的问题,因为我的控制台显示这些属性被保存为 nil。
在我的地址模型中我有:
class Address < ApplicationRecord
geocoded_by :full_address # can also be an IP address
# --------------- associations
belongs_to :addressable, :polymorphic => true, optional: true
# --------------- scopes
# --------------- validations
# --------------- class methods
def unit_line
if self.unit.present?
['Unit', unit.titlecase].join(' ')
end
end
def first_line
[street_number, street.titlecase].join(' ')
end
def middle_line
if self.building.present?
['Building', building.titlecase].join(' ')
end
end
def last_line
[city.titlecase, region.upcase, zip].join(' ')
end
# def country_name
# # self.country = ISO3166::Country[country]
# # country.translations[I18n.locale.to_s] || country.name
# # iso_country = ISO3166::Country.find_by_name(country) # `country` should be name like 'Australia'
# # iso_country.translations[I18n.locale.to_s] || iso_country.name
# end
# def country_name
# self.country = ISO3166::Country[country]
# country.translations[I18n.locale.to_s] || country.name
# end
def country_name
country = self.country
ISO3166::Country[country]
end
def full_address
[self.unit_line, first_line, middle_line, last_line, country_name].compact.join("<br>").html_safe
end
# --------------- callbacks
after_create :geocode#, if self.full_address.changed?
我也试过:
after_validation :geocode
# --------------- instance methods
# --------------- private methods
end
我的地址 table 具有纬度和经度的十进制属性。我正在使用地理编码器 gem 并希望在创建后对地址进行地理编码。
我有一个 geocoder.rb 的初始化器:
Geocoder.configure(
# Geocoding options
:timeout => 3, # geocoding service timeout (secs)
:lookup => :google, # name of geocoding service (symbol)
:language => :en, # ISO-639 language code
:use_https => true, # use HTTPS for lookup requests? (if supported)
# :http_proxy => nil, # HTTP proxy server (user:pass@host:port)
# :https_proxy => nil, # HTTPS proxy server (user:pass@host:port)
:api_key => nil, # API key for geocoding service
# :cache => nil, # cache object (must respond to #[], #[]=, and #keys)
# :cache_prefix => "geocoder:", # prefix (string) to use for all cache keys
# exceptions that should not be rescued by default
# (if you want to implement custom error handling);
# supports SocketError and TimeoutError
# :always_raise => [],
# calculation options
:units => :km, # :km for kilometers or :mi for miles
# :distances => :linear # :spherical or :linear
)
任何人都可以看到我需要做什么才能让它工作吗?
尽管对我的 address.rb 进行了验证后请求地理编码,但我的 lat/lng 属性没有更新坐标。
控制台输出
a = Address.first
Address Load (30.2ms) SELECT "addresses".* FROM "addresses" ORDER BY "addresses"."id" ASC LIMIT [["LIMIT", 1]]
=> #<Address id: 8, unit: "16", building: "asdf", street_number: "15", street: "Johnston Street", city: "Balmain East", region: "NSW", zip: "2041", country: "AU", time_zone: "Midway Island", addressable_id: 1, addressable_type: "Organisation", description: "registered_office", created_at: "2016-11-10 00:16:50", updated_at: "2016-11-10 00:16:50", latitude: nil, longitude: nil>
Eric 的建议
我尝试采纳 Eric 的建议来触发地理编码,但它没有更新 lat/lng 坐标。
Address.where(latitude: nil).or(Address.where(longitude: nil)).each{|marker| marker.save}
Address Load (16.3ms) SELECT "addresses".* FROM "addresses" WHERE ("addresses"."latitude" IS NULL OR "addresses"."longitude" IS NULL)
(2.0ms) BEGIN
(0.8ms) COMMIT
=> [#<Address id: 8, unit: "1", building: "asdf", street_number: "10", street: "Darling Street", city: "Balmain", region: "NSW", zip: "2041", country: "AU", time_zone: "Midway Island", addressable_id: 1, addressable_type: "Organisation", description: "registered_office", created_at: "2016-11-10 00:16:50", updated_at: "2016-11-10 00:16:50", latitude: nil, longitude: nil>]
像往常一样,从简单开始,慢慢添加更多代码。
我使用了之前
我将 gem 'geocoder'
添加到 Gemfile。
在bundle install
之后,我添加了
geocoded_by :name # can also be an IP address
after_validation :geocode
到我的标记 class,它已经将纬度和经度定义为 :decimal 属性。
在rails c
中:
Marker.create(:name => 'New Dehli')
Marker.create(:name => 'New-York')
完成,它们出现在地图上了!
注意:如果由于某种原因某些标记没有坐标,地图将不会显示,您将在 js 控制台中收到 "too much recursion" 错误。
为避免这种情况,您可以通过在模型中启用 after_validation :geocode
并在控制台中启动它来确保所有标记都有坐标:
Marker.where(latitude: nil).or(Marker.where(longitude: nil)).each{|marker| marker.save}
保存标记会触发验证,而验证会触发地理编码。
如果出于某种原因您仍然有非地理编码标记,请将您的 js 更改为:
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4
});
var bounds = new google.maps.LatLngBounds();
var n = markers.length;
for (var i = 0; i < n; i++) {
var lat = markers[i].latitude;
var lng = markers[i].longitude;
if (lat == null || lng ==null){
console.log(markers[i].name + " doesn't have coordinates");
}else {
var marker = new google.maps.Marker({
position: {lat: parseFloat(lat), lng: parseFloat(lng)},
title: markers[i].name,
map: map
});
bounds.extend(marker.position);
}
}
map.fitBounds(bounds);
}