Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

ActiveRecord connection adapter for PostGIS, based on postgresql and rgeo

License

NotificationsYou must be signed in to change notification settings

rgeo/activerecord-postgis-adapter

Repository files navigation

Gem VersionBuild StatusMaintainability

The activerecord-postgis-adapter provides access to featuresof the PostGIS geospatial database from ActiveRecord. It extendsthe standard postgresql adapter to provide support for the spatial data typesand features added by the PostGIS extension. It uses theRGeo library to represent spatial data in Ruby.

Overview

The adapter provides three basic capabilities:

First, it providesspatial migrations. It extends the ActiveRecord migrationsyntax to support creating spatially-typed columns and spatial indexes. Youcan control the various PostGIS-provided attributes such as SRID, dimension,and geographic vs geometric math.

Second, it recognizes spatial types and casts them properly to RGeo geometryobjects. The adapter can configure these objects automatically based on theSRID and dimension in the database table, or you can tell it to convert thedata to a different form. You can also set attribute data using WKT format.

Third, it lets you include simple spatial data in queries. WKT format data andRGeo objects can be embedded in where clauses.

Install

The adapter requires PostgreSQL 9.0+ and PostGIS 2.4+.

Installing PostGIS

Here are common methods for installing PostGIS, but more detailed methods can be found on theinstallation guide.

MacOS

brew install postgis

Ubuntu/Debian

sudo apt-get install postgis postgresql-16-postgis-3

Windows

PostGIS is likely available as an optional package via your Postgresql installer. If not, refer to the installation guide.

Version compatibility

VersionActiveRecordRubyPostGISNote
11.1.x8.13.2.0+2.0+
11.0.x8.03.2.0+2.0+
10.x7.23.1.0+2.0+
9.x7.13.0.0+2.0+
8.x7.02.7.0+2.0+
7.x6.12.5.0+, JRuby2.0+
6.x6.02.5.0+, JRuby2.0+
5.x5.1, 5.22.2.2+, JRuby2.0+
4.x5.02.2.2+, JRuby2.0+
3.x4.21.9.3+, JRuby2.0+
2.x4.0.0 - 4.1.x1.9.3+, JRuby2.0+Read 2.x README
0.6.x3.x1.8.7+, JRuby, Rubinius1.5+Read 0.6.x / 2.x README
PostGIS 1 Notes

Upgrading to version 8.x

ThePostgisDatabaseTasks module has been removed which means that the rake tasks to install postgis are no longer available. If using a Rails app, please seeUpgrading an Existing Database

Upgrading from 6.x

