I hope this post fills a bit of that void.
It’s actually quite simple, really. You see, Google is an immense company swimming in cash and dominating virtually every product it has its hands in. Who has the world’s most popular video sharing site? Google. Search engine? Google. How about email service? Google. And mapping service? Google. Whose mobile operating system has the largest market share worldwide? Google’s. Heck, it’s not even a close race in most of these categories.
While this is great for the company, it’s not so healthy for the rest of us. Whenever a company lacks competition, the pace of innovation slows, and arrogance towards customers tends to rise. Anytime a majority of our data is concentrated in the hands of a single company, feelings of unease should arise. That’s why whenever a small, promising startup takes on the giant, I will cheer for the underdog. And I’m not the only one.
Besides, MapBox is actually open source, and given a choice, I’ll go with open source over proprietary any day.
Converting Addresses into Coordinates
All right, enough of that. Let’s start coding.
First thing we’ll do is convert our addresses into coordinates, which MapBox needs in order to place our markers (pin-drops) on the map. We can do this manually by using the MapBox Geocoding API, or we could automate it with the Geocoder gem. Because there is a Railscasts episode covering the gem, I won’t go into any more detail here.
Building a JSON object
Once we have the coordinates, we’re ready to build a JSON object array that will tell MapBox how to display our markers. Our JSON objects will be in the GeoJSON format, which is just a format to describe geographic data in JSON. MapBox uses the GeoJSON format to capture the necessary data needed to generate all the markers on the map. Building a JSON object in Rails is easy. The code below shows how I did it for Phindee; it comes from my
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
The above code simply loops through each happy hour, creates an object, then appends and returns the newly created object to the
@geojson array with the help of the
<< method. Note that each object in our JSON array must contain a
type key, a
geometry key, and a
property key. In our example above, the
geometry key says that we want our marker displayed as a point at that specific set of coordinates, while the
property key says we want our marker to be a medium blue circle that displays the happy hour name and street address when clicked.
I placed the above code inside one of the methods in my happy_hours_controller.rb file, as that’s the controller that deals with happy hours. You’ll place your code inside whatever controller is appropriate for your specific situation.
Telling Rails How to Respond
Because we want Rails to be able to return a JSON object, we’ll need to explicitly tell it do so via a
respond_to block, which we will place right after the code we wrote above.
1 2 3 4
Depending on the type of request, only one of the two lines above will be executed. For example, when we will later make an AJAX request in the JSON format, Rails will know to respond with the JSON object we just created above; otherwise, it will respond with a regular HTML file.
Working with the MapBox API
Adding the Library Code
Initializing the Map
happy_hours.js.coffee), and we’ll add a line instantiating the map with the map ID of the custom-colored map we just created (make sure you add this and all subsequent CoffeeScript code inside a
$(document).ready -> method, or it won’t load).
1 2 3
The coordinates we’re passing on to the
setView() method tell the API where to center the map, while the 14 represents the zoom level for the map. In reality,
Making the AJAX Call
Okay, now we’re ready to use the JSON objects we created earlier. We’ll make an AJAX call in the JSON format, and Rails will return our JSON object.
1 2 3 4 5 6 7 8 9
The code above simply sends out an AJAX call to the URL that corresponds to the controller method into which we added the JSON object code from before. The
.json extension alerts Rails to return a JSON response, instead of an HTML one. On a successful return, we then parse the JSON object and pass it on to the
setGeoJSON() method for mapping. Kid stuff.
Creating Custom Popups
Now we’ll create our custom popups.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
To summarize the code above, we’re simply looping through each marker, creating a custom popup for it, and then binding it using the
bindPop() method, which once again comes from the Leaflet library.
Opening a Popup Programmatically
If you look at Phindee, you’ll notice that when you open the sidebar and click on a happy hour, the popup on the corresponding marker on the map automatically opens up. Being able to open up a popup programmatically is useful, and below is how I did it.
1 2 3 4 5 6 7 8 9 10
We’re simply adding a
click event on the sidebar happy hours, extracting the happy hour name, and looping through each marker to find the one with the matching name. Once we find a match, we extract the marker’s ID, and use that ID to open up the popup programmatically by calling Leaflet’s
And that’s all there is to it! Our MapBox integration with Ruby on Rails is now complete, although we only scratched the surface of what’s possible. Feel free to take a look at the MapBox and Leaflet documentation to learn more.