I have a Mapbox map with a GEOjson being fed to it showing all “Experiences” as custom markers. When I am attempting to take the same concept and apply it to only ONE Experience on it’s “show” view, I’m not able to get the data to feed through correctly and keep getting a 404 error in the console. Any ideas what I have wrong?
experiences_controller.rb
def geomap
@experience = Experience.find(params[:id])
respond_to do |format|
format.json do
render json: {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [@experience.latitude, @experience.longitude]
},
properties: {
title: @experience.name,
:'marker-color' => '#00607d',
:'marker-symbol' => 'circle',
:'marker-size' => 'medium'
}
}.to_json
end
end
end
Original Map Controller for All Experiences
def map
@experiences = Experience.published
@geojson = Array.new
@experiences.each do |experience|
@geojson << {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [experience.longitude, experience.latitude]
},
properties: {
title: experience.name,
address: experience.location,
image: experience.cover_photo(nil),
price: experience.price,
id: experience.id,
cat_help: experience.cat_help,
guide: experience.user.fullname,
guide_id: experience.user.id,
summary: experience.summary.truncate(150),
:'marker-color' => '#00607d',
:'marker-symbol' => 'circle',
:'marker-size' => 'medium'
}
}
end
respond_to do |format|
format.html
format.json { render json: @geojson } # respond with the created JSON object
end
end
Experiences.js
$(function() {
mapboxgl.accessToken = 'access-token';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox-style',
center: [-96, 37.8],
zoom: 3
});
map.on('load', function() {
$.ajax({
dataType: 'text',
url: '/geomap.json',
success: function(data) {
var myjson;
myjson = $.parseJSON(data);
var geojson = {
type: 'FeatureCollection',
features: myjson
};
// add markers to map
geojson.features.forEach(function(marker) {
// create a HTML element for each feature
var el = document.createElement('div');
el.className = 'geomarker';
// make a marker for each feature and add to the map
new mapboxgl.Marker(el)
.setLngLat(marker.geometry.coordinates)
.setPopup(new mapboxgl.Popup({ offset: 25 }) // add popups
.setHTML('<a href="/experiences/' + marker.properties.id + '"><div class="row popup-bckg ml-0 mt-2 mb-0 align-items-end rounded" style="background-image:url(' + marker.properties.image + ')">' +
'<div class="w-100 row ml-0 marker-title rounded-bottom"><div class="col-9"><h4 class="mb-0"><strong>' + marker.properties.title + '</strong></h4><small>' + marker.properties.address + '</small></div>' +
'<div class="col-2"><h4><strong>$' + marker.properties.price + '</strong></h4></div></div></div></a>' +
'<div class="row mx-1 mt-3"><div class="col-md-6 align-items-start"><h4 class="mt-0 mb-0">SUMMARY</h4></div><div class="col-md-2 align-items-start"></div><small class="mt-0 mb-0">Guided by: <a href="/users/' + marker.properties.guide_id + '"><strong style="color:orange;">' + marker.properties.guide + '</strong></a></small></div>' +
'<div class="row justify-content-center"><div class="col-11"><hr class="mb-2 mt-1"/><p>' + marker.properties.summary + '</p></div></div>'))
.addTo(map);
});
},
error:function() {
alert("Could not load the events");
}
});
});
});
routes.rb
Rails.application.routes.draw do
resources :experiences do
member do
get 'listing'
get 'pricing'
get 'description'
get 'photo_upload'
get 'amenities'
get 'location'
get 'about'
get 'subcats'
get 'languages'
get 'timeslots'
get 'geomap'
end
collection do
get 'dashboard'
get 'bookings'
end
resources :photos, only: [:create, :destroy]
resources :timeslots, only: [:create, :destroy]
resources :reservations, only: [:create]
resources :calendars
resources :subcategories
end
resources :subcategories do
resources :experiences
end
resources :categories do
resources :experiences
resources :subcategories
end
devise_for :users, controllers: {
sessions: 'users/sessions',
passwords: 'users/passwords',
registrations: 'users/registrations'
}
resources :host_requests do
resources :users
end
resources :static_pages do
resources :users
end
resources :users, only: [:show]
get '/host_calendar' => "calendars#host"
get 'search' => 'static_pages#search'
get '/admin' => "admins#dashboard"
get '/admin/experiences' => "admins#experiences"
get '/admin/host_applications' => "admins#host_applications"
post 'host-updater/:id', to: 'admins#host_update', as: :host_update
get '/dashboard/admin/host_applications' => "users#dashboard_admin_hostapps"
get '/map' => "static_pages#map"
get '/activities' => "categories#activity"
get '/hosting/dashboard' => "host_dashboards#home"
get '/hosting/dashboard/experiences' => "host_dashboards#experiences"
get '/hosting/dashboard/declined' => "host_dashboards#declined"
get '/hosting/dashboard/bookings' => "host_dashboards#bookings"
get '/hosting/dashboard/pending' => "host_dashboards#pending"
get '/hosting/dashboard/incomplete' => "host_dashboards#incomplete"
root to: "static_pages#home"
end
I ended up figuring it out by making it all a bit simpler. Rather than trying to write the geojson out of the controller, I used inline ruby in the script to assign javascript variables the latitude and longitude information. Then I created some inline GeoJSON and used those variables for the coordinates and other feature information. Also - moved my script out of an external js file and into the html.erb view so that it can access the variables. Here’s the updated script:
Updated Javascript
<script>
$(function() {
mapboxgl.accessToken = 'pk.eyJ1IjoianJvY2tldGxhYiIsImEiOiJjajZuNnh5dm4wNTgyMndvMXNqY3lydjI4In0.gHVskGK1QuUoxm8sMwugWQ';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/jrocketlab/cjdcjrwbocrzs2rnurx4lg141',
center: [-96, 37.8],
zoom: 3
});
map.on('load', function() {
var latitude = '<%= j @experience.latitude.to_s %>';
var longitude = '<%= j @experience.longitude.to_s %>';
var title = '<%= j @experience.name.to_s %>'
var geojson = {
type: 'FeatureCollection',
features: [{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [longitude, latitude]
},
properties: {
title: title,
description: 'Washington, D.C.'
}
}]
};
// add markers to map
geojson.features.forEach(function(marker) {
// create a HTML element for each feature
var el = document.createElement('div');
el.className = 'geomarker';
// make a marker for each feature and add to the map
new mapboxgl.Marker(el)
.setLngLat(marker.geometry.coordinates)
.setPopup(new mapboxgl.Popup({ offset: 25 }) // add popups
.setHTML('<h3 class="text-center">Where To Meet</h3>'))
.addTo(map);
});
});
});
</script>