Search code examples
ruby-on-railsgmaps4rails

Instance Variable loop inside the controller


I have some repeated code inside one of my controllers that I would like to consolidate into a loop, but I can't find any clear instruction on how to do so since this seems to be a unique use case for gmaps4rails. I tried creating an array of instance variables but it didn't seem to work! The code I'd like to consolidate:

stores_controller.rb -->

class StoresController < ApplicationController

    def map
      @rep1 = Store.where(:user_id => "1")
      @rep2 = Store.where(:user_id => "10")
      @rep3 = Store.where(:user_id => "11")
      @rep4 = Store.where(:user_id => "12")
      @rep5 = Store.where(:user_id => "13")
      @rep6 = Store.where(:user_id => "14")
      @rep7 = Store.where(:user_id => "15")
      @rep8 = Store.where(:user_id => "16")
      @rep9 = Store.where(:user_id => "17")
      @repA = Store.where(:user_id => "18")

      @hash1 = Gmaps4rails.build_markers(@rep1) do |store, marker|
        marker.lat store.lat
        marker.lng store.long
        marker.title store.name
        marker.infowindow "#{store.store_infowindow}"
        marker.picture({
           :url => "//chart.apis.google.com/chart?chst=d_map_pin_letter&chld=TP|81DF08|000000",
           :width   => 52,
           :height  => 32
        })

      end
      @hash2 = Gmaps4rails.build_markers(@rep2) do |store, marker|
        marker.lat store.lat
        marker.lng store.long
        marker.title store.name
        marker.infowindow "#{store.store_infowindow}"
        marker.picture({
           :url => "//chart.apis.google.com/chart?chst=d_map_pin_letter&chld=BS|267AD2|D9E1FF",
           :width   => 52,
           :height  => 32
        })
      end
      @hash3 = etc, etc, etc...

I'll also include the marker loader from my map JS in the view file for good measure,

map.html.erb -->

markers = handler.addMarkers(<%=raw @hash1.to_json %>), handler.addMarkers(<%=raw @hash2.to_json %>),
          handler.addMarkers(<%=raw @hash3.to_json %>), handler.addMarkers(<%=raw @hash3.to_json %>),
          handler.addMarkers(<%=raw @hash4.to_json %>), handler.addMarkers(<%=raw @hash5.to_json %>),
          handler.addMarkers(<%=raw @hash6.to_json %>), handler.addMarkers(<%=raw @hash7.to_json %>),
          handler.addMarkers(<%=raw @hash8.to_json %>), handler.addMarkers(<%=raw @hash9.to_json %>),
          handler.addMarkers(<%=raw @hashA.to_json %>);

The gmaps4rails marker building @hash variables continue their individual loops through all 10 reps beyond these first two indicated here. The only two variables within these hashes are the 'build_markers(@rep#)' call and the 'chld=TP|81DF08|000000' call which indicates the initials and color of the marker for each user. I'm a beginner, so for all I know I could be doing this completely wrong from the start! Any advice is appreciated. Thanks!

EDIT -->

My consolidated code, which ended up being as simple as adding a "Marker" column to my user table since that was the only hard-coded variable that needed changing, in the form of '#{store.user.marker}' within the map marker URL:

stores_controller.rb -->

def map
  @stores = Store.all
  @hash = Gmaps4rails.build_markers(@stores) do |store, marker|
    marker.lat store.lat
    marker.lng store.long
    marker.title store.name
    marker.infowindow "#{store.store_infowindow}"
    marker.picture({
       :url => "//chart.apis.google.com/chart?chst=d_map_pin_letter&chld=#{store.user.marker}",
       :width   => 52, :height  => 32
    })
  end
  respond_to do |format|
    format.html
    format.json { render json: @hash }
  end
end

Solution

  • A better way to do this is to simply fetch the records from the db and store the whole collection in one instance variable.

    @stores = Store.where(user_id: [1, 2, 3])
    
    @markers = Gmaps4rails.build_markers(@stores) do |store, marker|
      marker.lat store.lat
      marker.lng store.long
      marker.title store.name
      marker.infowindow "#{store.store_infowindow}"
      # if they need different pictures handle it in the model
      marker.picture({
               :url => "//chart.apis.google.com/chart?chst=d_map_pin_letter&chld=TP|81DF08|000000",
               :width   => 52,
               :height  => 32
      })
    end
    

    Doing this:

      @rep1 = Store.where(:user_id => "1")
      @rep2 = Store.where(:user_id => "10")
      @rep3 = Store.where(:user_id => "11")
      @rep4 = Store.where(:user_id => "12")
      @rep5 = Store.where(:user_id => "13")
      @rep6 = Store.where(:user_id => "14")
      @rep7 = Store.where(:user_id => "15")
    

    Is horrible for performance since each line will create a separate database query. If you are new at ruby I would suggest doing something like http://tryruby.org and learning how to manipulate arrays and hashes and the basics before trying to solve more complex problems.