Module: Geocoder::Store::ActiveRecord::ClassMethods

Defined in:
lib/geocoder/stores/active_record.rb

Overview

Methods which will be class methods of the including class.

Instance Method Summary collapse

Instance Method Details

#distance_from_sql(location, *args) ⇒ Object



83
84
85
86
87
88
# File 'lib/geocoder/stores/active_record.rb', line 83

def distance_from_sql(location, *args)
  latitude, longitude = Geocoder::Calculations.extract_coordinates(location)
  if Geocoder::Calculations.coordinates_present?(latitude, longitude)
    distance_sql(latitude, longitude, *args)
  end
end

#near_scope_options(latitude, longitude, radius = 20, options = {}) ⇒ Object

Get options hash suitable for passing to ActiveRecord.find to get records within a radius (in kilometers) of the given point. Options hash may include:

  • :units - :mi or :km; to be used. for interpreting radius as well as the distance attribute which is added to each found nearby object. Use Geocoder.configure[:units] to configure default units.

  • :bearing - :linear or :spherical. the method to be used for calculating the bearing (direction) between the given point and each found nearby point; set to false for no bearing calculation. Use Geocoder.configure[:distances] to configure default calculation method.

  • :select - string with the SELECT SQL fragment (e.g. “id, name”)

  • :select_distance - whether to include the distance alias in the

    SELECT SQL fragment (e.g. <formula> AS distance)
    
  • :select_bearing - like :select_distance but for bearing.

  • :order - column(s) for ORDER BY SQL clause; default is distance;

    set to false or nil to omit the ORDER BY clause
    
  • :exclude - an object to exclude (used by the nearbys method)

  • :distance_column - used to set the column name of the calculated distance.

  • :bearing_column - used to set the column name of the calculated bearing.

  • :min_radius - the value to use as the minimum radius.

    ignored if database is sqlite.
    default is 0.0
    


117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/geocoder/stores/active_record.rb', line 117

def near_scope_options(latitude, longitude, radius = 20, options = {})
  if options[:units]
    options[:units] = options[:units].to_sym
  end
  latitude_attribute = options[:latitude] || geocoder_options[:latitude]
  longitude_attribute = options[:longitude] || geocoder_options[:longitude]
  options[:units] ||= (geocoder_options[:units] || Geocoder.config.units)
  select_distance = options.fetch(:select_distance)  { true }
  options[:order] = "" if !select_distance && !options.include?(:order)
  select_bearing = options.fetch(:select_bearing) { true }
  bearing = bearing_sql(latitude, longitude, options)
  distance = distance_sql(latitude, longitude, options)
  distance_column = options.fetch(:distance_column) { 'distance' }
  bearing_column = options.fetch(:bearing_column)  { 'bearing' }

  # If radius is a DB column name, bounding box should include
  # all rows within the maximum radius appearing in that column.
  # Note: performance is dependent on variability of radii.
  bb_radius = radius.is_a?(Symbol) ? maximum(radius) : radius
  b = Geocoder::Calculations.bounding_box([latitude, longitude], bb_radius, options)
  args = b + [
    full_column_name(latitude_attribute),
    full_column_name(longitude_attribute)
  ]
  bounding_box_conditions = Geocoder::Sql.within_bounding_box(*args)

  if using_unextended_sqlite?
    conditions = bounding_box_conditions
  else
    min_radius = options.fetch(:min_radius, 0).to_f
    # if radius is a DB column name,
    # find rows between min_radius and value in column
    if radius.is_a?(Symbol)
      c = "BETWEEN ? AND #{radius}"
      a = [min_radius]
    else
      c = "BETWEEN ? AND ?"
      a = [min_radius, radius]
    end
    conditions = [bounding_box_conditions + " AND (#{distance}) " + c] + a
  end
  {
    :select => select_clause(options[:select],
                             select_distance ? distance : nil,
                             select_bearing ? bearing : nil,
                             distance_column,
                             bearing_column),
    :conditions => add_exclude_condition(conditions, options[:exclude]),
    :order => options.include?(:order) ? options[:order] : "#{distance_column} ASC"
  }
end