activerecord-postgis-adapter 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,10 @@
1
+ === 0.4.2 / 2012-04-12
2
+
3
+ * Support the db:structure:load rake task in recent versions of Rails.
4
+ * Support installing PostGIS via the PostgreSQL extension mechanism (requires at least PostGIS 2.0 and PostgreSQL 9.1).
5
+ * Support bounding boxes in queries (useful for "window" queries such as finding objects to display in a map region).
6
+ * Fix some issues determine the correct default value for spatial columns.
7
+
1
8
  === 0.4.1 / 2012-02-22
2
9
 
3
10
  * Some compatibility fixes for Rails 3.2. (Reported by Ryan Williams with implementation help from Radek Paviensky.)
@@ -98,11 +98,23 @@ You can also use WKT:
98
98
 
99
99
  rec = MySpatialTable.where(:latlon => 'POINT(-122 47)').first
100
100
 
101
- The adapter also provides experimental support for more complex queries
102
- such as radius searches. However, these extensions require Arel 2.1
103
- (which is scheduled for release with Rails 3.1). We do not have these
104
- documented yet, and the syntax is subject to change. For now, you should
105
- write more complex queries in SQL.
101
+ Most more complex spatial queries require the use of SQL functions. You
102
+ can write such queries in raw SQL, but you may find the "squeel" gem
103
+ very helpful in this regard. Using squeel, you can write queries like
104
+ the following:
105
+
106
+ my_polygon = get_my_polygon()
107
+ MySpatialTable.where{st_intersects(latlon, my_polygon)}.first
108
+
109
+ One common query is to find all objects displaying in a window. This can
110
+ be done using the overlap (&&) operator with a bounding box, as follows:
111
+
112
+ sw = get_sw_corner()
113
+ ne = get_ne_corner()
114
+ window = RGeo::Cartesian::BoundingBox.create_from_points(sw, ne)
115
+ MySpatialTable.where{latlon.op('&&', window)}.all
116
+
117
+ Note that using squeel to create SQL functions requires Rails 3.1 or later.
106
118
 
107
119
  == Installation And Configuration
108
120
 
@@ -116,8 +128,8 @@ This adapter has the following requirements:
116
128
  * pg gem 0.11 or later.
117
129
  * \ActiveRecord 3.0.3 or later. Earlier versions will not work.
118
130
  Should be compatible with Rails versions through 3.2.x.
119
- * rgeo gem 0.3.4 or later.
120
- * rgeo-activerecord gem 0.4.3 or later.
131
+ * rgeo gem 0.3.10 or later.
132
+ * rgeo-activerecord gem 0.4.4 or later.
121
133
 
122
134
  Install this adapter as a gem:
123
135
 
@@ -153,15 +165,27 @@ Besides the adapter name "postgis", most of the other database connection
153
165
  configuration parameters are the same as for the stock postgresql adapter.
154
166
  However, there are several important differences:
155
167
 
168
+ The <i>postgis_extension</i> parameter is specific to the PostGIS adapter,
169
+ and directs the adapter to use PostgreSQL's CREATE EXTENSION mechanism to
170
+ install the PostGIS types, functions, and tables to a newly created
171
+ database. Generally, the value should be set to true, although you can
172
+ also set it to a comma-delimited list of extension names (which should
173
+ include the base "postgis" extension) if you want to customize which
174
+ extensions are installed. This is the easiest and cleanest way to create
175
+ a PostGIS-enabled database, but it requires PostgreSQL 9.1 or later and
176
+ PostGIS 2.0 or later.
177
+
156
178
  The <i>script_dir</i> parameter is specific to the PostGIS adapter, and
