Accessing PostGIS spatial data from Rails
Asked Answered
T

3

8

I need to use an existing PostGIS database from my Rails application. So far I am able to access the DB just fine, GeoRuby nicely converts the 'geom' column into a Point object.

What I am looking for is an easy way to execute ActiveRecord-like queries on those tables, e.g.

Poi.find_within_radius(...)

or similar spatial queries like distance calculations et. al.

I tried several combinations of geokit, accompanying rails plugins but I'm quite sure there must be something better out there in the ruby/rails universe. Any hints?

Tamer answered 7/10, 2009 at 14:10 Comment(0)
S
6

Since you've got GeoRuby, put in your Poi model

SRID = 4326 #WGS84

# geometry column is geom
# pt is a GeoRuby Point
def self.find_within_radius(pt, dist = 0.01)
  self.all :conditions => "ST_DWithin(geom, ST_GeomFromText('POINT(#{pt.x} #{pt.y})', #{SRID}), #{dist})"
end

For distance calculations you can use methods on the point objects

dist_circle = poi1.geom.spherical_distance(poi2.geom)
dist_projected = poi1.geom.euclidean_distance(poi2.geom)
Sanford answered 8/10, 2009 at 22:46 Comment(1)
Thanks a bunch for the samples, I tried them out and they work like a charm! Now I've got a starting point to do some more research (or dabbling in my case...)Tamer
F
1

Adding to synecdoche's answer, in Rails 3 you can use ActiveRelation scopes, which would allow you to chain queries.

Untested:

# Poi.rb

scope :within, proc { |point, distance|
  p = "POINT(#{point.x} #{point.y})"
  where("ST_DWithin(geom, ST_GeomFromText('#{p}', #{SRID}), #{distance})")
}

scope :rated, proc { |rating| where(rating: rating) }

Usage:

home = Point.new(5,5)
Poi.rated(5).within(home, 25)

Even if you don't chain scopes, most of the time it's better than using class methods.

Filmer answered 8/11, 2011 at 19:19 Comment(0)
A
0

ST_Distance() doesn't means you probably don't have postgis installed or you didn't create a postgis template... or you didn't create your database using the postgis template if the template exists.

Aeromedical answered 2/12, 2010 at 1:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.