When upgrading from version 6.x to a newer major version, you may need to modify yourSpatialFactoryStore configuration. Please see this section of the README in rgeo-activerecord for more details (https://github.com/rgeo/rgeo-activerecord#spatial-factories-for-columns).

database.yml

You must modify yourconfig/database.yml file to use the postgisadapter. At minimum, you will need to change theadapter field frompostgresql topostgis. Recommended configuration:

development:username:your_usernameadapter:postgishost:localhostschema_search_path:public

If you have installed your PostGIS extension in a schema other thanpublic, whichis the default, add that schema to yourschema_search_path:

development:schema_search_path:public, postgis

Here are some other options that are supported:

development:adapter:postgisencoding:unicodepostgis_extension:postgis# default is postgispostgis_schema:public# default is publicschema_search_path:public,postgispool:5database:my_app_development# your database nameusername:my_app_user# the username your app will use to connectpassword:my_app_password# the user's passwordsu_username:my_global_user# a superuser for the databasesu_password:my_global_pasword# the superuser's password
rgeo dependency

This adapter uses thergeo gem, which has additional dependencies.Please see the README documentation forrgeo for more information:https://github.com/rgeo/rgeo

Setup

If you have not created your rails app yet start there.

rails new my_app --database=postgresql

Add the gem to your Gemfile.

gem'activerecord-postgis-adapter'

And tell ActiveRecord to use the adapter by setting theadapter field inconfig/database.yml

default:&defaultadapter:postgis

Create the database if you haven't already.

rake db:create

Create a migration to add the PostGIS extension to your database.

rails generate migration AddPostgisExtensionToDatabase

The migration should look something like this:

classAddPostgisExtensionToDatabase <ActiveRecord::Migration[7.2]defchangeenable_extension'postgis'endend

Then run the migration.

rails db:migrate

Creating Spatial Tables

To store spatial data, you must create a column with a spatial type. PostGISprovides a variety of spatial types, including point, linestring, polygon, anddifferent kinds of collections. These types are defined in a standard producedby the Open Geospatial Consortium. You can specify options indicating the coordinatesystem and number of coordinates for the values you are storing.

The activerecord-postgis-adapter extends ActiveRecord's migration syntax tosupport these spatial types. The following example creates five spatialcolumns in a table:

create_table:my_spatial_tabledo |t|t.column:shape1,:geometryt.geometry:shape2t.line_string:path,srid:3785t.st_point:lonlat,geographic:truet.st_point:lonlatheight,geographic:true,has_z:trueend

The first column, "shape1", is created with type "geometry". This is a general"base class" for spatial types; the column declares that it can contain valuesofany spatial type.

The second column, "shape2", uses a shorthand syntax for the same type as the shape1 column.You can create a column either by invokingcolumn or invoking the name of the type directly.

The third column, "path", has a specific geometric type,line_string. Italso specifies an SRID (spatial reference ID) that indicates which coordinatesystem it expects the data to be in. The column now has a "constraint" on it;it will accept only LineString data, and only data whose SRID is 3785.

The fourth column, "lonlat", has thest_point type, and accepts only Pointdata. Furthermore, it declares the column as "geographic", which means itaccepts longitude/latitude data, and performs calculations such as distancesusing a spheroidal domain.

The fifth column, "lonlatheight", is a geographic (longitude/latitude) pointthat also includes a third "z" coordinate that can be used to store heightinformation.

The following are the data types understood by PostGIS and exposed byactiverecord-postgis-adapter:

  • :geometry -- Any geometric type
  • :st_point -- Point data
  • :line_string -- LineString data
  • :st_polygon -- Polygon data
  • :geometry_collection -- Any collection type
  • :multi_point -- A collection of Points
  • :multi_line_string -- A collection of LineStrings
  • :multi_polygon -- A collection of Polygons

Following are the options understood by the adapter:

  • :geographic -- If set to true, create a PostGIS geography column forlongitude/latitude data over a spheroidal domain; otherwise create ageometry column in a flat coordinate system. Default is false. Alsoimplies :srid set to 4326.
  • :srid -- Set a SRID constraint for the column. Default is 4326 for ageography column, or -1 for a geometry column. Note that PostGIS currently(as of version 2.0) requires geography columns to have SRID 4326, so thisconstraint is of limited use for geography columns.
  • :has_z -- Specify that objects in this column include a Z coordinate.Default is false.
  • :has_m -- Specify that objects in this column include an M coordinate.Default is false.

To create a PostGIS spatial index, addusing: :gist to your index:

add_index:my_table,:lonlat,using::gist# orchange_table:my_tabledo |t|t.index:lonlat,using::gistend

Attributes

Models may also define attributes using the above data types and options.

classSpatialModel <ActiveRecord::Baseattribute:centroid,:st_point,srid:4326,geographic:trueend

centroid will not have an associated column in thespatial_models table, but any geometry object assigned to thecentroid attribute will be cast to a geographic point.

Configuring ActiveRecord

ActiveRecord's usefulness stems from the way it automatically configuresclasses based on the database structure and schema. If a column in thedatabase has an integer type, ActiveRecord automatically casts the data to aRuby Integer. In the same way, the activerecord-postgis-adapter automaticallycasts spatial data to a corresponding RGeo data type.

RGeo offers more flexibility in its type system than can beinterpreted solely from analyzing the database column. For example, you canconfigure RGeo objects to exhibit certain behaviors related to theirserialization, validation, coordinate system, or computation. These settingsare embodied in the RGeo factory associated with the object.

You can configure the adapter to use a particular factory (i.e. aparticular combination of settings) for data associated with each type inthe database.

Here's an example using a Geos default factory:

RGeo::ActiveRecord::SpatialFactoryStore.instance.tapdo |config|# By default, use the GEOS implementation for spatial columns.config.default=RGeo::Geos.factory_generator# But use a geographic implementation for point columns.config.register(RGeo::Geographic.spherical_factory(srid:4326),geo_type:"point")end

The default spatial factory for geographic columns isRGeo::Geographic.spherical_factory.The default spatial factory for cartesian columns isRGeo::Cartesian.preferred_factory.You do not need to configure theSpatialFactoryStore if these defaults are ok.

For more explanation ofSpatialFactoryStore, seethe rgeo-activerecord README

Deploying to Heroku

See thewiki entry andlinked issue for some notes on Heroku deployments.

Note: RGeo is looking for a Heroku user to help formalize/expand the wiki. If you're interested, please open a PR with a new md file, which can be copied to the wiki.

Working With Spatial Data

Of course, you're using this adapter because you want to work with geospatialdata in your ActiveRecord models. Once you've installed the adapter, set upyour database, and run your migrations, you can interact directly with spatialdata in your models as RGeo objects.

RGeo is a Ruby implementation of the industry standard OGC Simple Featuresspecification. It's a set of data types that can represent a variety ofgeospatial objects such as points, lines, polygons, and collections. It alsoprovides the standard set of spatial analysis operations such as computingintersections or bounding boxes, calculating length or area, and so forth. Werecommend browsing the RGeo documentation for a clearer understanding of itscapabilities. For now, just note that the data values you will be working withare all RGeo geometry objects.

Reading and Writing Spatial Columns

When you access a spatial attribute on your ActiveRecord model, it is given toyou as an RGeo geometry object (or nil, for attributes that allow nullvalues). You can then call the RGeo api on the object. For example, considerthe MySpatialTable class we worked with above:

record=MySpatialTable.find(1)p=record.lonlat# Returns an RGeo::Feature::Pointputsp.x# displays the x coordinateputsp.geometry_type.type_name# displays "Point"

The RGeo factory for the value is determined by how you configured theActiveRecord class, as described above. In this case, we explicitly set aspherical factory for the:lonlat column:

factory=p.factory# returns a spherical factory

You can set a spatial attribute by providing an RGeo geometry object, or byproviding the WKT string representation of the geometry. If a string isprovided, the activerecord-postgis-adapter will attempt to parse it as WKT andset the value accordingly.

record.lonlat='POINT(-122 47)'# sets the value to the given point

If the WKT parsing fails, the value currently will be silently set to nil. Inthe future, however, this will raise an exception.

record.lonlat='POINT(x)'# sets the value to nil

If you set the value to an RGeo object, the factory needs to match the factoryfor the attribute. If the factories do not match, activerecord-postgis-adapterwill attempt to cast the value to the correct factory.

p2=factory.point(-122,47)# p2 is a point in a spherical factoryrecord.lonlat=p2# sets the value to the given pointrecord.shape1=p2# shape1 uses a flat geos factory, so it# will cast p2 into that coordinate system# before setting the valuerecord.save

If, however, you attempt to set the value to the wrong type-- for example,setting a linestring attribute to a point value, you will get an exceptionfrom Postgres when you attempt to save the record.

record.path=p2# This will appear to work, but...record.save# This will raise an exception from the database

Spatial Queries

You can create simple queries based on representational equality in the sameway you would on a scalar column:

record2=MySpatialTable.where(:lonlat=>factory.point(-122,47)).first

You can also use WKT:

record3=MySpatialTable.where(:lonlat=>'POINT(-122 47)').first

Note that these queries use representational equality, meaning they returnrecords where the lonlat value matches the given value exactly. A 0.00001degree difference would not match, nor would a different representation of thesame geometry (like a multipoint with a single element). Equality queriesaren't generally all that useful in real world applications. Typically, if youwant to perform a spatial query, you'll look for, say, all the points within agiven area. For those queries, you'll need to use the standard spatial SQLfunctions provided by PostGIS.

To perform more advanced spatial queries, you can use the extended Arel interface included in the activerecord-postgis-adapter. The functions accept WKT strings or RGeo features.

point=RGeo::Geos.factory(srid:0).point(1,1)buildings=Building.arel_tablecontaining_buiildings=Building.where(buildings[:geom].st_contains(point))

Seergeo-activerecord for more information about advanced spatial queries.

Joining Spatial Columns

If a spatial column is joined with another model,srid andgeographic will not be automatically inferred and they will default to 0 andfalse, by default. In order to properly infer these options after a join, anattribute must be created on the target table.

classSpatialModel <ActiveRecord::Basebelongs_to:foo# has column geo_point (:st_point, srid: 4326, geographic: true)endclassFoo <ActiveRecord::Basehas_one:spatial_model# re-define geo_point here so join worksattribute:geo_point,:st_point,srid:4326,geographic:trueend# perform a query where geo_point is joined to foofoo=Foo.joins(:spatial_models).select("foos.id, spatial_models.geo_point").firstpfoo.geo_point.class# => RGeo::Geographic::SphericalPointImplpfoo.geo_point.srid# => 4326

Background: PostGIS

A spatial database is one that includes a set of data types, functions,tables, and other objects related to geospatial data. When these objects arepresent in your database, you can use them to store and query spatial objectssuch as points, lines, and polygons.

PostGIS is an extension for PostgreSQL that provides definitions for the objectsyou need to add to a database to enable geospatial capabilities.

When you create your Rails database as described above in the section oninstallation and configuration, activerecord-postgis-adapter automaticallyinvokes PostGIS to add the appropriate definitions to your database. You candetermine whether your database includes the correct definitions by attemptingto invoke the POSTGIS_VERSION function:

SELECT POSTGIS_VERSION();# succeeds if PostGIS objects are present.

Standard spatial databases also include a table calledspatial_ref_sys. Thistable includes a set of "spatial reference systems", or coordinate systems---for example, WGS84 latitude and longitude, or Mercator Projection. Spatialdatabases also usually include a table calledgeometry_columns, whichincludes information on each database column that includes geometric data. Inrecent versions of PostGIS,geometry_columns is actually not a table but aview into the system catalogs.

Development and Support

RubyDoc Documentation is available athttps://rubydoc.info/gems/activerecord-postgis-adapter

Contributions are welcome. See CONTRIBUTING.md for instructions.

Report issues athttps://github.com/rgeo/activerecord-postgis-adapter/issues

Support is also available on the rgeo-users google group athttps://groups.google.com/group/rgeo-users

Acknowledgments

Daniel Azuma authored the PostGIS Adapter and its supportinglibraries (including RGeo).

Tee Parham is a former maintainer.

Keith Doggett is a current maintainer.

Ulysse Buonomo is a current maintainer.

Development is supported by:

This adapter implementation owes some debt to the spatial_adapter plugin(https://github.com/fragility/spatial_adapter). Although we made some differentdesign decisions for this adapter, studying the spatial_adapter source gave usa head start on the implementation.

License

Copyright Daniel Azuma, Tee Parham

https://github.com/rgeo/activerecord-postgis-adapter/blob/master/LICENSE.txt

About

ActiveRecord connection adapter for PostGIS, based on postgresql and rgeo

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Sponsor this project

    Packages

    No packages published

    Contributors61

    Languages


    [8]ページ先頭

    ©2009-2025 Movatter.jp