{"id":13463388,"url":"https://github.com/geokit/geokit-rails","last_synced_at":"2025-05-14T01:05:47.292Z","repository":{"id":468527,"uuid":"93340","full_name":"geokit/geokit-rails","owner":"geokit","description":"Official Geokit plugin for Rails/ActiveRecord. Provides location-based goodness for your Rails app. Requires the Geokit gem.","archived":false,"fork":false,"pushed_at":"2024-02-23T16:46:25.000Z","size":389,"stargazers_count":1574,"open_issues_count":38,"forks_count":244,"subscribers_count":35,"default_branch":"master","last_synced_at":"2025-04-09T18:09:43.513Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/geokit.png","metadata":{"files":{"readme":"README.markdown","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"MIT-LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2008-12-19T01:56:49.000Z","updated_at":"2025-03-12T06:09:52.000Z","dependencies_parsed_at":"2024-01-13T11:51:31.976Z","dependency_job_id":"c926fd7d-426f-40f0-9e32-28d31fd2a6b9","html_url":"https://github.com/geokit/geokit-rails","commit_stats":{"total_commits":302,"total_committers":56,"mean_commits":5.392857142857143,"dds":0.7516556291390728,"last_synced_commit":"e3a9f6e21d1987b360f4b656d2d35cd0d5814971"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geokit%2Fgeokit-rails","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geokit%2Fgeokit-rails/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geokit%2Fgeokit-rails/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geokit%2Fgeokit-rails/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/geokit","download_url":"https://codeload.github.com/geokit/geokit-rails/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248154454,"owners_count":21056539,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T13:00:52.562Z","updated_at":"2025-04-10T03:39:41.508Z","avatar_url":"https://github.com/geokit.png","language":"Ruby","funding_links":[],"categories":["Time \u0026 Space","Ruby","Gems","Geolocation"],"sub_categories":["Geocoding \u0026 Maps","Articles"],"readme":"Geokit Rails\n============\n\n[![Gem Version](https://badge.fury.io/rb/geokit-rails.svg)](http://badge.fury.io/rb/geokit-rails)\n[![Build Status](https://travis-ci.org/geokit/geokit-rails.svg?branch=master)](https://travis-ci.org/geokit/geokit-rails)\n[![Coverage Status](https://coveralls.io/repos/geokit/geokit-rails/badge.svg?branch=master)](https://coveralls.io/r/geokit/geokit-rails)\n[![Code Climate](https://codeclimate.com/github/geokit/geokit-rails.svg)](https://codeclimate.com/github/geokit/geokit-rails)\n\n## COMMUNICATION\n\n* If you **need help**, use [Stack Overflow](http://stackoverflow.com/questions/tagged/geokit). (Tag 'geokit' and we'll be alerted)\n* If you **found a bug**, use GitHub issues.\n* If you **have an idea**, use GitHub issues.\n* If you'd like to **ask a general question**, use GitHub issues.\n* If you **want to contribute**, submit a pull request.\n\n## INSTALLATION\n\nGeokit for Rails consists of a generic Gem ([geokit](https://github.com/geokit/geokit)) and a Rails plugin ([geokit-rails](https://github.com/geokit/geokit-rails)).\n\nMake sure you use a version \u003e= 3.0 of Rails.\n\nYou just have to add the 'geokit-rails' gem to your Gemfile\n\n```ruby\ngem 'geokit-rails'\n```\n\nThen tell bundler to update the gems :\n\n```sh\n$ bundle install\n```\nGenerate the configuration initializer:\n\n```sh\n$ rails g geokit_rails:install\n```\n\nNow, if you wish to use the various geocoding services, you can add your keys to the new initializer.\n\n\n\nIf you want to use geokit-rails in a Rails 2 application, just use the good old plugin ([geokit-rails](https://github.com/andre/geokit-rails)).\n\n\n## FEATURE SUMMARY\n\nGeokit provides key functionality for location-oriented Rails applications:\n\n- Distance calculations, for both flat and spherical environments. For example,\n  given the location of two points on the earth, you can calculate the miles/Km\n  between them.\n- ActiveRecord distance-based finders. For example, you can find all the points\n  in your database within a 50-mile radius.\n- IP-based location lookup utilizing hostip.info. Provide an IP address, and get\n  city name and latitude/longitude in return\n- A before_action helper to geocoder the user's location based on IP address,\n  and retain the location in a cookie.\n- Geocoding from multiple providers. It provides a fail-over mechanism, in case\n  your input fails to geocode in one service. Geocoding is provided by the Geokit\n  gem, which you must have installed\n\nThe goal of this plugin is to provide the common functionality for location-oriented\napplications (geocoding, location lookup, distance calculation) in an easy-to-use\npackage.\n\n## A NOTE ON TERMINOLOGY\n\nThroughout the code and API, _latitude_ and _longitude_ are referred to as _lat_\nand _lng_.  We've found over the long term the abbreviation saves lots of typing time.\n\n## LOCATION QUERIES\n\n### MAKING A MODEL MAPPABLE\n\nTo get started, just specify an ActiveRecord class as `acts_as_mappable`:\n\n```ruby\nclass Location \u003c ActiveRecord::Base\n  acts_as_mappable\nend\n```\n\nThere are some defaults you can override:\n\n```ruby\nclass Location \u003c ActiveRecord::Base\n  acts_as_mappable :default_units =\u003e :miles,\n                   :default_formula =\u003e :sphere,\n                   :distance_field_name =\u003e :distance,\n                   :lat_column_name =\u003e :lat,\n                   :lng_column_name =\u003e :lng\nend\n```\n\nThe optional parameters are `units`, `formula`, and `distance_field_name`.\nValues for **units** can be `:miles`, `:kms` (kilometers), or `:nms` (nautical miles),\nwith `:miles` as the default.\nValues for **formula** can be `:sphere` or `:flat` with `:sphere` as the default.\n`:sphere` gives you Haversine calculations, while `:flat` gives the Pythagoreum Theory.\nThese defaults persist through out the gem.\n\nThe plug-in creates a calculated `distance` field on AR instances that have\nbeen retrieved through a Geokit location query. By default, these fields are\nknown as \"distance\" but this can be changed through the `:distance_field_name` key.\n\nYou can also define alternative column names for latitude and longitude using\nthe `:lat_column_name` and `:lng_column_name` keys.  The defaults are `lat` and\n`lng` respectively.\n\n### NEW SCOPES TO USE\n\nOnce you've specified `acts_as_mappable`, a few scopes are available :\n\n* `within` and `beyond` find records within or beyond a certain distance from the origin point.\n* `in_range` finds records within a certain distance range from the origin point.\n* `in_bounds` finds records within a rectangle on the map\n* `closest` and `farthest` find the closest or farthest record from the origin point\n* `by_distance` finds records ordered by distance from the origin point\n\nAll of these scopes take a hash of options where the first parameter is simply\none of  the possible options, without the name.\n\nA few examples :\n\n```ruby\nLocation.within(5, :origin =\u003e @somewhere)\n```\n\n```ruby\nLocation.in_range(2..5, :origin =\u003e @somewhere)\n```\n\n```ruby\nLocation.in_bounds([@south_west_point, @north_east_point], :origin =\u003e @somewhere)\n```\n\nThe options can be :\n\n`:origin` as a two-element array of latitude/longitude:\n\n```ruby\nLocation.by_distance(:origin =\u003e [37.792,-122.393])\n```\n\n`:origin` as a geocodeable string:\n\n```ruby\nLocation.by_distance(:origin =\u003e '100 Spear st, San Francisco, CA')\n```\n\n`:origin` as an object which responds to `lat` and `lng` methods,\nor `latitude` and `longitude` methods, or whatever methods you have\nspecified for `lng_column_name` and `lat_column_name`:\n\n```ruby\nLocation.geo_scope(:origin =\u003e my_store)\n# my_store.lat and my_store.lng methods exist\n```\n\n`:units` or `:formula` can be used to override the default values in a specific query\n\n```ruby\nLocation.within(5, :units =\u003e :kms, :origin =\u003e @somewhere)\n# it will get the records within 5 kilometers instead of 5 miles\n```\n\n`:range` as a native Ruby range\n\n`:bounds` as an array of two elements : the south/west point and the north/east point.\n\n```ruby\n@sw = Geokit::LatLng.new(32.91663,-96.982841)\n@ne = Geokit::LatLng.new(32.96302,-96.919495)\n@somewhere = Location.find(123456)\nLocation.within(:bounds =\u003e [@sw, @ne], :origin =\u003e @somewhere)\n```\n\n`:bounds` as a Geokit::Bounds object\n\n```ruby\n@bounds = Geokit::Bounds.new([32.91663,-96.982841], [32.96302,-96.919495])\n@somewhere = Location.find(123456)\nLocation.within(:bounds =\u003e [@sw, @ne], :origin =\u003e @somewhere)\n```\n\nWhen using a point of reference or bounds, you leverage the power of Geokit\nto build this objects. Basically, if Geokit can make a Geokit::Point\nor a Geokit::Bounds with what you give to it, you're good to go.\n\n### FIND BY SQL\n\nFinally, if all that is desired is the raw SQL for distance\ncalculations, you can use the following:\n\n```ruby\nLocation.distance_sql(origin, units = default_units, formula = default_formula)\n```\n\nThereafter, you are free to use it in `find_by_sql` as you wish.\n\n### CHAINABILITY\n\nYou can then chain these scope with any other or use a \"calling\" method like `first`, `all`, `count`, …\n\n```ruby\nLocation.within(5, :origin =\u003e @somewhere).all\nLocation.within(5, :origin =\u003e @somewhere).count\nLocation.by_distance(:origin =\u003e [37.792,-122.393]).first\n```\n\nYou can add `order` clauses in the chain as for any ActiveRecord query\n\n```ruby\nLocation.within(5, :origin =\u003e @somewhere).order('nbr_seats ASC')\n```\n\nYou can even sort by distance (use the same name as specified in the model class)\n\n```ruby\nLocation.within(5, :origin =\u003e @somewhere).order('distance DESC, nbr_seats ASC')\n```\n\nIdem for the `limit` clause. In fact, `closest` and `farthest` are defined like this :\n\n```ruby\ndef closest(options = {})\n  by_distance(options).limit(1)\nend\ndef farthest(options = {})\n  by_distance({:reverse =\u003e true}.merge(options)).limit(1)\nend\n```\n\n#### Important caveat\n\nIn the current version of geokit-rails, it is not possible to add a `where` clause\nusing the _distance_ column. I've tried many different ways to do this and didn't get it working.\n\nOne would expect to build a query like this :\n\n```ruby\nscoped  = Location.by_distance(:origin =\u003e @somewhere)\nscoped  = scoped.where('distance \u003c= 5')\nresults = scoped.all\n```\n\nThis is not possible right now, it must be done in a single step like this :\n\n```ruby\nscoped  = Location.within(5, :origin =\u003e @somewhere)\nresults = scoped.all\n```\n\nEvery good idea that would help achieve this is very much welcome.\n\n### FINDING WITHIN A BOUNDING BOX\n\nIf you are displaying points on a map, you probably need to query for whatever falls within the rectangular bounds of the map:\n\n```ruby\nStore.in_bounds([sw_point,ne_point]).all\n```\n\nIf you want the query to return things that are located on the rectangular bounds, specify the `inclusive` option set to true:\n\n```ruby\nStore.in_bounds([sw_point,ne_point], :inclusive =\u003e true).all\n```\n\nThe input to `bounds` can be an array with the two points or a Bounds object. However you provide them, the order should always be the southwest corner, northeast corner of the rectangle. Typically, you will be getting the sw\\_point and ne\\_point from a map that is displayed on a web page.\n\nIf you need to calculate the bounding box from a point and radius, you can do that:\n\n```ruby\nbounds = Geokit::Bounds.from_point_and_radius(home,5)\nStore.in_bounds(bounds).all\n```\n\n----\n\n# What is following is from the previous _geokit-rails_ plugin.\n\n\u003e **It has not been tested with Rails 3 nor with this version of the gem.**\n**Most of it should work, but it is not sure**\n\n\n## USING INCLUDES\n\nYou can use includes along with your distance finders:\n\n```ruby\nstores = Store.within(5, :origin=\u003ehome).includes([:reviews,:cities]).order('distance asc').all\n```\n\n*However*, ActiveRecord drops the calculated distance column when you use include. So, if you need to use the distance column, you'll have to re-calculate it post-query in Ruby:\n\n```ruby\nstores.sort_by{|s| s.distance_to(home)}\n```\n\nIn this case, you may want to just use the bounding box condition alone in your SQL (there's no use calculating the distance twice):\n\n```ruby\nbounds=Geokit::Bounds.from_point_and_radius(home,5)\nstores=Store.includes([:reviews,:cities]).in_bounds(bounds)\nstores.sort_by{|s| s.distance_to(home)}\n```\n\n## USING :through\n\nYou can also specify a model as mappable \"through\" another associated model. In other words, that associated model is the actual mappable model with \"lat\" and \"lng\" attributes, but this \"through\" model can still utilize all of the above find methods to search for records.\n\n```ruby\nclass Location \u003c ActiveRecord::Base\n  belongs_to :locatable, :polymorphic =\u003e true\n  acts_as_mappable\nend\n```\n\n```ruby\nclass Company \u003c ActiveRecord::Base\n  has_one :location, :as =\u003e :locatable  # also works for belongs_to associations\n  acts_as_mappable :through =\u003e :location\nend\n```\n\nThen you can still call:\n\n```ruby\nCompany.within(distance, :origin =\u003e @somewhere)\n```\n\nYou can also give :through a hash if your location is nested deep. For example, given:\n\n```ruby\nclass House\n  acts_as_mappable\nend\n```\n\n```ruby\nclass Family\n  belongs_to :house\nend\n```\n\n```ruby\nclass Person\n  belongs_to :family\n  acts_as_mappable :through =\u003e { :family =\u003e :house }\nend\n```\n\nRemember that the notes above about USING INCLUDES apply to the results from\nthis find, since an include is automatically used.\n\n## IP GEOCODING\n\nYou can obtain the location for an IP at any time using the geocoder\nas in the following example:\n\n```ruby\nlocation = IpGeocoder.geocode('12.215.42.19')\n```\n\nwhere Location is a GeoLoc instance containing the latitude,\nlongitude, city, state, and country code.  Also, the success\nvalue is true.\n\nIf the IP cannot be geocoded, a GeoLoc instance is returned with a\nsuccess value of false.\n\nIt should be noted that the IP address needs to be visible to the\nRails application.  In other words, you need to ensure that the\nrequesting IP address is forwarded by any front-end servers that\nare out in front of the Rails app.  Otherwise, the IP will always\nbe that of the front-end server.\n\nThe Multi-Geocoder will also geocode IP addresses and provide\nfailover among multiple IP geocoders. Just pass in an IP address for the\nparameter instead of a street address. Eg:\n\n```ruby\nlocation = Geocoders::MultiGeocoder.geocode('12.215.42.19')\n```\n\nThe MultiGeocoder class requires 2 configuration setting for the provider order.\nOrdering is done through `Geokit::Geocoders::provider_order` and\n`Geokit::Geocoders::ip_provider_order`, found in\n`config/initializers/geokit_config.rb`. If you don't already have a\n`geokit_config.rb` file, the plugin creates one when it is first installed.\n\n\n## IP GEOCODING HELPER\n\nA class method called geocode_ip_address has been mixed into the\nActionController::Base.  This enables before_action style lookup of\nthe IP address.  Since it is a filter, it can accept any of the\navailable filter options.\n\nUsage is as below:\n\n```ruby\nclass LocationAwareController \u003c ActionController::Base\n  geocode_ip_address\nend\n```\n\nA first-time lookup will result in the GeoLoc class being stored\nin the session as `:geo_location` as well as in a cookie called\n`:geo_session`.  Subsequent lookups will use the session value if it\nexists or the cookie value if it doesn't exist.  The last resort is\nto make a call to the web service.  Clients are free to manage the\ncookie as they wish.\n\nThe intent of this feature is to be able to provide a good guess as\nto a new visitor's location.\n\n## INTEGRATED FIND AND GEOCODING\n\nGeocoding has been integrated with the finders enabling you to pass\na physical address or an IP address.  This would look the following:\n\n```ruby\nLocation.farthest(:origin =\u003e '217.15.10.9')\nLocation.farthest(:origin =\u003e 'Irving, TX')\n```\n\nwhere the IP or physical address would be geocoded to a location and\nthen the resulting latitude and longitude coordinates would be used\nin the find.  This is not expected to be common usage, but it can be\ndone nevertheless.\n\n## ADDRESS GEOCODING\n\nGeocoding is provided by the Geokit gem, which is required for this plugin.\nSee the top of this file for instructions on installing the Geokit gem.\n\nGeokit can geocode addresses using multiple geocodeing web services.\nGeokit supports services like Google, Yahoo, and Geocoder.us, and more --\nsee the Geokit gem API for a complete list.\n\nThese geocoder services are made available through the following classes:\nGoogleGeocoder, YahooGeocoder, UsGeocoder, CaGeocoder, and GeonamesGeocoder.\nFurther, an additional geocoder class called MultiGeocoder incorporates an ordered failover\nsequence to increase the probability of successful geocoding.\n\nAll classes are called using the following signature:\n\n```ruby\ninclude Geokit::Geocoders\nlocation = XxxGeocoder.geocode(address)\n```\n\nwhere you replace Xxx Geocoder with the appropriate class.  A GeoLoc\ninstance is the result of the call.  This class has a \"success\"\nattribute which will be true if a successful geocoding occurred.\nIf successful, the lat and lng properties will be populated.\n\nGeocoders are named with the convention NameGeocoder.  This\nnaming convention enables Geocoder to auto-detect its sub-classes\nin order to create methods called `name_geocoder(address)` so that\nall geocoders can be called through the base class.  This is done\npurely for convenience; the individual geocoder classes are expected\nto be used independently.\n\nThe MultiGeocoder class requires the configuration of a provider\norder which dictates what order to use the various geocoders.  Ordering\nis done through `Geokit::Geocoders::provider_order`, found in\n`config/initializers/geokit_config.rb`.\n\nIf you don't already have a `geokit_config.rb` file, the plugin creates one\nwhen it is first installed.\n\nMake sure your failover configuration matches the usage characteristics\nof your application -- for example, if you routinely get bogus input to\ngeocode, your code will be much slower if you have to failover among\nmultiple geocoders before determining that the input was in fact bogus.\n\nThe Geocoder.geocode method returns a GeoLoc object. Basic usage:\n\n```ruby\nloc=Geocoder.geocode('100 Spear St, San Francisco, CA')\nif loc.success\n  puts loc.lat\n  puts loc.lng\n  puts loc.full_address\nend\n```\n\n## REVERSE GEOCODING\n\nCurrently, only the Google Geocoder supports reverse geocoding.\nPass the lat/lng as a string, array or LatLng instance:\n\n```ruby\nres=Geokit::Geocoders::GoogleGeocoder.reverse_geocode \"37.791821,-122.394679\"\n# =\u003e #\u003cGeokit::GeoLoc:0x558ed0 ...\nres.full_address\n# =\u003e \"101-115 Main St, San Francisco, CA 94105, USA\"\n```\n\nThe address will usually appear as a range, as it does in the above example.\n\n\n## INTEGRATED FIND WITH ADDRESS GEOCODING\n\nJust has you can pass an IP address directly into an ActiveRecord finder\nas the origin, you can also pass a physical address as the origin:\n\n```ruby\nLocation.closest(:origin =\u003e '100 Spear st, San Francisco, CA')\n```\n\nwhere the physical address would be geocoded to a location and then the\nresulting latitude and longitude coordinates would be used in the\nfind.\n\nNote that if the address fails to geocode, the find method will raise an\nActiveRecord::GeocodeError you must be prepared to catch. Alternatively,\nYou can geocoder the address beforehand, and pass the resulting lat/lng\ninto the finder if successful.\n\n## Auto Geocoding\n\nIf your geocoding needs are simple, you can tell your model to automatically\ngeocode itself on create:\n\n```ruby\nclass Store \u003c ActiveRecord::Base\n  acts_as_mappable :auto_geocode=\u003etrue\nend\n```\n\nIt takes two optional params:\n\n```ruby\nclass Store \u003c ActiveRecord::Base\n  acts_as_mappable :auto_geocode=\u003e{:field=\u003e:address, :error_message=\u003e'Could not geocode address'}\nend\n```\n\n. . . which is equivalent to:\n\n```ruby\nclass Store \u003c\u003c ActiveRecord::Base\n  acts_as_mappable\n  before_validation :geocode_address, :on =\u003e :create\n\n  private\n  def geocode_address\n    geo=Geokit::Geocoders::MultiGeocoder.geocode (address)\n    errors.add(:address, \"Could not Geocode address\") if !geo.success\n    self.lat, self.lng = geo.lat,geo.lng if geo.success\n  end\nend\n```\n\nIf you need any more complicated geocoding behavior for your model, you should roll your own\n`before_validate` callback.\n\n\n## Distances, headings, endpoints, and midpoints\n\n```ruby\ndistance = home.distance_from(work, :units=\u003e:miles)\nheading  = home.heading_to(work) # result is in degrees, 0 is north\nendpoint = home.endpoint(90,2)  # two miles due east\nmidpoint = home.midpoint_to(work)\n```\n\n## Cool stuff you can do with bounds\n\n```ruby\nbounds = Bounds.new(sw_point,ne_point)\nbounds.contains?(home)\nputs bounds.center\n```\n\nHOW TO . . .\n=================================================================================\n\nA few quick examples to get you started ....\n\n## How to install the Geokit Rails plugin\n(See the very top of this file)\n\n## How to find all stores within a 10-mile radius of a given lat/lng\n1. ensure your stores table has lat and lng columns with numeric or float\n   datatypes to store your latitude/longitude\n\n2. use `acts_as_mappable` on your store model:\n3.\n  ```ruby\n  class Store \u003c ActiveRecord::Base\n     acts_as_mappable\n     ...\n  end\n  ```\n\n3. finders now have extra capabilities:\n\n  ```ruby\n  Store.find(:all, :origin =\u003e[32.951613,-96.958444], :within=\u003e10)\n  ```\n\n## How to geocode an address\n\n1. configure your geocoder key(s) in `config/initializers/geokit_config.rb`\n\n2. also in `geokit_config.rb`, make sure that `Geokit::Geocoders::provider_order` reflects the\n   geocoder(s). If you only want to use one geocoder, there should\n   be only one symbol in the array. For example:\n\n  ```ruby\n  Geokit::Geocoders::provider_order=[:google]\n  ```\n\n3. Test it out in script/console\n\n  ```ruby\n  include Geokit::Geocoders\n  res = MultiGeocoder.geocode('100 Spear St, San Francisco, CA')\n  puts res.lat\n  puts res.lng\n  puts res.full_address\n  ```\n\n    ... etc. The return type is GeoLoc, see the API for\n    all the methods you can call on it.\n\n## How to find all stores within 10 miles of a given address\n\n1. as above, ensure your table has the lat/lng columns, and you've\n   applied `acts_as_mappable` to the Store model.\n\n2. configure and test out your geocoder, as above\n\n3. pass the address in under the :origin key\n\n  ```ruby\n  Store.find(:all, :origin=\u003e'100 Spear st, San Francisco, CA', :within=\u003e10)\n  ```\n\n4. you can also use a zipcode, or anything else that's geocodable:\n\n  ```ruby\n  Store.find(:all, :origin=\u003e'94117', :conditions=\u003e'distance\u003c10')\n  ```\n\n## How to sort a query by distance from an origin\n\nYou now have access to a 'distance' column, and you can use it\nas you would any other column. For example:\n\n```ruby\nStore.find(:all, :origin=\u003e'94117', :order=\u003e'distance')\n```\n\n## How to sort elements of an array according to distance from a common point\n\nUsually, you can do your sorting in the database as part of your find call.\nIf you need to sort things post-query, you can do so:\n\n```ruby\nstores = Store.all\nstores.sort_by{|s| s.distance_to(home)}\n```\n\nObviously, each of the items in the array must have a latitude/longitude so\nthey can be sorted by distance.\n\n## Database indexes\n\nMySQL can't create indexes on a calculated field such as those Geokit uses to\ncalculate distance based on latitude/longitude values for a record.  However,\nindexing the lat and lng columns does improve Geokit distance calculation\nperformance since the lat and lng columns are used in a straight comparison\nfor distance calculation.  Assuming a Page model that is incorporating the\nGeokit plugin the migration would be as follows.\n\n```ruby\nclass AddIndexToPageLatAndLng \u003c ActiveRecord::Migration\n\n  def self.up\n    add_index  :pages, [:lat, :lng]\n  end\n\n  def self.down\n    remove_index  :pages, [:lat, :lng]\n  end\nend\n```\n\n## Database Compatability\n\n* Geokit works with MySQL (tested with version 5.0.41), PostgreSQL (tested with version 8.2.6) and Microsoft SQL Server (tested with 2000).\n* Geokit is known to *not* work with Postgres versions under 8.1 -- it uses the least() function.\n\n\n## HIGH-LEVEL NOTES ON WHAT'S WHERE\n\n`acts_as_mappable.rb`, as you'd expect, contains the ActsAsMappable\nmodule which gets mixed into your models to provide the\nlocation-based finder goodness.\n\n`ip_geocode_lookup.rb` contains the before_action helper method which\nenables auto lookup of the requesting IP address.\n\n### The Geokit gem provides the building blocks of distance-based operations:\n\nThe Mappable module, which provides basic\ndistance calculation methods, i.e., calculating the distance\nbetween two points.\n\nThe LatLng class  is a simple container for latitude and longitude, but\nit's made more powerful by mixing in the above-mentioned Mappable\nmodule -- therefore, you can calculate easily the distance between two\nLatLng objects with `distance = first.distance_to(other)`\n\nGeoLoc represents an address or location which\nhas been geocoded. You can get the city, zipcode, street address, etc.\nfrom a GeoLoc object. GeoLoc extends LatLng, so you also get lat/lng\nAND the Mappable module goodness for free.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeokit%2Fgeokit-rails","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgeokit%2Fgeokit-rails","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeokit%2Fgeokit-rails/lists"}