Sunday, January 23, 2011

Easy data caching in Rails 3

Three common forms of caching

There are 3 types of caching that are very commonly talked about in the rails community; page caching, action caching, and fragment caching. All of these are well documented and are great ways to cache varying amounts of content for your pages.

Is that all the caching I need?

Caching at the view level is great but it isn't necessarily the best fit for every situation. In some cases it may be easier to cache data at a lower level. Perhaps you want to cache the results of an external data request for a given period of time. None of the view caching methods would be a really great fit.

Lower level data caching

Rails 3 actually has a great method for caching data at a lower level than the view. It even uses the same caching store as action and fragment caching. ActiveSupport::Cache::Store allows you to store any serializable Ruby object. Rails even provides an already initialized cache store via Rails.cache.

Example usage and code

I used this on www.checkthesock.com to cache METAR queries. I was using current_metar a gem I built that pulls metar data from ADDS. I made a model called CachedMetar to return cached results to the rest of my application.


Code walk through

This model basically returns the result of the block argument to Rails.cache.fetch the first time it is called. Any time it is called within the next 5 minutes it returns the value that was cached the first time. Everywhere I had previously been calling CurrentMetar::Metar.get_metar("ICAO code") I switched to call CachedMetar.metar("ICAO code") and that was all it took.

Testing

Testing is actually surprisingly easy. I used shoulda and mocha and here is what I ended up with.


Reference

Friday, January 21, 2011

SEO friendly maps with jQuery

In my free time I am working on a social networking site for RC pilots. I have information pages for various RC airfields and I was looking for a good way to display a listing of the fields. Putting markers on an embedded google map is a great way to display this type of data to users. The method I have seen recommended for this is to make separate list and map views. I don't really think that is a great user experience though.

The main reason making two pages is suggested is that maps require many lines of code and JavaScript functions that will dilute your content. The solution I arrived at was to use as little javascript as possible to generate my map. I ended up accomplishing this by using javascript to parse the content of the page to generate the markers.

To be able to easily parse out the data I wanted to display on the map I ended up making my own microformat. I put a class of field on the div that contained each field I was showing on the page. In that div I put the content that I wanted to display in the information popup for each marker. Then in that div I put two spans that contained the latitude and longitude and gave them each a class. The results ended up looking like this:


Then I wrote some javascript to parse this microformat and generate markers for my map. I used jQuery selectors to select each field in the html. For each field the latitude, longitude, and html contents are selected. Then the add_marker method is called to setup the marker with that data. After the marker is created I hide the field div.


Users with javascript will see a map with a bunch of markers that have an information bubble when clicked on. Users that do not have javascript enabled will see a list of field information. The textual content is the same for both users, the users with javascript just get an improved experience.

Go to www.checkthesock.com/fields to see the end result.