Skip to content

Instantly share code, notes, and snippets.

@jendiamond
Forked from kkchu791/map.md
Last active March 18, 2016 07:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jendiamond/cb79d01d3db894e4ade2 to your computer and use it in GitHub Desktop.
Save jendiamond/cb79d01d3db894e4ade2 to your computer and use it in GitHub Desktop.

Add a Map

We are going to setup a map feature that will allow you to see all your adventures on a map and search for adventures by address.

First let’s setup our migrations

Setup an address column

In your command line, generate the migrations for address, latitutde and longitude.

$ rails generate migration AddAddressToAdventures address:string

$ rails generate migration AddLatitudeAndLongitudeToAdventures latitude:float longitude:float

Then run your migrations.

$ rake db:migrate

Then, add address field to form. We will setup our app so we only need to input an address and not coordinates.

#app/views/adventures/_form.html.erb

  <div class="field">
    <%= f.label :address %><br>
    <%= f.text_field :address %>
  </div>

Because we’ve added new attributes to our form, we need to permit them in our params in our controller. Add address attribute to the permitted params of adventures_controller.

#app/controllers/adventures_controller.rb

 def adventure_params
    params.require(:adventure).permit(:name, :description, :picture, :visit, :address)
 end

Let’s also add in our map attributes to our adventures/page

# app/views/adventures/show.html.erb
    <p><b>Name: </b><%= @adventure.name %></p>
    <p><b>Description: </b><%= @adventure.description %></p>
   + <p><b>Address: </b><%= @adventure.address %></p>
    + <p><b>Latitude: </b><%= @adventure.latitude %></p>
    + <p><b>Longitude: </b><%= @adventure.longitude %></p>

Now create a new adventure and add in an address. You’ll know it works when you see the the coordinates of your address on your show page.

Setting up geocoder

Now let’s setup our geocoder gem. Geocoder is an excellent gem for converting addresses and coordinates, finding nearby locations and determining distances.

In your Gemfile add

#Gemfile
gem 'geocoder'

Bundle in your command line

$ bundle install

Setup your adventure model for geocoder

# app/models/adventure.rb

class Adventure < ActiveRecord::Base
+ geocoded_by :address   
+ after_validation :geocode          # this command auto fetches our coordinates
  mount_uploader :picture, PictureUploader
  has_many :comments
end

Setting up gmaps4rails

The gmaps4rails gem allows us to use google maps with our own custom overlays (markers, infowindows).

Add gmaps4rails to your gemfile

# Gemfile

gem 'gmaps4rails'

and bundle again in your command line

$ bundle install

Adding a map section to your app

Create a new file in your views/pages directory called map.html.erb.

#views/pages/map.html.erb

You will need to add scripts that connect with Google’s map API and a div that holds the map. Add in the code below to that map file. You can change the size of the map by messing with the width and height on the <div id=map.

# views/pages/map.html.erb

<div style='width: 800px;'>
  <div id="map" style='width: 800px; height: 400px;'></div> 
</div>

<script src="//maps.google.com/maps/api/js?v=3.18&sensor=false&client=&key=&libraries=geometry&language=&hl=&region="></script>

<script src="//google-maps-utility-library-v3.googlecode.com/svn/tags/markerclustererplus/2.0.14/src/markerclusterer_packed.js"></script>

<script type="text/javascript">
  var handler = Gmaps.build('Google');
  handler.buildMap({ internal: {id: 'custom_style'}, provider: {}, internal: {id: 'map'}}, function(){
    markers = handler.addMarkers(<%=raw @hash.to_json %>);
    handler.bounds.extendWith(markers);
    handler.fitMapToBounds();
  });
</script>

For this to work, we need underscoreJS. Go to http://underscorejs.org/ and click on production version(1.8.3). Copy everything in that file.

Create a new file in vendor/assets/javascripts directory called underscore.js. Paste in what you copied

#vendor/assets/javascripts/underscore.js

#Paste code here

Next, setup your javascript by requiring underscore and gmaps/google in your application.js

We need to do this so our javascript can see those gems.

#app/assets/javascript/application.js

+ //= require underscore
+ //= require gmaps/google
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require_tree .

Whenever we add to our application.js file, we should restart our server to see those changes.

In the command line, restart your server.

Next, we’ll fix up our controller. Add in a map method to pages_controller to incorporate the map.

#app/controllers/pages_controller.rb

  def map
    if params[:search].present?
      @adventures = Adventure.near(params[:search], 1000, :order => :address)
    else
      @adventures = Adventure.all
    end
    @hash = Gmaps4rails.build_markers(@adventures) do |adventure, marker|
      marker.lat adventure.latitude
      marker.lng adventure.longitude
      marker.infowindow adventure.name
      marker.picture({
        "width" => 32,
        "height" => 32})
      marker.json({ name: adventure.name})
    end
  end

Add static maps and nearby locations in the adventures/show page. The image tag shows a static map and the nearby locations will find all the nearby locations of the address you entered in a 1000 mile radius.

# views/adventures/show.html.erb

<%= image_tag "http://maps.google.com/maps/api/staticmap?size=450x300&sensor=false&zoom=16&markers=#{@adventure.latitude}%2C#{@adventure.longitude}" %>

<h3>Nearby Adventures</h3>
<ul>
<% for location in @adventure.nearbys(10) %>
  <li><%= link_to location.address, location %> (<%= location.distance.round(2) %> miles)</li>
<% end %>
</ul>

Go to one of your adventure#show pages to see your map and nearby locations.

###Adding search field

Finally, let’s add a search input feature to your views which allows you to enter an address or location name, and will get the nearest adventures to that inputted area.

#app/views/pages/map.html.erb

<%= form_tag adventures_path, :method => :get do %>
  <p>
    <%= text_field_tag :search, params[:search] %>
    <%= submit_tag "Search Near", :name => nil %>
  </p>
<% end %>

And there you have it. Try creating a few more adventure to populate your map.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment