Giter Site home page Giter Site logo

geokit / geokit-rails Goto Github PK

View Code? Open in Web Editor NEW
1.6K 1.6K 243.0 389 KB

Official Geokit plugin for Rails/ActiveRecord. Provides location-based goodness for your Rails app. Requires the Geokit gem.

License: MIT License

Ruby 93.50% CSS 0.03% HTML 6.47%

geokit-rails's Introduction

Geokit

Gem Version Build Status Coverage Status Reviewed by Hound Code Climate

DESCRIPTION

The Geokit gem provides:

  • Distance calculations between two points on the earth. Calculate the distance in miles, kilometers, meters, or nautical miles, with all the trigonometry abstracted away by Geokit.
  • Geocoding from multiple providers. It supports Google, Yahoo, and Geocoder.ca geocoders, and others. It provides a uniform response structure from all of them. It also provides a fail-over mechanism, in case your input fails to geocode in one service.
  • Rectangular bounds calculations: is a point within a given rectangular bounds?
  • Heading and midpoint calculations

Combine this gem with the geokit-rails to get location-based finders for your Rails app.

COMMUNICATION

  • If you need help, use Stack Overflow. (Tag 'geokit' and we'll be alerted)
  • If you found a bug, use GitHub issues.
  • If you have an idea, use GitHub issues.
  • If you'd like to ask a general question, use GitHub issues.
  • If you want to contribute, submit a pull request.

INSTALL

gem install geokit

SUPPORTED GEOCODERS

"regular" address geocoders

  • Yahoo BOSS - requires an API key.
  • Geocoder.ca - for Canada; may require authentication as well.
  • Geonames - a free geocoder
  • Bing
  • Yandex
  • MapQuest
  • Geocod.io
  • OpenStreetMap (Nominatim)
  • Mapbox - requires an access token
  • OpenCage - requires an API key

address geocoders that also provide reverse geocoding

  • Google - Supports multiple results and bounding box/country code biasing. Also supports Maps API for Business keys; see the configuration section below.
  • FCC
  • OpenStreetMap (Nominatim)
  • Mapbox
  • OpenCage

IP address geocoders

  • IP - geocodes an IP address using hostip.info's web service.
  • Geoplugin.net -- another IP address geocoder
  • RIPE
  • MaxMind
  • Ipstack
  • IP-API.com

HTTPS-supporting geocoders

  • Google
  • Yahoo
  • Bing
  • FCC
  • MapQuest
  • Mapbox
  • OpenCage

Options to control the use of HTTPS are described below in the Configuration section.

QUICK START

    irb> require 'rubygems'
    irb> require 'geokit'
    irb> a=Geokit::Geocoders::GoogleGeocoder.geocode '140 Market St, San Francisco, CA'
    irb> a.ll
     => 37.79363,-122.396116
    irb> b=Geokit::Geocoders::GoogleGeocoder.geocode '789 Geary St, San Francisco, CA'
    irb> b.ll
     => 37.786217,-122.41619
    irb> a.distance_to(b)
     => 1.21120007413626
    irb> a.heading_to(b)
    => 244.959832435678
    irb(main):006:0> c=a.midpoint_to(b)      # what's halfway from a to b?
    irb> c.ll
    => "37.7899239257175,-122.406153503469"
    irb(main):008:0> d=c.endpoint(90,10)     # what's 10 miles to the east of c?
    irb> d.ll
    => "37.7897825005142,-122.223214776155"

FYI, that .ll method means "latitude longitude".

See the RDOC more more ... there are also operations on rectangular bounds (e.g., determining if a point is within bounds, find the center, etc).

CONFIGURATION

If you're using this gem by itself, here are the configuration options:

    # These defaults are used in Geokit::Mappable.distance_to and in acts_as_mappable
    Geokit::default_units = :miles # others :kms, :nms, :meters
    Geokit::default_formula = :sphere

    # This is the timeout value in seconds to be used for calls to the geocoder web
    # services.  For no timeout at all, comment out the setting.  The timeout unit
    # is in seconds.
    Geokit::Geocoders::request_timeout = 3

    # This setting can be used if web service calls must be routed through a proxy.
    # These setting can be nil if not needed, otherwise, a valid URI must be
    # filled in at a minimum.  If the proxy requires authentication, the username
    # and password can be provided as well.
    Geokit::Geocoders::proxy = 'https://user:password@host:port'

    # This setting can be used if a web service blocks requests by certain user agents.
    # If not set Geokit uses the default useragent header set by the different net adapter libs.
    Geokit::Geocoders::useragent = 'my agent string'

    # This is your yahoo application key for the Yahoo Geocoder.
    # See http://developer.yahoo.com/faq/index.html#appid
    # and http://developer.yahoo.com/maps/rest/V1/geocode.html
    Geokit::Geocoders::YahooGeocoder.key = 'REPLACE_WITH_YOUR_YAHOO_KEY'
    Geokit::Geocoders::YahooGeocoder.secret = 'REPLACE_WITH_YOUR_YAHOO_SECRET'

    # This is your Google Maps geocoder keys (all optional).
    # See http://www.google.com/apis/maps/signup.html
    # and http://www.google.com/apis/maps/documentation/#Geocoding_Examples
    Geokit::Geocoders::GoogleGeocoder.client_id = ''
    Geokit::Geocoders::GoogleGeocoder.cryptographic_key = ''
    Geokit::Geocoders::GoogleGeocoder.channel = ''

    # You can also use the free API key instead of signed requests
    # See https://developers.google.com/maps/documentation/geocoding/#api_key
    Geokit::Geocoders::GoogleGeocoder.api_key = ''

    # You can also set multiple API KEYS for different domains that may be directed to this same application.
    # The domain from which the current user is being directed will automatically be updated for Geokit via
    # the GeocoderControl class, which gets it's begin filter mixed into the ActionController.
    # You define these keys with a Hash as follows:
    #Geokit::Geocoders::google = { 'rubyonrails.org' => 'RUBY_ON_RAILS_API_KEY', 'ruby-docs.org' => 'RUBY_DOCS_API_KEY' }

    # This is your authorization key for geocoder.ca.
    # To use the free service, the value can be set to nil or false.  For
    # usage tied to an account, set the value to the key obtained from
    # Geocoder.ca.
    # See http://geocoder.ca
    # and http://geocoder.ca/?register=1
    Geokit::Geocoders::CaGeocoder.key = 'KEY'

    # This is your username key for geonames.
    # To use this service either free or premium, you must register a key.
    # See http://www.geonames.org
    Geokit::Geocoders::GeonamesGeocoder.key = 'KEY'

    # This is your access key for ipstack.
    # To use this service either free or premium, you must register a key.
    # See https://ipstack.com
    Geokit::Geocoders::IpstackGeocoder.api_key = 'API_KEY'

    # This is your api key for ip-api.com.
    # For the free version (with rate limits), leave api_key unset.
    # See https://ip-api.com/
    Geokit::Geocoders::IpApiGeocoder.key = ''

    # Most other geocoders need either no setup or a key
    Geokit::Geocoders::BingGeocoder.key = ''
    Geokit::Geocoders::MapQuestGeocoder.key = ''
    Geokit::Geocoders::YandexGeocoder.key = ''
    Geokit::Geocoders::MapboxGeocoder.key = 'ACCESS_TOKEN'
    Geokit::Geocoders::OpencageGeocoder.key = 'some_api_key'

    # Geonames has a free service and a premium service, each using a different URL
    # GeonamesGeocoder.premium = true will use http://ws.geonames.net (premium)
    # GeonamesGeocoder.premium = false will use http://api.geonames.org (free)
    Geokit::Geocoders::GeonamesGeocoder.premium = false

    # require "external_geocoder.rb"
    # Please see the section "writing your own geocoders" for more information.
    # Geokit::Geocoders::external_key = 'REPLACE_WITH_YOUR_API_KEY'

    # This is the order in which the geocoders are called in a failover scenario
    # If you only want to use a single geocoder, put a single symbol in the array.
    #
    # Valid symbols are: :bing, :ca, :fcc, :geocodio, :geonames, :google,
    # :map_quest, :mapbox, :maxmind, :opencage, :osm, :us, :yahoo, and :yandex.
    #
    # Be aware that there are Terms of Use restrictions on how you can use the
    # various geocoders.  Make sure you read up on relevant Terms of Use for each
    # geocoder you are going to use.
    Geokit::Geocoders::provider_order = [:google,:us]

    # The IP provider order.
    #
    # Valid symbols are :ipstack, :geo_plugin, :ip, and :ripe.
    #
    # As before, make sure you read up on relevant Terms of Use for each.
    # Geokit::Geocoders::ip_provider_order = [:external,:geo_plugin,:ip]

	# Disable HTTPS globally.  This option can also be set on individual
	# geocoder classes.
    Geokit::Geocoders::secure = false

    # Control verification of the server certificate for geocoders using HTTPS
    Geokit::Geocoders::ssl_verify_mode = OpenSSL::SSL::VERIFY_(PEER/NONE)
    # Setting this to VERIFY_NONE may be needed on systems that don't have
    # a complete or up to date root certificate store. Only applies to
    # the Net::HTTP adapter.

Google Geocoder Tricks

The Google Geocoder sports a number of useful tricks that elevate it a little bit above the rest of the currently supported geocoders. For starters, it returns a suggested_bounds property for all your geocoded results, so you can more easily decide where and how to center a map on the places you geocode. Here's a quick example:

    irb> res = Geokit::Geocoders::GoogleGeocoder.geocode('140 Market St, San Francisco, CA')
    irb> pp res.suggested_bounds
    #<Geokit::Bounds:0x53b36c
     @ne=#<Geokit::LatLng:0x53b204 @lat=37.7968528, @lng=-122.3926933>,
     @sw=#<Geokit::LatLng:0x53b2b8 @lat=37.7905576, @lng=-122.3989885>>

In addition, you can use viewport or country code biasing to make sure the geocoders prefers results within a specific area. Say we wanted to geocode the city of Toledo in Spain. A normal geocoding query would look like this:

    irb> res = Geokit::Geocoders::GoogleGeocoder.geocode('Toledo')
    irb> res.full_address
    => "Toledo, OH, USA"

Not exactly what we were looking for. We know that Toledo is in Spain, so we can tell the Google Geocoder to prefer results from Spain first, and then wander the Toledos of the world. To do that, we have to pass Spain's ccTLD (country code top-level domain) to the :bias option of the geocode method. You can find a comprehensive list of all ccTLDs here: http://en.wikipedia.org/wiki/CcTLD.

    irb> res = Geokit::Geocoders::GoogleGeocoder.geocode('Toledo', :bias => 'es')
    irb> res.full_address
    => "Toledo, Toledo, Spain"

Alternatively, we can specify the geocoding bias as a bounding box object. Say we wanted to geocode the Winnetka district in Los Angeles.

    irb> res = Geokit::Geocoders::GoogleGeocoder.geocode('Winnetka')
    irb> res.full_address
    => "Winnetka, IL, USA"

Not it. What we can do is tell the geocoder to return results only from in and around LA.

    irb> la_bounds = Geokit::Geocoders::GoogleGeocoder.geocode('Los Angeles').suggested_bounds
    irb> res = Geokit::Geocoders::GoogleGeocoder.geocode('Winnetka', :bias => la_bounds)
    irb> res.full_address
    => "Winnetka, California, USA"

Another option is to use Component Filtering as described at https://developers.google.com/maps/documentation/geocoding/intro#ComponentFiltering. To do that supply the :components option to the geocode method. This option should be a hash with keys corresponding to desired component names.

Suppose we'd like to geocode string 'Austin'. Regularly, Google would return 'Austin, TX, USA' for such a query. Not with component filtering:

    irb>res = Geokit::Geocoders::GoogleGeocoder.geocode("austin", components: { administrative_area: 'IL', country: 'US' })
    irb>res.full_address
    => "Austin, Chicago, IL, USA"

The Multigeocoder

Multi Geocoder - provides failover for the physical location geocoders, and also IP address geocoders. Its configured by setting Geokit::Geocoders::provider_order, and Geokit::Geocoders::ip_provider_order. You should call the Multi-Geocoder with its :geocode method, supplying one address parameter which is either a real street address, or an ip address. For example:

    Geokit::Geocoders::MultiGeocoder.geocode("900 Sycamore Drive")

    Geokit::Geocoders::MultiGeocoder.geocode("12.12.12.12")

    Geokit::Geocoders::MultiGeocoder.geocode("Hamburg, Germany", :provider_order => [:osm, :mapbox, :google])

MULTIPLE RESULTS

Some geocoding services will return multiple results if the there isn't one clear result. Geoloc can capture multiple results through its "all" method.

    irb> geo=Geokit::Geocoders::GoogleGeocoder.geocode("900 Sycamore Drive")
    irb> geo.full_address
    => "900 Sycamore Dr, Arkadelphia, AR 71923, USA"
    irb> geo.all.size
    irb> geo.all.each { |e| puts e.full_address }
    900 Sycamore Dr, Arkadelphia, AR 71923, USA
    900 Sycamore Dr, Burkburnett, TX 76354, USA
    900 Sycamore Dr, TN 38361, USA
    ....

geo.all is just an array of additional Geolocs, so do what you want with it. If you call .all on a geoloc that doesn't have any additional results, you will get an array of one.

NOTES ON WHAT'S WHERE

mappable.rb contains the Mappable module, which provides basic distance calculation methods, i.e., calculating the distance between two points.

LatLng is a simple container for latitude and longitude, but it's made more powerful by mixing in the above-mentioned Mappable module -- therefore, you can calculate easily the distance between two LatLng objects with distance = first.distance_to(other)

GeoLoc represents an address or location which has been geocoded. You can get the city, zipcode, street address, etc. from a GeoLoc object. GeoLoc extends LatLng, so you also get lat/lng AND the Mappable module goodness for free.

geocoders.rb contains all the geocoder implementations. All the geocoders inherit from a common base (class Geocoder) and implement the private method do_geocode.

WRITING YOUR OWN GEOCODERS

If you would like to write your own geocoders, you can do so by requiring 'geokit' or 'geokit/geocoders.rb' in a new file and subclassing the base class (which is class "Geocoder"). You must then also require such external file back in your main geokit configuration.

  require "geokit"

  module Geokit
    module Geocoders

      # and use :my to specify this geocoder in your list of geocoders.
      class MyGeocoder < Geocoder

        # Use via: Geokit::Geocoders::MyGeocoder.key = 'MY KEY'
        config :key

        private

        def self.do_geocode(address, options = {})
          # Main geocoding method
        end

        def self.parse_json(json)
          # Helper method to parse http response. See geokit/geocoders.rb.
        end
      end

    end
  end

geokit-rails's People

Contributors

albanpeignier avatar brandoncc avatar brennandunn avatar denisahearn avatar dreamcat4 avatar forgotpw1 avatar glennpow avatar gustin avatar jensb avatar jlecour avatar jonnyandrew avatar josevalim avatar mischa avatar mnoack avatar monde avatar mquy avatar nikosmichas avatar nneal avatar olleolleolle avatar pex avatar pklingem avatar pzgz avatar richessler avatar roccogalluzzo avatar ryankopf avatar sethpollack avatar sionide21 avatar thomdixon avatar wspruijt avatar zeke avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

geokit-rails's Issues

Error: syntax error near DESC

Been trying to fix some test errors on the Rails4 branch. Just compiling some info here.

ActsAsMappableTest#test_scoped_distance_column_in_select
ActiveRecord::StatementInvalid: PG::SyntaxError: ERROR:  syntax error at or near "DESC"
LINE 1: ...ations"."company_id" = $1  ORDER BY (ACOS(least(1 DESC, COS(...

also occurs in:

ActsAsMappableTest#test_distance_column_in_select
ActsAsMappableTest#test_ip_geocoded_distance_column_in_select

Occuring on Postgres and MySQL

It appears that the problem is introduced when ActiveRecord splits strings with a comma to inject ASC/DESC here: https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation/query_methods.rb#L994

I'm not sure if it's truly an ActiveRecord error or if we are passing in a malformed order string.

The order passed in is:

"\n          (ACOS(least(1,COS(0.5745378329739577)*COS(-1.692244085410541)*COS(RADIANS(locations.lat))*COS(RADIANS(locations.lng))+\n          COS(0.5745378329739577)*SIN(-1.692244085410541)*COS(RADIANS(locations.lat))*SIN(RADIANS(locations.lng))+\n          SIN(0.5745378329739577)*SIN(RADIANS(locations.lat))))*3963.19)\n          asc"

@mnoack can I assume that all the tests on Rails4 branch are up to date?

acts_as_mappable not getting correct database adapter_name

When I try and use the acts_as_mappable integration, I always get the error message 'jdbc' is not a supported adapter. Does this mean that this plugin will not work with jruby?

It looks like connection.adapter_name in acts_as_mappable fails if the name is 'jdbc' but hardcoding mySQL seems to work... I'm not sure if that is the correct solution. Any advice would be appreciated.

Missing 'distance' field on returned instances

As documented:

The plug-in creates a calculated distance field on AR instances that have been retrieved throw a Geokit location query. By default, these fields are known as "distance" but this can be changed through the :distance_field_name key.

"distance" field on returned objects is not available.

Find Query

Is it possible to find Location within a country.

For example if I give input as 36.03,-115.23(this reverse gecodes to Las Vegas , US)

is it possible to find Locations within United States or for that matter within Las Vegas

Missing gem warning

I have geokit-rails installed, along with the geokit gem as outlined in the README. However, when I run rake gems:install I get the following error:

WARNING: geokit-rails requires the Geokit gem.

I've also tried adding require 'geokit' to the top of my config/initializers/geokit_config.rb file, but to no avail. I can actually stop the warning if I add that line to the top of the plugin's init.rb file, but I'm not keen on poking into the plugin code to make it behave. Could you please address these warnings? Thank you!

.order('distance DESC') fails with ActiveRecord::StatementInvalid: Mysql::Error: Unknown column 'distance' in 'order clause'

Barn.within(5, :origin => "30093").order('distance DESC')

This produces:

Barn Load (0.3ms)  SELECT `contacts`.* FROM `contacts` WHERE `contacts`.`type` IN ('Barn') AND ((
 (ACOS(least(1,COS(0.591845095540716)*COS(-1.4692258158522673)*COS(RADIANS(contacts.lat))*COS(RADIANS(contacts.lng))+
 COS(0.591845095540716)*SIN(-1.4692258158522673)*COS(RADIANS(contacts.lat))*SIN(RADIANS(contacts.lng))+
 SIN(0.591845095540716)*SIN(RADIANS(contacts.lat))))*3963.19)
 <= 5)) ORDER BY distance DESC
ActiveRecord::StatementInvalid: Mysql::Error: Unknown column 'distance' in 'order clause': SELECT `contacts`.* FROM `contacts`  WHERE `contacts`.`type` IN ('Barn') AND ((
          (ACOS(least(1,COS(0.591845095540716)*COS(-1.4692258158522673)*COS(RADIANS(contacts.lat))*COS(RADIANS(contacts.lng))+
          COS(0.591845095540716)*SIN(-1.4692258158522673)*COS(RADIANS(contacts.lat))*SIN(RADIANS(contacts.lng))+
          SIN(0.591845095540716)*SIN(RADIANS(contacts.lat))))*3963.19)
          <= 5)) ORDER BY distance DESC
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/activerecord-3.2.14/lib/active_record/connection_adapters/mysql_adapter.rb:308:in `query'
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/activerecord-3.2.14/lib/active_record/connection_adapters/mysql_adapter.rb:308:in `block in exec_without_stmt'
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/activerecord-3.2.14/lib/active_record/connection_adapters/abstract_adapter.rb:280:in `block in log'
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/activesupport-3.2.14/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/activerecord-3.2.14/lib/active_record/connection_adapters/abstract_adapter.rb:275:in `log'
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/activerecord-3.2.14/lib/active_record/connection_adapters/mysql_adapter.rb:307:in `exec_without_stmt'
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/activerecord-3.2.14/lib/active_record/connection_adapters/mysql_adapter.rb:290:in `exec_query'
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/activerecord-3.2.14/lib/active_record/connection_adapters/mysql_adapter.rb:430:in `select'
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/activerecord-3.2.14/lib/active_record/connection_adapters/abstract/database_statements.rb:18:in `select_all'
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/activerecord-3.2.14/lib/active_record/connection_adapters/abstract/query_cache.rb:63:in `select_all'
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/activerecord-3.2.14/lib/active_record/querying.rb:38:in `block in find_by_sql'
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/activerecord-3.2.14/lib/active_record/explain.rb:41:in `logging_query_plan'
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/activerecord-3.2.14/lib/active_record/querying.rb:37:in `find_by_sql'
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/activerecord-3.2.14/lib/active_record/relation.rb:171:in `exec_queries'
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/activerecord-3.2.14/lib/active_record/relation.rb:160:in `block in to_a'
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/activerecord-3.2.14/lib/active_record/explain.rb:41:in `logging_query_plan'
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/activerecord-3.2.14/lib/active_record/relation.rb:159:in `to_a'
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/activerecord-3.2.14/lib/active_record/relation.rb:498:in `inspect'
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/railties-3.2.14/lib/rails/commands/console.rb:47:in `start'
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/railties-3.2.14/lib/rails/commands/console.rb:8:in `start'
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/railties-3.2.14/lib/rails/commands.rb:41:in `<top (required)>'
        from script/rails:6:in `require'
        from script/rails:6:in `<main>'

Doing the order directly in the search works, but the SQL doesn't appear to do anything with distance:

Barn.within(5, :origin => "30093", :order => 'distance desc')
Barn Load (4.3ms)  SELECT `contacts`.* FROM `contacts` WHERE `contacts`.`type` IN ('Barn') AND ((
 (ACOS(least(1,COS(0.591845095540716)*COS(-1.4692258158522673)*COS(RADIANS(contacts.lat))*COS(RADIANS(contacts.lng))+
 COS(0.591845095540716)*SIN(-1.4692258158522673)*COS(RADIANS(contacts.lat))*SIN(RADIANS(contacts.lng))+
 SIN(0.591845095540716)*SIN(RADIANS(contacts.lat))))*3963.19)
 <= 5))

And then the distance column isn't available:

barns[0].distance
NoMethodError: undefined method `distance' for #<Barn:0xb5a525c>
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/activemodel-3.2.14/lib/active_model/attribute_methods.rb:407:in `method_missing'
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/activerecord-3.2.14/lib/active_record/attribute_methods.rb:149:in `method_missing'
        from (irb):9
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/railties-3.2.14/lib/rails/commands/console.rb:47:in `start'
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/railties-3.2.14/lib/rails/commands/console.rb:8:in `start'
        from /home/riding/.rvm/gems/ruby-1.9.3-p362@rr-3xmid/gems/railties-3.2.14/lib/rails/commands.rb:41:in `<top (required)>'
        from script/rails:6:in `require'
        from script/rails:6:in `<main>'

Here's relevant bits from the model:

acts_as_mappable :auto_geocode => true, :distance_field_name => :distance

I tried adding attr_accessor :distance and attr_accessible :distance to no avail.

Here's my Gemfile:

source 'https://rubygems.org'

gem 'rails', '3.2.14'

gem 'mysql'

# Gems used only for assets and not required
# in production environments by default.
group :assets do
  gem 'sass-rails',   '~> 3.2.3'
  gem 'coffee-rails', '~> 3.2.1'
  # See https://github.com/sstephenson/execjs#readme for more supported runtimes
  gem 'therubyracer', :platforms => :ruby
  gem 'uglifier', '>= 1.0.3'
end

gem 'jquery-rails', '3.0.4'
gem 'twitter', '4.8.1'
gem 'haml', '2.2.6'
gem 'formtastic', '2.2.1'
gem 'json', '1.8.0'
gem 'tld', '0.6.4'
gem 'addressable', '2.1.0'
gem 'stringex', '2.1.0'
gem 'will_paginate', '~> 3.0.0'
gem 'geokit-rails', '2.0.1'
gem 'awesome_print', '1.1.0'
gem 'paperclip', '3.5.2'
gem 'gruff', '0.3.6'
gem 'rmagick', '2.11.0'

group :development, :test do
  gem 'rspec-rails', '~> 2.0'
  gem 'shoulda-matchers', '2.4.0'
  gem "capybara", '2.1.0'
  gem "webrick", '~> 1.3.1'
  gem "pry", '0.9.12.3'
end

group :test do
  gem 'database_cleaner', '1.1.1'
end

I would be happy to test additional things, but I'm not sure where to start digging.

Where is config file?

The README refers to file assets/api_keys_template for a default configuration file. This seems to be missing. I see no source for the configuration file anywhere in the source. I was expecting a rake task or some such to generate the default configuration file.

rake test failure

I'm trying to execute test, but it's failing with this message:
uninitialized constant MockPerson::MockFamily

DB=postgresql rake test
Here is an extract of backtrace

/var/lib/gems/1.8/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:105:in const_missing': uninitialized constant MockPerson::MockFamily (NameError) from /var/lib/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2199:incompute_type'
from /var/lib/gems/1.8/gems/activesupport-2.3.5/lib/active_support/core_ext/kernel/reporting.rb:11:in silence_warnings' from /var/lib/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2195:incompute_type'
from /var/lib/gems/1.8/gems/activerecord-2.3.5/lib/active_record/reflection.rb:156:in send' from /var/lib/gems/1.8/gems/activerecord-2.3.5/lib/active_record/reflection.rb:156:inklass'
from ./lib/geokit-rails/acts_as_mappable.rb:122:in end_of_reflection_chain' from ./lib/geokit-rails/acts_as_mappable.rb:64:inacts_as_mappable'
from ./test/../test/models/mock_person.rb:3
...

Select columns does not work ( :select=>'field1,field2')!

Example:

Model 1

class Point < ActiveRecord::Base
belongs_to :imageable, :polymorphic => true
acts_as_mappable
end

Model 2

class Product < ActiveRecord::Base
has_many :points, :as => :imageable
acts_as_mappable :through => :points
end

Controller

class ProductsController < ApplicationController
def near
@products = Product.all(:include => :points, :select => "title", :origin => origin, :within => distance)
respond_to do |format|
format.xml { render :xml => @products.to_xml(:include => :points) }
end
end
end

Using :select => "title" does not work - the rule is ignored (all fields are selected not just title).

FInd suggested bounds of a country by reverse geocoding

res = Geokit::Geocoders::GoogleGeocoder.reverse_geocode(params[:coordinate])
addresses = res.all
country = addresses.last

Above code correctly displays country as

{
"state_fips": null,
"is_us?": true,
"provider": "google",
"state": null,
"block_fips": null,
"ll": "37.09024,-95.712891",
"province": null,
"street_address": null,
"full_address": "United States",
"zip": null,
"precision": "country",
"district": null,
"country_code": "US",
"lat": 37.09024,
"city": null,
"lng": -95.712891,
"success": true,
"district_fips": null
}

How ever country.suggested_bounds is incorrectly found as
{"ne":{"lng":-115.229126,"lat":36.03131},"sw":{"lng":-115.231824,"lat":36.028612}}

Rails 3: ArgumentError (Unknown key(s): within, origin) / fix

I just started migrating my app to Rails 3 and for my old find syntax,
Court.all(:conditions => ["auctions_count > 0 AND id <> ?", @court.id], :origin => [@court.lat, @court.lng], :within => 150.0, :order => "auctions_count DESC", :limit => 5)
I get the following error, and provide an easy (and nasty) fix for it below.

ArgumentError (Unknown key(s): within, origin):
  activesupport (3.0.1) lib/active_support/core_ext/hash/keys.rb:43:in `assert_valid_keys'
  activerecord (3.0.1) lib/active_record/relation/spawn_methods.rb:89:in `apply_finder_options'
  activerecord (3.0.1) lib/active_record/relation/finder_methods.rb:143:in `all'
  activerecord (3.0.1) lib/active_record/base.rb:439:in `__send__'
  activerecord (3.0.1) lib/active_record/base.rb:439:in `all'
  (my controller)

It works when I monkey patch the following with an initializer.
module ActiveRecord
module SpawnMethods
VALID_FIND_OPTIONS = [ :conditions, :include, :joins, :limit, :offset, :extend,
:order, :select, :readonly, :group, :having, :from, :lock, :origin, :within ]
end
end

This works for me with

ruby 1.8.7 (2008-08-11 patchlevel 72) [i686-darwin9]

rails 3.0.1

geokit gem 1.5.0

geokit_rails plugin 1.?.? (says 1.1.4 in about.yml and 1.2.0 in CHANGELOG.rdoc, checked out November 21, 2010)

NoMethodError: undefined method `geo_scope' for #<Class... on Rails4

Hi guys, I'm trying to use this gem but I've a big issue.

my gemfile:
gem "geokit"
gem 'geokit-rails', '~> 2.0.0' # otherwise 1.14 (maybe)

the model:
class MyModel < ActiveRecord::Base
acts_as_mappable :units => :kms,
:distance_field_name => :distance,
:lat_column_name => :lat,
:lng_column_name => :lng
end

in console:
MyModel.geo_scope(within: location.range, origin: [location.lat, location.lng])

this is the output:
NoMethodError: undefined method geo_scope' for #<Class:0x007f9eaf632dd8> from .../.rvm/gems/ruby-2.0.0-p0/gems/activerecord-4.0.0/lib/active_record/dynamic_matchers.rb:22:inmethod_missing'

How can I fix it?

Thank you

No initializer created, defaults to miles despite specifying it in acts_as_mappable

I'm specifying kms as my unit as per the instructions, as below:

class Airport < ActiveRecord::Base
  attr_accessible :IATA_code, :ICAO_code, :name, :latitude, :longitude,
                  :city, :altitude_feet, :timezone_offset, :daylight_savings_time,
                  :openflight_airport_id

    acts_as_mappable :default_units => :kms,
                  :units => :kms,
                  :default_formula => :sphere,
                  :distance_field_name => :distance,
                  :lat_column_name => :latitude,
                  :lng_column_name => :longitude


end

But every distance_to calculation that I make on airport instances returns the distance in miles. There is no initialiser file, as installing the gem didn't put one in the right place.

'distance' field was gone away

I'm using geokit-rails 2.0.1. When I run:

Location.within(5, origin: [37.792,-122.393]).order("distance asc")

An error occurred:

PG::UndefinedColumn: ERROR:  column "distance" does not exist

Why does the field distance go away?

Error with Rails 4 and auto_geocode param : undefined method 'before_validation_on_create'

When I use the "auto_geocode" params of the acts_as_mappable method, I get the following error :

./.rvm/gems/ruby-1.9.3-p194/gems/activerecord-4.0.0/lib/active_record/dynamic_matchers.rb:22:in 'method_missing' : undefined method 'before_validation_on_create' for #<Class:0x007fcc7a24dc38> (NoMethodError)
from ./.rvm/gems/ruby-1.9.3-p194/gems/geokit-rails-1.1.4/lib/geokit-rails/acts_as_mappable.rb:91:in `acts_as_mappable'

"geocode" method failing for authenticated geocoder.us call

When using authenticated requests to geocoder.us the requests fail with 401 not authorized. Replacing line 166 of geocoders.rb with the code below solves the problem.

res = Net::HTTP.start(uri.host, uri.port) {|http|
http.request(req)
}

Is this mis-configuration or a problem with the proxy code?

Reverse Geocode example is not working

I have tried the following example given in reverse geocode section,

res=Geokit::Geocoders::GoogleGeocoder.reverse_geocode "37.791821,-122.394679"
=> #<Geokit::GeoLoc:0x558ed0 ...
res.full_address
"101-115 Main St, San Francisco, CA 94105, USA"

But I am getting the following result,

Provider: 
Street: 
City: 
State: 
Zip: 
Latitude: 
Longitude: 
Country: 
Success: false

What could be wrong?

Geokit::ActsAsMappable::UnsupportedAdapter: `postgresql` is not a supported adapter.

Brief backtrace:

/gems/geokit-rails-2.0.1/lib/geokit-rails/acts_as_mappable.rb:101 in "rescue in adapter"
/gems/geokit-rails-2.0.1/lib/geokit-rails/acts_as_mappable.rb:95 in "adapter"
/gems/geokit-rails-2.0.1/lib/geokit-rails/acts_as_mappable.rb:322 in "sphere_distance_sql"
/gems/geokit-rails-2.0.1/lib/geokit-rails/acts_as_mappable.rb:193 in "distance_sql"

I'm not sure why this error happens, but sometimes connection.adapter_name returns postgresql instead of PostgreSQL, and so it causes connection.adapter_name.camelcase to return Postgresql. I will inspect more to find the root cause.

For now, we can monkey patch this problem by this:

# ./config/initializers/geokit_rails_patch.rb
require 'geokit-rails/adapters/postgresql'
module Geokit::Adapters
  class Postgresql < PostgreSQL
  end
end

Or dirtier ;)

# ./config/initializers/geokit_rails_patch.rb
require 'geokit-rails/adapters/postgresql'
Geokit::Adapters::Postgresql = Geokit::Adapters::PostgreSQL

session[:geo_location] returns nil

I added in the top of the controller:

geocode_ip_address

And then:

logger.info "======= GEOLOCATION ==========="
logger.info session[:geo_location]

It returns: nil in the logs

Searching within Polygons

Searching on the basis of a rectangle can be rather artificial; most of all, it can be contextually misleading. Have you investigated the possibility of defining multiple points and searching within that area?

Many avenues can be thought of:
• searching multiple vectors (n-1 points of the polygon);
• working one's way through northern-most & southern-most points, as well as eastern-most and western-most points, then middling points;
• defining a central point (not necessarily center) and outlying points to alleviate the filtering...

order by distance doesn't seem to work

I've tryed to order my request by distance but I get an exception:

ActiveRecord::StatementInvalid in PagesController#index 
PGError: ERROR:  syntax error at or near "AS" 
LINE 1: ...S(users.latitude))*COS(RADIANS(users.longitude))+ AS 
alias_2... 
                                                             ^ 
: SELECT * FROM ( SELECT     DISTINCT ON ("users".id) "users".id, 
users.updated_at AS alias_0, users. AS alias_1, 
COS(0.852012144638921)*COS(0.0415964332145236)*COS(RADIANS(users.latitude)) *COS(RADIANS(users.longitude)) 
+ AS alias_2 FROM       "users" LEFT OUTER JOIN "pictures" ON 
"pictures"."user_id" = "users"."id" WHERE 
(((pictures.picture_file_name IS NOT NULL) AND 
(users.latitude>47.9181925059163 AND users.latitude<49.7152074574837 
AND users.longitude>1.01890820654452 AND 
users.longitude<3.74769192543548)) AND ( 
(ACOS(least(1,COS(0.852012144638921)*COS(0.0415964332145236)*COS(RADIANS(us ers.latitude))*COS(RADIANS(users.longitude)) 
+ 
COS(0.852012144638921)*SIN(0.0415964332145236)*COS(RADIANS(users.latitude)) *SIN(RADIANS(users.longitude)) 
+ 
SIN(0.852012144638921)*SIN(RADIANS(users.latitude))))*6376.77271) 
          <= 100))) AS id_list ORDER BY id_list.alias_0 DESC, 
id_list.alias_1 , id_list.alias_2  LIMIT 15

I've well added this lines to my User model:
acts_as_mappable :distance_field_name => :distance,
:lat_column_name => :latitude,
:lng_column_name => :longitude

And this is my AR query:

@users_carousel = User.find(:all, 
                            :order => 'users.updated_at desc, users.distance', 
                            :limit => User::MAX_USERS_IN_CAROUSEL,
                            :origin => visitor_ip, 
                            :include => :pictures,
                            :conditions => 'pictures.picture_file_name IS NOT NULL')

I'me using rails3, with pgsql.

Thank you very much for you work!!! :)

Calling .last on ActiveRecord_Relation with by_distance generates bad sql

Not sure if this is a bug in geokit-rails or ActiveRecord but I have a database query that uses by_nearby to sort locations by proximity. This works great if I append .first, .second etc to the query call.

It also gives expected behaviour if I use query[-1] to select the last record.

However, if I call query.last, it generates bad sql (presumably it tries to optimise by reversing the sort order, but this fails due to some complex math).

Here is the generated SQL:

>>> puts Friend.friends_closest_first(@user, @user.current_geolocation).to_sql
=> SELECT "friends".* FROM "friends" INNER JOIN "friendships" ON "friendships"."friend_id" = "friends"."id" INNER JOIN "geolocations" ON "geolocations"."id" = "friends"."geolocation_id" WHERE (friendships.user_id = 1)  ORDER BY
          (ACOS(least(1,COS(-0.5838126347921033)*COS(-1.2332496494591931)*COS(RADIANS(geolocations.latitude))*COS(RADIANS(geolocations.longitude))+
          COS(-0.5838126347921033)*SIN(-1.2332496494591931)*COS(RADIANS(geolocations.latitude))*SIN(RADIANS(geolocations.longitude))+
          SIN(-0.5838126347921033)*SIN(RADIANS(geolocations.latitude))))*3963.19)
          asc

This works fine:

>>>Friend.friends_closest_first(@user, @user.current_geolocation).first
=> first_record
>>>Friend.friends_closest_first(@user, @user.current_geolocation)[-1]
=> last_record

This fails:

>>>Friend.friends_closest_first(@user, @user.current_geolocation).last
=> ActiveRecord::StatementInvalid: PG::SyntaxError: ERROR:  syntax error at or near "DESC"
LINE 1: ...(friendships.user_id = 1)  ORDER BY (ACOS(least(1 DESC, COS(...
                                                             ^
: SELECT  "friends".* FROM "friends" INNER JOIN "friendships" ON "friendships"."friend_id" = "friends"."id" INNER JOIN "geolocations" ON "geolocations"."id" = "friends"."geolocation_id" WHERE (friendships.user_id = 1)  ORDER BY (ACOS(least(1 DESC, COS(-0.5838126347921033)*COS(-1.2332496494591931)*COS(RADIANS(geolocations.latitude))*COS(RADIANS(geolocations.longitude))+
          COS(-0.5838126347921033)*SIN(-1.2332496494591931)*COS(RADIANS(geolocations.latitude))*SIN(RADIANS(geolocations.longitude))+
          SIN(-0.5838126347921033)*SIN(RADIANS(geolocations.latitude))))*3963.19)
          DESC LIMIT 1

Not a problem as I said, I can use the array[-1] selector as a workaround, but perhaps it could be possible to fix in geokit-rails so that last returns the correct value?

-S

Geokit is called twice for a query

Hi guys,

I am calling a simple query:

`@cars = Car.includes(:services).within(distance, origin: city).paginate(:page => params[:page], :per_page => 100)`

And when I take a look to the log, I see there following:

Geokit is using the domain: localhost
Multi geocoding. address: New York, NY, United States, args []
Google geocoding. address: New York, NY, United States, args []
Google geocoding. Result: %7B%0A.....
Geokit is using the domain: localhost
Multi geocoding. address: New York, NY, United States, args []
Google geocoding. address: New York, NY, United States, args []
Google geocoding. Result: %7B%0A.....

Why is this output twice for every call I make? I checked the code there shouldn't be any duplicity.

In Gemfile: gem 'geokit-rails'

Thanks,
Radek

Mysql::Error: Unknown column 'distance'

I'm using Rails 3.2.15, ruby 1.8.7 with geokit-rails 2.0. I get the following error message on a by_distance query:

Mysql::Error: Unknown column 'distance' in 'order clause': SELECT tests.* FROM tests WHERE (course_type = 1 OR course_type = 2) AND ((sharemode = 1 OR sharemode = 3) AND event_date >= '2011-01-01 00:00:00' AND event_date <= '2014-01-01 00:00:00') ORDER BY (ACOS(least(1,COS(0.0)_COS(0.0)_COS(RADIANS(tests.latitude))_COS(RADIANS(tests.longitude))+ COS(0.0)_SIN(0.0)_COS(RADIANS(tests.latitude))_SIN(RADIANS(tests.longitude))+
SIN(0.0)_SIN(RADIANS(tests.latitude))))_3963.19) asc, country, distance ASC

Query:

@test_results = Test.app_mode(request.domain).by_distance(:origin => [0,0]).find(:all, :conditions => ["(sharemode = ? OR sharemode = ?) AND event_date >= ? AND event_date <= ?", 1, 3, @search_window_past, @search_window_future], :order => 'country, distance ASC')

Thanks,

Nick,

connection.adapter_name for Postgresql

There may be a bogg in Geokit::ActsAsMappable::SingletonMethods in adapter method:

klass = Adapters.const_get(connection.adapter_name.camelcase)
should be (I think)
klass = Adapters.const_get(connection.adapter_name)

Otherwise I receive an exception: uninitialized constant Geokit::Adapters::Postgresql

Records have invalid ids when using all(:within => distance, :origin => location) on a has_many :through association

The problem is that geokit-rails sets the find's :select option to "*", and the has_many :through association uses a join...causing it to include multiple id columns. I've got a fix here:

http://github.com/myronmarston/geokit-rails/commit/a1caf6dcde7406988798685de73b2b87370539c5

It'd be nice to get my fix pulled into the official repo. How do you like to receive patches? I sent a pull request a while ago and never got a response.

gem

Is there a chance to build a gem? It would be handy

Recommended way to work with model with multiple geocoded associations

Just curious how you guys would handle a scenario like this:

Say you have a Trip model and a Trip has an origin_location and a destination_location. Hypothetically something like:

class Trip < ActiveRecord::Base 
  belongs_to :origin_location, :class_name => 'Location'
  belongs_to :destination_location, :class_name => 'Location'
  acts_as_mappable :through => :origin_location
  acts_as_mappable :through => :destination_location
end

class Location < ActiveRecord::Base
  acts_as_mappable
end

And I'm kind of thinking I want to make calls like:

Trip.destination_location_within(50, [lat, lng])
and
Trip.origin_location_within(50, [lat, lng])

Do you think that makes sense, or should this instead be modeled differently? Any insight / advice on how to handle this situation?

Thanks!

Cannot load geoip

I'm having this error after "bundle update":

/Users/../.rvm/gems/ruby-2.0.0-p247@master/gems/activesupport-4.0.1/lib/active_support/dependencies.rb:229:in `require': cannot load such file -- geoip (LoadError)

Before the bundle update it was working perfectly.

In the while, if I exclude geokit-rails from my gemfile, everything works fine....

AAM::add_distance_to_select: uses "*" for SQL SELECT clause, better would be "table_name.*"

diff --git a/vendor/plugins/geokit-rails/lib/geokit-rails/acts_as_mappable.rb b/vendor/plugins/geokit-rails/lib/g
index b64af74..339ccfa 100644
--- a/vendor/plugins/geokit-rails/lib/geokit-rails/acts_as_mappable.rb
+++ b/vendor/plugins/geokit-rails/lib/geokit-rails/acts_as_mappable.rb
@@ -388,7 +388,7 @@ module Geokit
         def add_distance_to_select(options, origin, units=default_units, formula=default_formula)
           if origin
             distance_selector = distance_sql(origin, units, formula) + " AS #{distance_column_name}"
-            selector = options.has_key?(:select) && options[:select] ? options[:select] : "*"
+            selector = options.has_key?(:select) && options[:select] ? options[:select] : "#{self.table_name}.*"
             options[:select] = "#{selector}, #{distance_selector}"  
           end
         end

before_validation_on_create removed in Rails 3

Rails 3 is giving me a "no method found" error when I enable auto_geocode.
The validation should be called like so:
before_validation :auto_geocode_address, :on => :create
because before_validation_on_create has been deprecated.
Although when I change the callback to that code WEBrick crashes so there's more to the bug.

Running Rails 3 Beta 2 with ruby 1.9.2

Install issues

Hi,
Thanks for your work. i followed the instructions adding the geokit gem and then installing geokit-rails. however, had trouble with the following step:

  1. The configuration file: Geokit for Rails uses a configuration file in config/initializers. You must add your own keys for the various geocoding services if you want to use geocoding. If you need to refer to the original template again, see the assets/api_keys_template file.

**Didnt see the assets/api_keys)template file. Are you referring to /app/assets folder? I found an example of the api_keys_template online but what should the final file be called?

  1. The gem dependency: Geokit for Rails depends on the Geokit gem. Tell Rails about this dependency in config/environment.rb, within the initializer block: config.gem "geokit"

