Search code examples
ruby-on-railsgeojsonmapbox-gl-js

GEOjson in controller for Mapbox Markers


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

Solution

  • 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>