alexreisner/geocoder

Support for coordinate arrays instead of independent latitude and longitude parameters in ActiveRecord

brianewell opened this issue · 4 comments

This is a feature request.

I have just started experimenting with storing GPS coordinates in PostgreSQL using the point geometric type. According to the PostgreSQL manual, it represents a pair of x and y coordinates as a pair of floating-point variables, which seems ideal for this library.

However it appears that accessing latitude and longitude through independent parameters is hard coded when interfacing with ActiveRecord, see the following example:

app/models/organization.rb:

class Organization < ApplicationRecord
...
  geocoded_by :physical_address, coordinates: :coordinates
  after_validation :geocode, if: ->(org){ org.physical_address.present? and org.physical_address_changed? }
...
end

Expected behavior

I would have hoped this just worked as a model with independent latitude and longitude parameters would:

$ rake geocode:all CLASS=Organization
# a short wait, followed by a database full of geocoded records

Actual behavior

Instead, it fails like this:

$ rake geocode:all CLASS=Organization
rake aborted!
ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR:  column organizations.latitude does not exist
LINE 1: ...ECT "organizations".* FROM "organizations" WHERE (organizati...
                                                             ^


Caused by:
PG::UndefinedColumn: ERROR:  column organizations.latitude does not exist
LINE 1: ...ECT "organizations".* FROM "organizations" WHERE (organizati...
                                                             ^

Tasks: TOP => geocode:all
(See full trace by running task with --trace)

Steps to reproduce

  1. Spin up a new rails project backed by a PostgreSQL database.
  2. Create a migration that uses the point datatype: t.column :coordinates, :point
  3. (optional) Explicitly suggest to Geocoder that gecoded coordinates should be stored in the parameter backed by before mentioned point datatype: geocoded_by :address, coordinates: :coordinates
  4. Exercise geocoding and see it attempt to access parameters that aren't explicitly set.

Environment info

  • Geocoder version: v1.6.7
  • Rails version: v6.1.4.1
  • Database: PostgreSQL v13.1

Thanks for this. You make an interesting point. However, I believe Postgres's point type is intended to represent points on a flat 2D plane, not a globe. The associated geometric functions wouldn't work as expected. I think it's actually reasonable to argue that this is the wrong data type to use for lat/lon coordinates, and that it's potentially misleading. Unless there's a significant advantage to storing them this way, I'm hesitant to add this functionality.

You make an interesting point.

I see what you did there.

Yes, it does seem that point is normally intended for use in cartesian planes, ergo the associated native Postgresql geometric functions would certainly not be helpful for geocoder.

I was originally considering this feature request from a consistency and simplicity perspective: two floats named latitude and longitude don't have native Postgresql geometry functions either, and if one were to simply use POINT as a storage type, that shouldn't be too different from what's done in MongoDB and results in a slightly cleaner database.

Then I took a glance at PostGIS, the geospatial extension to PostgreSQL. It appears that the geography datatype does adhere to WGS 84 and casts from POINT, however clearly some experimentation is going to have to be done to confirm that ActiveRecord and PostGIS play well together before pushing for any PostGIS functionality in Geocoder.

I'll see what I can do about standing up a test environment to see how AR and PostGIS like each other and get back to you here on the results of those tests.

Ha! I assure you, that was unintentional.

Thanks for doing this research. This all lives near the edge of what I see as Geocoder's domain. The rgeo gem is great for using ActiveRecord with PostGIS. Because rgeo exists (and is good), I've decided to include only rudimentary geo-search features in Geocoder, and to focus instead on fetching data from APIs. But if there's something simple we can do to help support the use of rgeo, I think I'd be open to that.

I was unfamiliar with rgeo, but will definitely look into that gem.