Skip to content

Instantly share code, notes, and snippets.

@stuart
Created October 13, 2011 03:12
Show Gist options
  • Save stuart/1283257 to your computer and use it in GitHub Desktop.
Save stuart/1283257 to your computer and use it in GitHub Desktop.
Acts as geolocatable
module Geolocatable
def acts_as_geolocatable(options = {})
options = {:lat => 'lat', :lng => 'lng'}.merge(options)
write_inheritable_attribute :acts_as_geolocatable_options, options
class_inheritable_reader :acts_as_geolocatable_options, options
include Geolocatable::Model
end
module Model
extend ActiveSupport::Concern
included do
# Use like: :origin => [12.453,34.566], :within => 10
scope :near, lambda{ |*args|
origin = *args.first[:origin]
if (origin).is_a?(Array)
origin_lat, origin_lng = origin
else
origin_lat, origin_lng = origin.lat, origin.lng
end
origin_lat, origin_lng = Math::PI*origin_lat/180, Math::PI*origin_lng/180
within = *args.first[:within]
{
:conditions => %(
(ACOS(COS(#{origin_lat})*COS(#{origin_lng})*COS(RADIANS(#{lng_sql}))*COS(RADIANS(#{lng_sql}))+
COS(#{origin_lat})*SIN(#{origin_lng})*COS(RADIANS(#{lat_sql}))*SIN(RADIANS(#{lng_sql}))+
SIN(#{origin_lat})*SIN(RADIANS(#{lat_sql})))*3963) <= #{within[0]}
),
:select => %( #{table_name}.* )
}
}
# Bounds must be in the format: lat_lo, lng_lo, lat_hi, lng_hi
scope :in_bounds, lambda{ |*args|
bounds = *args.first[:bounds]
lat_lo = bounds[0];
lng_lo = bounds[1];
lat_hi = bounds[2];
lng_hi = bounds[3];
{
:conditions => %(
(#{lat_sql} BETWEEN #{lat_lo} AND #{lat_hi}) AND
(#{lng_sql} BETWEEN #{lng_lo} AND #{lng_hi})
),
:select => %( #{table_name}.* )
}
}
end
module ClassMethods
def lat_sql
"#{table_name}.#{acts_as_geolocatable_options[:lat]}"
end
def lng_sql
"#{table_name}.#{acts_as_geolocatable_options[:lng]}"
end
end
end
end
@stuart
Copy link
Author

stuart commented Oct 13, 2011

This was my take on geolocation when the gems all had too much cruft or didnt work with Rails 3 or ruby 1.9.2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment