gmaps railscamp2008

24
Intégration de GoogleMaps dans une Application Rails 2.0 Sébastien Gruhier Xilinus Railscamp - Paris - 17 mai 2008

Upload: xilinus

Post on 17-May-2015

2.529 views

Category:

Technology


2 download

DESCRIPTION

Slide de ma session sur l'integration d'une google map dans une application Rails. Le code est disponible sur github: http://github.com/xilinus/gmaps_demo/

TRANSCRIPT

Page 1: Gmaps Railscamp2008

Intégration de GoogleMaps dans une Application Rails 2.0

Sébastien GruhierXilinus

Railscamp - Paris - 17 mai 2008

Page 2: Gmaps Railscamp2008

GoogleMapshttp://code.google.com/apis/maps/

• Affichage géolocalisé d’information (point, forme vectorielle, trafic ...)

• Librairie Javascript

• Gratuit sous certaines conditions

• Nécessite une API key

Page 3: Gmaps Railscamp2008

Plugin GeoKithttp://geokit.rubyforge.org/

• Ajout de finder geolocalisé à ActiveRecord

• MultiProvider (GoogleMap, YahooMaps...)

• Calcul de distance

• IP localisation via hostip.info

• ...

Page 4: Gmaps Railscamp2008

Application de demo

• Application Rails 2.0

• Visualisation des utilisateurs sur une googlemap

• Plugin restful_authenticated + geokit

Page 5: Gmaps Railscamp2008

Initialisation

• Assez parlé, codons un exemple

rails gmaps_demo -d mysql; cd gmaps_demo

• plugin geokit

./script/plugin install svn://rubyforge.org/var/svn/geokit/trunkgit module add git://github.com/ptb/geokit.git vendor/plugins/geokit

• plugin restful_authentication

./script/plugin install http://svn.techno-weenie.net/projects/plugins/restful_authenticationgit submodule add git://github.com/technoweenie/restful-authentication.git vendor/plugins/restful_authentication

• GIT: git submodule init

Page 6: Gmaps Railscamp2008

GeoKitTest

./script/console Loading development environment (Rails 2.0.2)include GeoKit::Geocoders>> include GeoKit::Geocoders=> Object>> home = MultiGeocoder.geocode("151 rue montmartre, paris")=> #<GeoKit::GeoLoc:0x27769b8 @country_code="FR", @lat=48.870519, @street_address="151, Rue Montmartre", @full_address="151, Rue Montmartre, 75002 2ème Arrondissement Paris, Paris, France", @precision="address", @zip="75002", @state="Ile-de-France", @success=true, @provider="google", @lng=2.342718, @city="Paris">

>> home = MultiGeocoder.geocode("151 rue montmartre, paris")>> rennes = MultiGeocoder.geocode("rennes, france")>> home.distance_to(rennes, :units => :kms) => 308.473068506021

Calcul “in memory”

Page 7: Gmaps Railscamp2008

Initialisation

• Editer database.yml si nécessaire

rake db:create

• Génération de l’authentification (sans activation ni stateful)

./script/generate authenticated user sessions rake db:migraterake db:fixtures:load

Page 8: Gmaps Railscamp2008

Initialisation

• Supprimer public/index.html

• Ajouter un layout simple

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <meta http-equiv="content-type" content="text/html;charset=UTF-8" /> <title>Google Maps Demo</title> </head> <body> <%= yield %> </body></html>

Page 9: Gmaps Railscamp2008

Initialisation

• Ajouter une vue users/index.html.erb

• Avec un partial users/_user.html.erb

User List<table border="0" cellspacing="5" cellpadding="5"> <tr> <th>Login</th> <th>Email</th> <th>Created At</th> </tr> <%= render :partial => "user", :collection => @users %></table><br/><%= link_to 'Add a new user', new_user_path %>

<tr> <td><%= user.login %></td> <td><%= user.email %></td> <td><%= user.created_at.to_s :short %></td></tr>

Page 10: Gmaps Railscamp2008

Initialisation fin!

• On ajoute une route par défaut

• Déplacer le code de environment.rb dans

config/initializers/geokit.rb avec une clé google valide

• Et on peut enfin s’amuser avec GoogleMaps :)

map.root :controller => 'users'

Page 11: Gmaps Railscamp2008

Géolocalisation

• Ajouter des attributs au model User./script/generate migration add_geolocalisation_to_users

class AddGeolocalisationToUsers < ActiveRecord::Migration def self.up add_column :users, :address, :string add_column :users, :lat, :decimal, :precision => 15, :scale => 10 add_column :users, :lng, :decimal, :precision => 15, :scale => 10 end

def self.down remove_column :users, :address remove_column :users, :lat remove_column :users, :lng endend

Page 12: Gmaps Railscamp2008

Géolocalisation

• Mettre à jour les deux fixturesUtilise la console !!

./script/console Loading development environment (Rails 2.0.2)>> MultiGeocoder.geocode("10 rue de la republique, paris, france")

=> #<GeoKit::GeoLoc:0x1102bdc @country_code="FR", @lat=48.866816, @street_address="10, Avenue De La République", @full_address="10, Avenue de la République, 75011 11ème Arrondissement Paris, Paris, France", @precision="address", @zip="75011", @state="Ile-de-France", @success=true, @provider="google", @lng=2.366405, @city="Paris">

