Module: CollectiveIdea::Acts::Geocodable::SingletonMethods

Defined in:
lib/acts_as_geocodable.rb

Instance Method Summary collapse

Instance Method Details

#count(*args) ⇒ Object

Extends ActiveRecord’s count method to be geo-aware.

Model.count(:within => 10, :origin => "Chicago, IL")

Options

  • :origin: A Geocode, String, or geocodable model that specifies the origin

  • :within: Limit to results within this radius of the origin

  • :beyond: Limit to results outside of this radius from the origin

  • :units: Units to use for :within or :beyond. Default is :miles unless specified otherwise in the acts_as_geocodable declaration.



115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/acts_as_geocodable.rb', line 115

def count(*args)
  options = args.extract_options!
  origin = location_to_geocode options.delete(:origin)
  if origin
    options[:units] ||= acts_as_geocodable_options[:units]
    with_proximity!(args, options) do
      geocode_conditions!(options, origin) do
        join_geocodes { super *args.push(options) }
      end
    end
  else
    super *args.push(options)
  end
end

#find(*args) ⇒ Object

Extends ActiveRecord’s find method to be geo-aware.

Model.find(:all, :within => 10, :origin => "Chicago, IL")

Whenever find is called with an :origin, a distance attribute indicating the distance to the origin is added to each of the results:

Model.find(:first, :origin => "Portland, OR").distance #=> 388.383

acts_as_geocodable adds 2 other retrieval approaches to ActiveRecord’s default find by id, find :first, and find :all:

  • :nearest: find the nearest location to the given origin

  • :farthest: find the farthest location from the given origin

    Model.find(:nearest, :origin => “Grand Rapids, MI”)

Options

  • :origin: A Geocode, String, or geocodable model that specifies the origin

  • :within: Limit to results within this radius of the origin

  • :beyond: Limit to results outside of this radius from the origin

  • :units: Units to use for :within or :beyond. Default is :miles unless specified otherwise in the acts_as_geocodable declaration.



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/acts_as_geocodable.rb', line 85

def find(*args)
  options = args.extract_options!
  origin = location_to_geocode options.delete(:origin)
  if origin
    options[:units] ||= acts_as_geocodable_options[:units]
    add_distance_to_select!(origin, options)
    with_proximity!(args, options) do
      geocode_conditions!(options, origin) do
        join_geocodes { super *args.push(options) }
      end
    end
  else
    super *args.push(options)
  end
end

#location_to_geocode(location) ⇒ Object

Convert the given location to a Geocode



131
132
133
134
135
136
137
# File 'lib/acts_as_geocodable.rb', line 131

def location_to_geocode(location)
  case location
  when Geocode then location
  when InstanceMethods then location.geocode
  when String, Fixnum then Geocode.find_or_create_by_query(location)
  end
end

#validates_as_geocodable(options = {}) ⇒ Object

Validate that the model can be geocoded

Options:

  • :message: Added to errors base (Default: Address could not be geocoded.)

  • :allow_nil: If all the address attributes are blank, then don’t try to validate the geocode (Default: false)

  • :precision: Require a minimum geocoding precision

validates_as_geocodable also takes a block that you can use to performa additional checks on the geocode. If this block returns false, then validation will fail.

validates_as_geocodable do |geocode|
  geocode.country == "US"
end


154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/acts_as_geocodable.rb', line 154

def validates_as_geocodable(options = {})
  options = options.reverse_merge :message => "Address could not be geocoded.", :allow_nil => false
  validate do |model|
    is_blank = model.to_location.attributes.except(:precision).all?(&:blank?)
    unless options[:allow_nil] && is_blank
      geocode = model.send :attach_geocode
      if !geocode ||
          (options[:precision] && geocode.precision < options[:precision]) ||
          (block_given? && yield(geocode) == false)
        model.errors.add_to_base options[:message]
      end
    end
  end
end