# ActsAsLocateable module BaconBear module Acts #:nodoc: module Locateable #:nodoc: def self.included(base) base.extend ClassMethods end module ClassMethods # Available options # :through => :attribute - Uses the latitude/longitude present in the attribute instead of in this class proper def acts_as_locateable(options = nil) @locatable_through = nil if (options.kind_of?(Hash)) @locatable_through = options[:through] if options.has_key?(:through) end class < ? AND longitude > ? AND latitude < ? AND longitude < ? ", min_lat, min_lon, max_lat, max_lon] find_include = locatable_through with_scope(:find => {:conditions => find_conditions, :include => find_include}) do yield end end end # Find instances of the locatable class within radius_in_miles of your target. # Target can be specified in a number of ways, see expand_radius_args for options def find_within_radius_with_dist(radius_in_miles, *args) lat, lon = expand_radius_args(args) within_radius_scope_with_dist(radius_in_miles, lat, lon) do find(:all) end end protected # Arguments can in the form of: # lat, lon # zip code # city, state # ZipCode object def expand_radius_args(args) case when args.size == 2 lat = args[0] lon = args[1] when args[0].kind_of?(Fixnum) || args[0].to_i > 0 z = ZipCode.find_by_zip(args[0]) raise ActiveRecord::RecordNotFound .new if z.nil? lat = z.lat lon = z.lon when args[0].kind_of?(String) city,state = args[0].split(/\,\s*/) z = ZipCode.find_by_city_and_state(city.upcase, state.upcase) raise ActiveRecord::RecordNotFound .new if z.nil? lat = z.lat lon = z.lon when args[0].kind_of?(ZipCode) lat = args[0].lat lon = args[0].lon end [lat, lon] end end # This module contains instance methods module InstanceMethods def latitude() if self.class.locatable_through.nil? read_attribute(:latitude).to_f else eval("#{self.class.locatable_through.to_s}").latitude.to_f end end def longitude() if self.class.locatable_through.nil? read_attribute(:longitude).to_f else eval("#{self.class.locatable_through.to_s}").longitude.to_f end end def lat() latitude end def lon() longitude end end end end end