157
- provides the path to the directory containing the SQL scripts for PostGIS
158
- installation. This directory should contain the files <tt>postgis.sql</tt>
159
- and <tt>spatial_ref_sys.sql</tt>. (A common setting for this directory
160
- might be <tt>/usr/local/share/contrib/postgis-1.5</tt>.) It is used by
161
- <tt>rake db:create</tt> to add the PostGIS types, functions, and tables to
162
- a newly created database. If you do not provide this parameter, you will
163
- need to add these objects to the database manually.
164
- Generally, therefore, this parameter is required at least for the test
179
+ provides an alternative mechanism for installing the PostGIS definitions
180
+ into a new database if either PostgreSQL 9.1 or PostGIS 2.0 is not
181
+ available. Its value should be set to the path to the directory containing
182
+ the SQL scripts for PostGIS installation. This is the directory containing
183
+ the files <tt>postgis.sql</tt> and <tt>spatial_ref_sys.sql</tt>. (A common
184
+ setting might be <tt>/usr/local/share/contrib/postgis-1.5</tt>.)
185
+
186
+ If you do not provide <i>postgis_extension</i> or <i>script_dir</i>, you
187
+ will need to add the PostGIS definitions to the database manually.
188
+ Generally, therefore, one of them is required at least for the test
165
189
  database, which is usually automatically created by the rake tasks.
166
190
 
167
191
  The <i>su_username</i> and <i>su_password</i> parameters are provided as
@@ -200,10 +224,10 @@ are managing a database using Rails and \ActiveRecord. For example:
200
224
 
201
225
  To deal with these issues, we recommend the following technique:
202
226
 
203
- * Set <i>script_dir</i> in both your development and test database
204
- configurations. This will cause the PostGIS Adapter to automatically
205
- add the PostGIS definitions and spatial references to your databases
206
- when rake db:create is run.
227
+ * Set either <i>postgis_extension</i> or <i>script_dir</i> in both your
228
+ development and test database configurations. This will cause the
229
+ PostGIS Adapter to automatically add the PostGIS definitions and
230
+ spatial references to your databases when rake db:create is run.
207
231
  * Include "postgis" in your <i>schema_search_path</i> for both your
208
232
  development and test databases. It is recommended that you include it
209
233
  as the <i>last</i> element, so that your application's tables don't get
@@ -226,7 +250,7 @@ Finally, you generally should _not_ set the \ActiveRecord schema format
226
250
  to <tt>:sql</tt>. You should leave it set to <tt>:ruby</tt>. The reason
227
251
  is that SQL structure dumps do not currently properly emit the correct
228
252
  <tt>AddGeometryColumn</tt> calls to create geometry columns. As a result,
229
- the <tt>geometry_columns</tt> table will not be properly populated, among
253
+ the <tt>geometry_columns</tt> table will not be populated properly, among
230
254
  other issues. Instead, the schema.rb output by the Ruby schema format
231
255
  should properly replicate the schema. This is a known issue that we are
232
256
  investigating.
@@ -251,6 +275,9 @@ current known issues.
251
275
  on a SQL dump to be an accurate representation of the schema. (That is,
252
276
  you should not set <tt>config.active_record.schema_format</tt> to
253
277
  <tt>:sql</tt>.)
278
+ * Other rake tasks may not be supported. Unfortunately, Rails makes it
279
+ difficult for custom \ActiveRecord adapters to support the standard
280
+ rake tasks.
254
281
 
255
282
  === Development and support
256
283
 
@@ -280,7 +307,7 @@ source gave us a head start on the implementation.
280
307
 
281
308
  === License
282
309
 
283
- Copyright 2010-2011 Daniel Azuma
310
+ Copyright 2010-2012 Daniel Azuma
284
311
 
285
312
  All rights reserved.
286
313
 
data/Version CHANGED
@@ -1 +1 @@
1
- 0.4.1
1
+ 0.4.2
@@ -71,7 +71,7 @@ def create_database(config_)
71
71
  conn_.execute("CREATE SCHEMA #{schema_}#{auth_}") unless schema_.downcase == 'public'
72
72
  end
73
73
 
74
- # Define the postgis stuff, if the script_dir is provided.
74
+ # Install postgis definitions into the database.
75
75
  # Note: a superuser is required to run the postgis definitions.
76
76
  # If a separate superuser is provided, we need to grant privileges on
77
77
  # the postgis definitions over to the regular user afterwards.
