i have some places in a database and I want to show them on a map – a quick tutorial using google maps api and rails

3 Feb

There is a tutorial over on the Google Maps API article page that shows how to use PHP/MySQL and the Google Maps API v3 to create a map that polls data from a database and shows as markers. I put together some notes to do the same thing using Rails.

First I created a migration to add a places table.

class CreatePlaces < ActiveRecord::Migration
  def self.up
    create_table :places do |t|
      t.string :state
      t.float :lat
      t.float :lng
      t.string :website
      t.integer :user_id
      t.timestamps
    end
  end

  def self.down
    drop_table :places
  end
end

You'll notice that each user has a place, so I updated the models to make that association and add some validation.
in user.rb

has_one :place

in place.rb
class Place < ActiveRecord::Base
  attr_accessible :state, :lat, :lng, :website, :user_id
  
  belongs_to :user
  
  validates_uniqueness_of :state, :user_id, : on => :create
  validates_presence_of :lat, :lng
end

I then added CRUD functionality for the places and added in some data. (If you are new to Rails, check out the getting started guide)

Next you want to output this data to a format that google maps can pick up, I used JSON.

  def index
    @places = Place.with_user_data

    respond_to do |format|
      format.html # index.html.haml
      format.json { render :json => @places }
    end
  end

If this is your first time using JSON I suggest getting the JSON viewer for firefox and reading How To Read JSON Using JQuery.

You’ll notice I used a named scope when creating the places object, this is so that I could explicitly select all the fields that needed to rendered to the JSON file.
in place.rb

named_scope :with_user_data, {
    :select => "places.*, users.first_name, users.last_name",
    :joins => :user
  }

At this point all of the data should be ready to view.

http://localhost:3000/places.json

**note that this image shows an example using jurisdictions instead of places and with additional data, but you’ll get the point **

To display the map I created a separate controller, set the layout to nil, and then accessed the map via Fancybox.

That said the actual view code is very bare

=content_for :head do
   %script{:src => "/javascripts/places_map.js "}
%body
      #map

And then the map javascript

var map;
	var arrMarkers = [];
	var arrInfoWindows = [];
	
	function mapInit(){
		var centerCoord = new google.maps.LatLng(38, -97); 
		var mapOptions = {
			zoom: 3,
			center: centerCoord,
			mapTypeId: google.maps.MapTypeId.TERRAIN
		};
		map = new google.maps.Map(document.getElementById("map"), mapOptions);
		
		$.getJSON("/places.json", {}, function(json){
			$.each(json, function(i,item){
				$("#markers").append('<li><a href="#" rel="' + i + '">' + item.place.name + '</a></li>');
				var marker = new google.maps.Marker({
					position: new google.maps.LatLng(item.place.lat, item.place.lng),
					map: map,
					title: item.place.state
				});
				arrMarkers[i] = marker;
				var infowindow = new google.maps.InfoWindow({
					content: "<h3>"+ item.place.state +"</h3><p>"+ item.place.first_name + "&nbsp;" +  item.place.last_name + ", &nbsp;" + "</p>",
					maxWidth: 100   
				});
				arrInfoWindows[i] = infowindow;
				google.maps.event.addListener(marker, 'click', function() {
					infowindow.open(map, marker);
				});
			});
		});
		    
	}
	$(function(){
		// initialize map (create markers, infowindows and list)
		mapInit();
		
		// "live" bind click event
		$("#markers a").live("click", function(){
			var i = $(this).attr("rel");
			arrInfoWindows[i].open(map, arrMarkers[i]);
		});
	});

And there you have it.

Let me know if you have any questions or comments.

Advertisement

2 Responses to “i have some places in a database and I want to show them on a map – a quick tutorial using google maps api and rails”

  1. Mike Rossetti August 27, 2011 at 9:25 pm #

    Is there a way to pull foursquare check-in data into the database?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.