Tag Archives: JavaScript

Typeahead.js, Elasticsearch and Rails!

Recently for a project I was required to take a list of keywords and make an auto suggest feature. Typically, this can be achieved through some simple but crude sql.

Since the project already required Elasticsearch, all the records were already neatly indexed for me. (minus the keywords) Additionally, the project was developed in Rails so I already had the benefit of the elasticsearch-rails project. With that in mind I got started…

Creating an Analyzer

The first step was to create an analyzer in Elasticsearch for our typeahead column. Creating new analyzers is pretty straightforward with the elasticsearch-rails gem. The “keyword” data we were getting was not checked for errors, so in our case we wanted the analyzer to lowercase everything to reduce the suggestions later. Example if there were searches for “Cats” and “cats” in our keywords we didn’t want to return two suggestions.

Creating a mapping

Now that the analyzer is setup, a mapping can be created. Within the mapping an index is created that uses the keyword info, but this is where it get’s kinda goofy. Elasticsearch wants this data to be structured in a hash with the key of “input” which in turn contains an array of the different keywords. See the example below for more details. The final thing to note is that the index is assigned our “typeahead” analyzer that was created above for both index analysis and search analysis.

Querying suggestions

Now that both the analyzer and mapping are setup, the data can be re-indexed and a query can be run. The following will run a “suggestion” query within the elasticsearch-rails gem. Note: the “text” key is the search term, while the “field” that is being searched on is the keyword_suggest field that was defined in the mapping above.

If all goes according to plan, our model should be returning keyword results in the format below…

Controller time

The controller to return json from the model is dead simple.

Displaying the results

Now that the controller is returning suggestions as json, it’s time to wire that up to a user interface. The project was using the popular Bootstrap framework. With version 2.3.2 there was a JavaScript plugin for typeahead functionality. However, this plugin has been removed as of 3.x in favor of using the typeahead.js library from twitter. It turns out, with a little effort typeahead isn’t that much more complicated to setup than the old bootstrap plugin.

First, an input tag is defined. Make sure that the autocomplete attribute is set to “off” so the native browser doesn’t kick in with it’s suggestions.

Typeahead.js uses an engine called bloodhound to make ajax calls as you type. It has some intelligent caching features and makes consuming that data pretty hands off. Once a new bloodhound object is created, the initialize() method must be called to finish the process.

Now that the bloodhound engine is setup, the input tag can be selected and typeahead will wire everything together. One thing to note, the “displayKey” setting is telling typeahead which key to use from our hash values within the array. In this case “text” is the key that should be used.

Going out with style

The last thing that I did was add a bit of custom styling to the typeahead box.

Overall I was pretty impressed by the solution. It look less than a couple hours to setup and was pretty fast and responsive. When considering a typeahead option for your next project give Elasticsearch a spin!

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 🙂

1 2 3 6