***I am a little new to Rails and tried to follow this instruction but when i copied "config.gem "geokit"" to config/environment.rb i got an error. Can you provide an example with the initializer blck code that would wrap your entry?

Is there any deeper problem indicated by the fact that the initializer file wasnt created?

Thanks,
Tyrone

ActiveRecord errors with Rails 4 and Postgres

I'm running Ruby 2.0.0p195, Rails 4.0.0, geokit 1.6.5, geokit-rails 2.0.0 (master), Postgres 9.2.4, pg gem 0.15.1.

I have a zip_codes table which has :latitude and :longitude columns both of PostgresQL type "float".

class ZipCode < ActiveRecord::Base
    acts_as_mappable :lat_column_name => :latitude, :lng_column_name => :longitude

and

class Item < ActiveRecord::Base
    belongs_to :zip_code
    acts_as_mappable :through => :zip_code

Without the acts_as_mappable, all the associations work fine. With them, the associations blow up. It seems to me that the Postgres ordered arguments ($1, $2, etc) are involved somehow. I get errors like this:

Item.all.map(&:zip_code)
#<ZipCode:0x007fb820efaaf8>
ActiveRecord::StatementInvalid: PG::Error: ERROR:  could not determine data type of parameter $1
: SELECT  "zip_codes".* FROM "zip_codes"  WHERE "zip_codes"."id" = $7  ORDER BY "zip_codes"."id" ASC LIMIT 1

