Smart Chicago’s Connect Chicago campaign is part of the federal Broadband Technology Opportunities Program. Smart Chicago has helped administer millions of dollars of these funds in programs for its partner, the City of Chicago.
The Connect Chicago location tool tool is a Ruby on Rails app that powers the map and detail page section of our site.
Origins
As part of this project, we hired Chicago developer Derek Eder, who has also worked on other Smart Chicago Collaborative since July 2012. The Connect Chicago Locator originated from Derek’s open source Searchable Map Template. It is powered by the free Google Fusion Tables service that lets you take spreadsheets of data and turn them into maps and other visualizations. His template, which can run on any web server, connects to your Fusion Table, reads in the data, and displays a searchable, filterable map. This template is super-useful and has been used by organizations like the City of Chicago, Chicago Public Schools, and the Chicago Tribune to get map-based sets up and running quickly.
The issue with the Searchable Map Template in the context of this project was that once the map is published, the only way to update it is to directly change the underlying Fusion Table through Google’s interface.
At Connect Chicago, we cover more that 250 places where you can use a computer for free, and it’s important that people in each of these locations (librarians, computer lab managers, social services agency leads, and so on) be able to update their detail page easily.
With an admin tool, managers at each location could update its own detail page with images, tables, contact info and transit directions. As far as we can tell know, no one has made a tool like this for Fusion Tables before.
We also knew that this general idea– the ability for non-technical people to update a robust web map with updated information– was broadly useful to Chicagoans. All of the code for this tool, including the underlying admin module, is available in this package.
One nice feature that I wanted in there, based on my long-term love for Flickr (30,000+ Creative Commons photos posted over nearly a decade): all photos on the detail pages are pulled from Flickr using system-generated unique tags. For example, here’s a bunch of photos I took of the Merlo Library on Belmont and tagged with “pcc-merlo-157 “).
Here’s some technical details from Derek about how we got this done:
The fusion_tables gem
The piece of technology that made these advanced features possible was the fusion_tables gem by Simon Tokumine. This gem, or code library, acts as an interface to read and write data to Fusion Tables from a Ruby application. It sounds simple, but in fact, adds a huge amount of power and convenience for building websites that interact with Fusion Tables. With this gem, we were able to fetch a row based on a URL and populate a detail page with the information.
Here’s a snippet of how it works (viewing the Connect Chicago Fusion Table alongside will help):
#initialize Fusion Tables API FT = GData::Client::FusionTables.new FT.clientlogin(APP_CONFIG['google_account'], APP_CONFIG['google_password']) FT.set_api_key(APP_CONFIG['google_api_key']) @location = FT.execute("SELECT * FROM 1xy_wp4-NhtKPecuDlhsS8MLO0z-g5ayY1OfBhAg WHERE slug = ‘roosevelt-library-1101-w-taylor-street';").first
From there, we have a handle on this @location object, and I can access different attributes like:
@location[:organization_name] # returns ‘Roosevelt Library’ @location[:address] # returns ‘1101 W. Taylor St’
Ruby on Rails Active Model framework
Now that we had an easy way to dynamically read data from our Fusion Table, we needed to give our site administrators some way to edit their data. On any web form, you want to make sure that the information people are entering is correct and what you expect. Form validation is the way to do this. Because we were using Ruby on Rails 3, we were able to leverage their powerful Active Model framework to handle it.
Active Model allows you to extend the non-database functionality of Active Record (an Object Relational Mapper) to any object. Remember our @location object we got from our fusion_tables gem? That is just a simple list of attributes and values (otherwise known as a Hash). By using Active Model, however, we can treat it like an Active Record object and get our form validation for free!
Inside the locations_controller:
@location = Location.new(location_edit) if @location.valid? # save our data else # oops! didn’t validate, take them back to the edit page end
And here’s our location model:
class Location include ActiveModel::Validations include ActiveModel::Conversion extend ActiveModel::Naming # this line tells ActiveModel to make sure that orgainzation_name and others aren’t empty when validation is called validates_presence_of :organization_name, :organization_type, :org_phone, :address, :city, :state, :zip_code def create_method( name, &block ) self.class.send( :define_method, name, &block ) end def create_attr( name ) create_method( "#{name}=".to_sym ) { |val| instance_variable_set( "@" + name, val) } create_method( name.to_sym ) { instance_variable_get( "@" + name ) } end def initialize(attributes = {}) #read in a hash of attributes from Fusion Tables and set them as attributes of the model #for more, see http://railscasts.com/episodes/219-active-model attributes.each do |name, value| name = "#{name}" create_attr name send("#{name}=", value) end end def persisted? false end end
Advancing the utility of a useful tool
From here on out, if you need a Searchable Map Template with an easy-to-use admin tool for distributed detail page authorship, use the Connect Chicago Locator Tool. We look forward to seeing what comes of this!
awesome work, this is a really helpful example!