Page 13: Gmaps Railscamp2008

Géolocalisation

• Ajouter au modèle User

• Ajouter edit/update + adresse à un user (dans la vue)

attr_accessible ..., :address

acts_as_mappable :auto_geocode => truebefore_validation_on_update :auto_geocode_address

Page 14: Gmaps Railscamp2008

GoogleMap

• Ajouter une route users/map

• Une action, un layout fullscreen: map.html.erb

map.resources :users, :collection => {:map => :get}

Page 15: Gmaps Railscamp2008

GoogleMaplayouts/map.html.erb

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <meta http-equiv="content-type" content="text/html;charset=UTF-8" /> <title>Google Maps Demo</title> <%= javascript_include_tag :all %> <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=<%= GeoKit::Geocoders::google %>" type="text/javascript"></script> <style type="text/css"> html, body { margin:0; height:100% } #map { min-height: 100%; background-color: #DDD; } * html #map { height: 100%; } </style> </head> <body> <%= yield %> </body></html>

Page 16: Gmaps Railscamp2008

GoogleMapviews/users/map.html.erb

<div id="map"></div><%= javascript_tag "new Application('map', '#{@users.to_json(:only => [:login, :lat, :lng])}');" %>

def map @users = User.find :all render :layout => 'map'end

Action

Vue

Page 17: Gmaps Railscamp2008

GoogleMapapplication.js

Application = new Class.create({ initialize: function(map, users) { this.element = $(map); this.users = users.evalJSON(); document.observe("dom:loaded", this.init.bind(this)); }, init: function() { if (GBrowserIsCompatible()) { // Create a google map this.map = new GMap2(this.element); // Center on France this.map.setCenter(new GLatLng(46.227638, 2.213749), 6); // Add controls this.map.addControl(new GLargeMapControl()); this.map.addControl(new GMapTypeControl()); // Add Markers if (this.users) { this.users.each(function(user) { var marker = new GMarker(new GLatLng(user.lat, user.lng)); GEvent.addListener(marker, "click", function() { marker.openInfoWindowHtml(user.login); }); this.map.addOverlay(marker); }.bind(this)) } } }});

Page 18: Gmaps Railscamp2008

MultiMap

Pour le fun, ajouter un map par user sur la page index :)

<tr> <td><%= user.login %></td> <td><%= user.email %></td> <td><%= user.lat %></td> <td><%= user.lng %></td> <td><%= user.created_at.to_s :short %></td> <td><div id="<%= dom_id(user) %>" class="minimap"></div></td> <td><%= link_to 'edit', edit_user_path(user) %></td></tr><%= javascript_tag "new MiniMap('#{dom_id(user)}', '#{user.to_json(:only => [:login, :lat, :lng])}');" %>

Page 19: Gmaps Railscamp2008

MultiMapClasse MiniMap

MiniMap = new Class.create({ initialize: function(map, user) { this.element = $(map); this.user = user.evalJSON(); document.observe("dom:loaded", this.init.bind(this)); }, init: function() { if (GBrowserIsCompatible()) { // Create a google map this.map = new GMap2(this.element); // Center on France this.map.setCenter(new GLatLng(this.user.lat, this.user.lng), 6); var marker = new GMarker(new GLatLng(this.user.lat, this.user.lng)); this.map.addOverlay(marker); } }});

Page 20: Gmaps Railscamp2008

GeoKitAutres fonctions

• sort_by_distance_from

• Column distance

• GeoKit::Bounds

>> u = User.find :first>> users.User.find :all>> users.sort_by_distance_from u

>> User.find :all, :origin => u, :within => 500, :order => 'distance'

>> bounds = GeoKit::Bounds.new(sw_point, ne_point) >> users = User.find :all, :bounds => bounds

Page 21: Gmaps Railscamp2008

GeoKitAutres fonctions

• eager loading

• IP Geocoding

>> users = Users.find :all, :origin => home, :include => [:articles], :within => 5, :order => 'distance'

>> location = GeoKit::Geocoders::IpGeocoder.geocode('82.236.140.196')=> #<GeoKit::GeoLoc:0x2784fe0 @country_code="FR", @lat=48.0833, @street_address=nil, @precision="unknown", @zip=nil, @state=nil, @success=true, @provider="hostip", @lng=-1.68333, @city="Rennes">

Page 22: Gmaps Railscamp2008

GeoKitAutres fonctions

• IP Geocoding

class ApplicationController < ActionController::Base # Auto-geocode the user's ip address and store # it in the session. geocode_ip_address

def loc # @location is a GeoLoc instance. @location = session[:geo_location] end end

Page 23: Gmaps Railscamp2008

GeoKitAutres fonctions

• Et encore!

# Finds within a distance radius.def find_within(distance, options={})alias find_inside find_within # Finds beyond a distance radius.def find_beyond(distance, options={})alias find_outside find_beyond # Finds according to a range. Accepts inclusive or exclusive ranges.def find_by_range(range, options={}) # Finds the closest to the origin.def find_closest(options={})alias find_nearest find_closest # Finds the farthest from the origin.def find_farthest(options={})

# Finds within rectangular bounds (sw,ne).def find_within_bounds(bounds, options={})

Page 24: Gmaps Railscamp2008

Done!!

• Code disponible sur githubgit://github.com/xilinus/gmaps_demo.git