it's as if the numbered arguments haven't been "reset" to $1, or something? I'm not entirely sure. Anyone else had this issue, or anything like it?

geokit-rails plugin doesn't play nice with geokit 1.5.0

After I upgraded the geokit gem from version 1.4.1 to version 1.5.0, I get the following error when starting my Rails project:

.../config/initializers/geokit_config.rb:10:NoMethodError: undefined method `timeout=' for Geokit::Geocoders:Module

I'm using Rails 2.3.4 with commit 93a264b of the geokit-rails plugin.

NoMethodError: undefined method merge_conditions

Ruby -> ruby 1.9.2dev (2010-04-04 trunk 27215) [i686-linux]
Rails -> Rails 3.0.0.beta2

Statement producing the error:
Location.find(:all, :origin =>[37.792,-122.393], :within=>10)

Stack trace:
NoMethodError: undefined method merge_conditions' for #<Class:0x9692d24> from /usr/local/lib/ruby/gems/1.9.1/gems/activerecord-3.0.0.beta2/lib/active_record/base.rb:1154:inmethod_missing'
from /home/ahmad/geok/vendor/plugins/geokit-rails/lib/geokit-rails/acts_as_mappable.rb:349:in apply_bounds_conditions' from /home/ahmad/geok/vendor/plugins/geokit-rails/lib/geokit-rails/acts_as_mappable.rb:260:inprepare_for_find_or_count'
from /home/ahmad/geok/vendor/plugins/geokit-rails/lib/geokit-rails/acts_as_mappable.rb:152:in find' from (irb):1 from /usr/local/lib/ruby/gems/1.9.1/gems/railties-3.0.0.beta2/lib/rails/commands/console.rb:47:instart'
from /usr/local/lib/ruby/gems/1.9.1/gems/railties-3.0.0.beta2/lib/rails/commands/console.rb:8:in start' from /usr/local/lib/ruby/gems/1.9.1/gems/railties-3.0.0.beta2/lib/rails/commands.rb:34:in<top (required)>'
from ./script/rails:9:in require' from ./script/rails:9:in

'

Added support for :through associations in XXX.sort_by_distance_from

I needed to have results include calculated distances, so per your docs I tried to use

bounds=Bounds.from_point_and_radius(home,5)
stores=Store.find :all, :include=>[:reviews,:cities] :bounds=>bounds
stores.sort_by_distance_from(home)

Where Store has act_as_mappable :through => :location

Unfortunately sort_by distance_from doesnt work with :through associations, but you can fix it with the following
In acts_as_mappable.rb in sort_by_distance_from function replace the following line:

e.send("#{distance_attribute_name}=", e.distance_to(origin,opts))

with the following 2 lines:

responder = e.through.blank? ? e : e.send(e.through)
e.send("#{distance_attribute_name}=", responder.distance_to(origin,opts))

Rails3 syntax

I'm trying to migrate to Rails3 syntax. The following query works:

@users = User.find(
  :all,
  :joins => "INNER JOIN profiles AS profiles ON users.id=profiles.user_id",
  :conditions => ["users.disabled = ? AND users.hidden = ?", false, false],
  :include => :profile,
  :origin => ll,
  :units => :miles, 
  :order => order_by
  ).paginate(:per_page => @per_page, :page => params[:page])

If I convert this query to Rails3 syntax using scopes, the query resembles:
@users = User.valid.joins(:profile).includes(:profile).order(order_by).paginate(:per_page => @per_page, :page => params[:page])

Question: how do I reference the :units and :origin in this syntax? I've tried a variation of the Rails3 syntax to use scopes and the .find method:

@users = User.valid.joins(:profile).includes(:profile).find(
  :all,
  :origin => ll,
  :units => :miles, 
  :order => order_by
  ).paginate(:per_page => @per_page, :page => params[:page])

but I get an error that reads "Unknown key(s): origin, units".

Is the plugin Rails3 compatible?

WARNING: geokit-rails requires the Geokit gem

Even though I have the geokit gem installed, I keep getting this message:

WARNING: geokit-rails requires the Geokit gem. You either don't have the gem installed,
or you haven't told Rails to require it. If you're using a recent version of Rails:
config.gem "geokit" # in config/environment.rb
and of course install the gem: sudo gem install geokit

Is it possible to make geokit-rails not print it when the geokit gem is installed.

Doc says "attribute on object" but method creates attribute on class

In acts_as_mappable.rb the Array#sort_by_distance_from method is documented like this:

This method creates a "distance" attribute on each object, calculates the

distance from the passed origin, and finally sorts the array by the

resulting distance.

In the implementation, a "distance" attribute is created on the class or classes of all objects in the array, which means that henceforth, all objects of that class will #respond_to?:distance. Not what I expected, and quite confusing since it never shows up in development mode (when the classes are reloaded between requests).

If this is the intended behaviour, it would be great if it was correctly documented. If it is not the intended behaviour, using singleton methods could be a solution.

nil latitude and logitude

I noticed an issue with nil lat/long values:

For ex:

a = Blah.new(:latitude => nil, :longitude => nil)

b = Blah.new(:latitude => x, :longitude => y)

Blah.find_closest(:origin => [x, y])

This will return a not b. Is this the proper intention? Is there a method in place to ignore nils? My solution was to use a named scope to prefilter for nils for the time being.

Updated Rails 3 docs?

For the newbie rails developers, it would be nice if there were docs for installing on rails 3 (assuming it works there...).

Add this to Configuration/Gemfile.rb: gem 'geokit'
make sure you have bundler: http://github.com/schacon/bundler
run bundle install in the command line

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.