У меня есть приложение Rails 3.2, которое позволяет пользователю создавать магазин, и я хочу, чтобы пользователь поместил свой магазин на карту. Я попробовал гем gmaps4rails и заставил его работать, используя конфигурацию по умолчанию — преобразование адреса, введенного пользователем, в координаты и отображение маркера на карте. Однако я считаю, что процесс преобразования не соответствует точности, и я предпочитаю, чтобы пользователь мог поставить свой собственный маркер на карте.
Это мой код после прочтения драгоценного камня:
# migration
t.string "address", :null => false
t.float "latitude"
t.float "longitude"
t.boolean "gmaps"
# model Shop.rb
attr_accessible :name, :address, :latitude, :longitude
acts_as_gmappable
def gmaps4rails_address
address
end
# shops_controller.rb
def show
@shop = Shop.find(params[:id])
@json = Shop.all.to_gmaps4rails
end
def edit
@shop = Shop.find(params[:id])
@json = Shop.all.to_gmaps4rails
end
def update
@shop = Shop.find(params[:id])
@json = Shop.all.to_gmaps4rails
if @shop.update_attributes(params[:shop])
flash[:success] = "Shop's updated."
redirect_to shop_path(@shop)
end
end
# view
<%= gmaps4rails(@json) %>
Частичная форма (ссылка из вики гема):
# _form.html.erb
....
<%= gmaps4rails(@json) %>
<% content_for :scripts do %>
<script type="text/javascript" charset="utf-8">
var markersArray = [];
// On click, clear markers, place a new one, update coordinates in the form
Gmaps.map.callback = function() {
google.maps.event.addListener(Gmaps.map.serviceObject, 'click', function(event) {
clearOverlays();
placeMarker(event.latLng);
updateFormLocation(event.latLng);
});
};
// Update form attributes with given coordinates
function updateFormLocation(latLng) {
$('#shop_attributes_latitude').val(latLng.lat());
$('#shop_attributes_longitude').val(latLng.lng());
$('#shop_attributes_gmaps_zoom').val(Gmaps.map.serviceObject.getZoom());
}
// Add a marker with an open infowindow
function placeMarker(latLng) {
var marker = new google.maps.Marker({
position: latLng,
map: Gmaps.map.serviceObject,
draggable: true
});
markersArray.push(marker);
// Set and open infowindow
var infowindow = new google.maps.InfoWindow({
content: '<div class="popup"><h2>Awesome!</h2><p>Drag me and adjust the zoom level.</p>'
});
infowindow.open(Gmaps.map.serviceObject,marker);
// Listen to drag & drop
google.maps.event.addListener(marker, 'dragend', function() {
updateFormLocation(this.getPosition());
});
}
// Removes the overlays from the map
function clearOverlays() {
if (markersArray) {
for (var i = 0; i < markersArray.length; i++ ) {
markersArray[i].setMap(null);
}
}
markersArray.length = 0;
}
</script>
Проблемы:
- При нажатии на карту существующий маркер не очищается. Тем не менее, это дает новый маркер.
- Когда я нажимаю кнопку отправки, широта и долгота не обновляются, чтобы отразить новую позицию нового маркера. Он просто использует старый.
ОБНОВЛЕНИЕ
Мне удалось заставить работать часть «обновить позицию маркера», но существующий маркер все еще не очищался, когда карта была нажата в форме. Результат на странице показа показывает только обновленный маркер, что приятно.
Вот обновленный код:
# Shop.rb
acts_as_gmappable :process_geocoding => false
# no more def gmaps4rails_address in the model
# controller
def show
@json = Shop.find(params[:id]).to_gmaps4rails
end
def edit
@json = Shop.find(params[:id]).to_gmaps4rails
end
def update
@shop = Shop.find(params[:id])
# @json = Shop.all.to_gmaps4rails # not needed here
...
end
# _form.html.erb
<%= gmaps4rails(@json) %>
<%= f.hidden_field :latitude %>
<%= f.hidden_field :longitude %>
<% content_for :scripts do %>
...
function updateFormLocation(latLng) {
$('#shop_latitude').val(latLng.lat());
$('#shop_longitude').val(latLng.lng());
$('#shop_gmaps_zoom').val(Gmaps.map.serviceObject.getZoom());
}
...