@@ -79,11 +79,23 @@ def create_database(config_)
79
79
  # If "postgis" is present in the search path, use it.
80
80
  # Otherwise, use the last schema in the search path.
81
81
  # If no search path is given, use "public".
82
- if (script_dir_ = config_['script_dir'])
82
+ script_dir_ = config_['script_dir']
83
+ postgis_extension_ = config_['postgis_extension']
84
+ if script_dir_ || postgis_extension_
83
85
  postgis_schema_ = search_path_.include?('postgis') ? 'postgis' : (search_path_.last || 'public')
84
- conn_.execute("SET search_path TO #{postgis_schema_}")
85
- conn_.execute(::File.read(::File.expand_path('postgis.sql', script_dir_)))
86
- conn_.execute(::File.read(::File.expand_path('spatial_ref_sys.sql', script_dir_)))
86
+ if script_dir_
87
+ # Use script_dir (for postgresql < 9.1 or postgis < 2.0)
88
+ conn_.execute("SET search_path TO #{postgis_schema_}")
89
+ conn_.execute(::File.read(::File.expand_path('postgis.sql', script_dir_)))
90
+ conn_.execute(::File.read(::File.expand_path('spatial_ref_sys.sql', script_dir_)))
91
+ elsif postgis_extension_
92
+ # Use postgis_extension (for postgresql >= 9.1 and postgis >= 2.0)
93
+ postgis_extension_ = 'postgis' if postgis_extension_ == true
94
+ postgis_extension_ = postgis_extension_.to_s.split(',') unless postgis_extension_.is_a?(::Array)
95
+ postgis_extension_.each do |extname_|
96
+ conn_.execute("CREATE EXTENSION #{extname_} SCHEMA #{postgis_schema_}")
97
+ end
98
+ end
87
99
  if has_su_
88
100
  conn_.execute("GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA #{postgis_schema_} TO #{username_}")
89
101
  conn_.execute("GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA #{postgis_schema_} TO #{username_}")
@@ -122,16 +134,26 @@ end
122
134
  ::ENV['PGHOST'] = config_["host"] if config_["host"]
123
135
  ::ENV['PGPORT'] = config_["port"].to_s if config_["port"]
124
136
  ::ENV['PGPASSWORD'] = config_["password"].to_s if config_["password"]
137
+ filename_ = ::File.join(::Rails.root, "db/#{::Rails.env}_structure.sql")
125
138
  search_path_ = config_["schema_search_path"].to_s.strip
126
139
  search_path_ = search_path_.split(",").map{ |sp_| sp_.strip }
127
140
  search_path_.delete('postgis')
128
141
  search_path_ = ['public'] if search_path_.length == 0
129
142
  search_path_ = search_path_.map{ |sp_| "--schema=#{sp_}" }.join(" ")
130
- `pg_dump -i -U "#{config_["username"]}" -s -x -O -f db/#{::Rails.env}_structure.sql #{search_path_} #{config_["database"]}`
143
+ `pg_dump -i -U "#{config_["username"]}" -s -x -O -f #{filename_} #{search_path_} #{config_["database"]}`
131
144
  raise "Error dumping database" if $?.exitstatus == 1
132
145
  end
133
146
 
134
147
 
148
+ ::RGeo::ActiveRecord::TaskHacker.modify('db:structure:load', nil, 'postgis') do |config_|
149
+ ::ENV['PGHOST'] = config_["host"] if config_["host"]
150
+ ::ENV['PGPORT'] = config_["port"].to_s if config_["port"]
151
+ ::ENV['PGPASSWORD'] = config_["password"].to_s if config_["password"]
152
+ filename_ = ::File.join(::Rails.root, "db/#{::Rails.env}_structure.sql")
153
+ `psql -f #{filename_} #{config_["database"]}`
154
+ end
155
+
156
+
135
157
  ::RGeo::ActiveRecord::TaskHacker.modify('db:test:clone_structure', 'test', 'postgis') do |config_|
136
158
  ::ENV['PGHOST'] = config_["host"] if config_["host"]
