ActsAsLocateable ================ About ----- ActsAsLocateable is an easy way to give any model the ability to be found by location. For instance, say you have a model Store which is associated with a zip code indicating where that Store is located. To find all the stores within a specific radius of another ZipCode, you can do a Store.find_within_radius(10, 12345) # Find all stores within 10 miles of zip code 12345 Getting the plugin ------------------ script/plugin install http://svn.baconbear.com/rails_plugins/acts_as_locateable/trunk/ Preparing the database ---------------------- In order to work its Kung Fu, ActsAsLocateable requires a table named ZipCode to exist. This table is a list of zip codes and their associated information such as latitude and longitude. If you have the plugin_migrations plugin installed (http://wiki.pluginaweek.org/Plugin_migrations), migrating the proper tables is as simple as: rake db:migrate:plugins PLUGIN=acts_as_locateable Otherwise, copy/paste the migrations found in acts_as_locateable/db/migrate into your main apps db/migrate directory and migrate the normal way Populating the database ----------------------- Now that the ZipCode table is created, we need to populate it. ActsAsLocateable comes with ZipCode data gleaned from http://www.cfdynamics.com/zipbase/. It's a CSV text file which should be fairly easy to understand if you take a glance at it. To import that database, run: rake db:locateable:populate_zipcodes Keep in mind this may take some time as it is importing 45,000 zip codes one record at a time. Preparing the model ------------------- Much like the many other ActsAs* plugins, using ActsAsLocateable is a snap. Say you have a model Item who already has attributes latitude and longitude in the database. Using ActsAsLocateable is as simple as: class Item < ActiveRecord::Base acts_as_locateable end If the latitude/longitude information is stored in an associated model instead of in the model itself, you can work that way too. In the below case, an Item is associated with the ZipCode model that we created previously. ActsAsLocateable is used as follows: class Item < ActiveRecord::Base has_one :zip_code acts_as_locateable :through => :zip_code end Usage ----- Once a model has been made "locateable", a number of Class methods are available: Item.find_within_radius(radius_in_miles, target) # Find all items within radius_in_miles of target Item.within_radius_scope(radius_in_miles, target) # Install a rails "with_scope" condition which limits finds to a specific area Item.find_within_radius_with_dist(radius_in_miles, target) # Same as above, except it returns an Array of Tuples. Each tuple is [instance, distance from instance to target] Item.within_radius_scope_with_dist(radius_in_miles, target) # Same as above, except it returns an Array of Tuples. Each tuple is [instance, distance from instance to target] "Target" mentioned above can come in a number of formats: - Zip Code: Item.find_within_radius(10, 94086) # Find all items within 10 miles of zip code 94086 - "City, State": Item.find_within_radius(10, "Sunnyvale, CA") # Find all items within 10 miles of Sunnyvale, CA - Lat, Lon: Item.find_within_radius(10, +40.922326, -072.637078) # Find all items within 10 miles of lat = +40.922326, lon = -072.637078 Examples -------- # Find all items within 10 miles of zip code 94086 Item.find_within_radius(10, 94086) # Find all items that have a description of "some description" within 10 miles of "Sunnyvale, CA" Item.within_radius_scope(10, "Sunnyvale, CA") do Item.find_by_description(:all, 'some description') end # Find all items and their distances within 10 miles of "Palo Alto, CA" items = Item.find_within_radius_with_dist(10, "Palo Alto, CA") items.each do |i| p i[0] # Print the item p i[1] # Print the distance from item to "Palo Alto, CA" end Credits ---------- Coded by Jeff Lee (www.baconbear.com) ActsAsLocateable is based heavily on the ZipCodeSearch plugin by Doug Fales (http://zipcodesearch.rubyforge.org/) and utilizes much of the same code and data. Special thanks to Doug for making his code freely available!