module GeocodableModel def self.included(base) base.extend(ClassMethods) end module ClassMethods def geocodable_model(&block) return if included_modules.include?(GeocodableModel::InstanceMethods) class_inheritable_accessor :_geocode_address_block self._geocode_address_block = block has_one :geocode, :as => :geocodable, :dependent => :destroy after_save :update_geocode include InstanceMethods end end module InstanceMethods def update_geocode addresses = _geocode_address_block.call(self) addresses = [*addresses] unless addresses.is_a?(Array) addresses.reject!(&:blank?) case when geocode && addresses.empty? geocode.destroy self.geocode = nil when geocode && !addresses.empty? geocode.update_attributes(:addresses => addresses) when !geocode && !addresses.empty? create_geocode(:addresses => addresses) end end def latitude geocode.latitude if geocode end def longitude geocode.longitude if geocode end def to_location geocode.to_location if geocode end end end class ActiveRecord::Base include GeocodableModel end