137
159
  ::ENV['PGPORT'] = config_["port"].to_s if config_["port"]
@@ -98,6 +98,8 @@ module ActiveRecord
98
98
  def quote(value_, column_=nil)
99
99
  if ::RGeo::Feature::Geometry.check_type(value_)
100
100
  "'#{::RGeo::WKRep::WKBGenerator.new(:hex_format => true, :type_format => :ewkb, :emit_ewkb_srid => true).generate(value_)}'"
101
+ elsif value_.is_a?(::RGeo::Cartesian::BoundingBox)
102
+ "'#{value_.min_x},#{value_.min_y},#{value_.max_x},#{value_.max_y}'::box"
101
103
  else
102
104
  super
103
105
  end
@@ -118,9 +120,9 @@ module ActiveRecord
118
120
  # We needed to return a spatial column subclass.
119
121
  table_name_ = table_name_.to_s
120
122
  spatial_info_ = spatial_column_info(table_name_)
121
- column_definitions(table_name_).collect do |name_, type_, default_, notnull_|
122
- SpatialColumn.new(@rgeo_factory_settings, table_name_, name_, default_, type_,
123
- notnull_ == 'f', type_ =~ /geometry/i ? spatial_info_[name_] : nil)
123
+ column_definitions(table_name_).collect do |col_name_, type_, default_, notnull_|
124
+ SpatialColumn.new(@rgeo_factory_settings, table_name_, col_name_, default_, type_,
125
+ notnull_ == 'f', type_ =~ /geometry/i ? spatial_info_[col_name_] : nil)
124
126
  end
125
127
  end
126
128
 
@@ -52,7 +52,6 @@ module ActiveRecord
52
52
  def initialize(factory_settings_, table_name_, name_, default_, sql_type_=nil, null_=true, opts_=nil)
53
53
  @factory_settings = factory_settings_
54
54
  @table_name = table_name_
55
- super(name_, default_, sql_type_, null_)
56
55
  @geographic = sql_type_ =~ /geography/i ? true : false
57
56
  if opts_
58
57
  # This case comes from an entry in the geometry_columns table
@@ -79,7 +78,7 @@ module ActiveRecord
79
78
  end
80
79
  end
81
80
  end
82
- elsif type == :spatial
81
+ elsif sql_type_ =~ /geography|geometry|point|linestring|polygon/i
83
82
  # Just in case there is a geometry column with no geometry_columns entry.
84
83
  @geometric_type = ::RGeo::Feature::Geometry
85
84
  @srid = @has_z = @has_m = nil
@@ -87,6 +86,7 @@ module ActiveRecord
87
86
  # Non-spatial column
88
87
  @geometric_type = @has_z = @has_m = @srid = nil
89
88
  end
89
+ super(name_, default_, sql_type_, null_)
90
90
  if type == :spatial
91
91
  if @srid
92
92
  @limit = {:srid => @srid, :type => @geometric_type.type_name.underscore}
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-postgis-adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,22 +9,27 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-23 00:00:00.000000000 Z
12
+ date: 2012-04-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rgeo-activerecord
16
- requirement: &2155891880 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: 0.4.3
21
+ version: 0.4.4
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2155891880
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 0.4.4
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: pg
27
- requirement: &2155890820 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,7 +37,12 @@ dependencies:
32
37
  version: 0.11.0
33
38
  type: :runtime
34
39
  prerelease: false
35
- version_requirements: *2155890820
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 0.11.0
36
46
  description: This is an ActiveRecord connection adapter for PostGIS. It is based on
37
47
  the stock PostgreSQL adapter, but provides built-in support for the spatial extensions
38
48
  provided by PostGIS. It uses the RGeo library to represent spatial data in Ruby.
@@ -78,7 +88,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
78
88
  version: 1.3.1
79
89
  requirements: []
80
90
  rubyforge_project: virtuoso
81
- rubygems_version: 1.8.17
91
+ rubygems_version: 1.8.19
82
92
  signing_key:
83
93
  specification_version: 3
84
94
  summary: An ActiveRecord adapter for PostGIS, based on RGeo.