Drawing Polylines with Rails and Google Maps

Chances are, you have dabbled into adding push pins onto a google map. It’s a pretty easy process, involving a latitude and longitude, which can then be turned into a pin using the google.maps.Marker() function. However, you may not have played with drawing a route with google maps. It turns out, that if you have a series of latitude and longitude points in a database, it is pretty simple to draw them onto a google map.

Rails to the rescue

For our example, we would like to retrieve some lat/lon coordinates from the database and “encode” them in the polyline format. Polyline Reference Once we have the points in the polyline format, we should be able to draw them on a google map. For simplicity, we will use rails on the server to query and transform these points.

Lat Lon
44.928729 -93.167033
44.928729 -93.167033

Assuming that we have data a “shapes” table like above, we should be able to easily query this out with active record and map it to an array of lat/lon points.

Now that the data is in a usable format we need to encode it to the polyline format. To do this we can use a gem called polylines. Just add the following to your gemfile.

At this point polylines should be available to use. It should be as simple as encoding the points.

If successful, you should get some encoded output like below. If so, congratulations you can move on the the final step!

Map it like it’s hot

Now that we have everything worked out on the server, we just need to draw it on the map. First, we are going to need to setup a map object.

Next, we need to setup a polyline object. We can adjust the stroke color, opacity and weight via configuration options. Once the poly object is created, the last thing we need to do is associate it with the map object. The setMap() function will create this association.

At this point, everything should be setup to draw on the map. All we need to do is take our encoded result from the server and set the path on our polyline object.

In the example above, the path variable is referring to the encoded server result. We use the decodePath function to decode our result, and then pass that value into the setPath() function on our polyline object. If all goes according to plan, we should get a blue line like so…

buses-path

Rails Asset Pipeline + Underscore templates

Rails has this shiny feature. Maybe you have heard of it… It is called the asset pipeline, and it is designed to make everything easier when it comes to managing your sites assets. For the most part, it does just that. Many of the those “best practices” Steve Souders has been telling you to do for years are now bundled up in a nice process. I was recently playing with the asset pipeline and stumbled a bit. I wasn’t quite sure where my JavaScript templates fit in to this whole process.

JST, where should you be?

After doing a bit of research, I quickly realized that the asset pipeline in rails is actually built off the sprockets gem. https://github.com/sstephenson/sprockets

This is good news, since sprockets already has built in support for jst templates. Score!

Assuming our application.js manifest file is requiring all our asset files, all we need to do is drop a .jst anywhere file in the /app/assets/javascripts folder.

For our very simple case I dropped in a file called test.jst with the contents below.

Fiddling around in the chrome developer tools you can see that JST[‘test’] is defined when the page loads. By using the _.template() function we can actually compile the template. In the case below, we are simply providing the “name” variable to our template and logging the output.


Let’s recap what happened real quick. Rails automatically loaded our jst file via the asset pipeline, converted it to a javascript string in a file “test.js”, and assigned “test” as a property on the global JST object. We can now access JST[‘test’] anywhere in our JavaScript code to get our template string, as evidence from the dev tools above.

Precompiling Templates

The above works well, however we can improve on it a bit. Most tutorials on client side templating will tell you to always “precompile” your template when the application starts up. Precompiling is the process of converting your string template into a JavaScript function. Something like the code below would do the trick with underscore. Notice how compiled_template actually becomes a reusable function. To execute our compiled template it is as easy as calling compiled_template({ name: ‘jason’ })

The code above will work nicely, however the client still has to take the time to compile each of our templates before they can be used. What if we did the compilation on the server and then passed the resulting function to the client instead of the template string?

EJS Server side compiling

Luckily, again rails has a gem for that. To use EJS simply add it to your gemfile and bundle.

NOTE: You will need to change any .jst files to .jst.ejs extensions. This will instruct EJS to precompile any templates before sending them to the client.

Let’s take a look at what our new test.jst.ejs file looks like when processed on the client.

Clearly, JST[‘test’] is now returning our precompiled function. Executing JST[‘test’] with our argument also gives us back the expected result of “Hi. jason.”

Conclusion

The asset pipeline is quite the tool in the tool belt, and can significantly help you manage not only static assets, but also dynamic client side templates. It seems as if rails has thought of everything 🙂

Quick Tip: Rails for legacy oracle tables

Using Rails can be fun, however sometimes you have a legacy Oracle table that is bringing you down. This table was possibly created long ago, and does not have a sequence setup to handle the primary key. Since Oracle has no auto number type this can be a problem. Rails usually would have a hard time with this since it likes to stick to it’s “sensible defaults”. However, if we set a few things manually we can whip Rails and Oracle into shape.

First thing we need to do is set the table_name and primary_key attributes for our legacy table. Then we need to set the before_save property to increment our column id by selecting the highest legacy id and adding one to it. Pretty simple.

This is for sure not a best practice, but if you cannot create a sequence and need rails to work with legacy oracle, this will do the trick.

1 2 3 4 5 14