activerecord-spatial 1.0.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1670 -0
- data/Gemfile +12 -13
- data/Guardfile +7 -10
- data/MIT-LICENSE +1 -1
- data/README.rdoc +8 -19
- data/Rakefile +2 -1
- data/activerecord-spatial.gemspec +12 -13
- data/lib/activerecord-spatial/active_record/connection_adapters/postgresql/adapter_extensions/active_record.rb +46 -0
- data/lib/activerecord-spatial/active_record/connection_adapters/postgresql/adapter_extensions.rb +7 -38
- data/lib/activerecord-spatial/active_record/connection_adapters/postgresql/postgis.rb +6 -7
- data/lib/activerecord-spatial/active_record/connection_adapters/postgresql/unknown_srid.rb +4 -5
- data/lib/activerecord-spatial/active_record/models/geography_column.rb +1 -2
- data/lib/activerecord-spatial/active_record/models/geometry_column.rb +1 -2
- data/lib/activerecord-spatial/active_record/models/spatial_column.rb +1 -2
- data/lib/activerecord-spatial/active_record/models/spatial_ref_sys.rb +5 -6
- data/lib/activerecord-spatial/active_record.rb +0 -1
- data/lib/activerecord-spatial/associations/active_record.rb +62 -120
- data/lib/activerecord-spatial/associations/base.rb +26 -75
- data/lib/activerecord-spatial/associations/preloader/spatial_association.rb +57 -0
- data/lib/activerecord-spatial/associations/reflection/spatial_reflection.rb +41 -0
- data/lib/activerecord-spatial/associations.rb +26 -4
- data/lib/activerecord-spatial/spatial_columns.rb +85 -94
- data/lib/activerecord-spatial/spatial_function.rb +62 -51
- data/lib/activerecord-spatial/spatial_scope_constants/postgis_2_0.rb +48 -0
- data/lib/activerecord-spatial/spatial_scope_constants/postgis_2_2.rb +46 -0
- data/lib/activerecord-spatial/spatial_scope_constants/postgis_legacy.rb +30 -0
- data/lib/activerecord-spatial/spatial_scope_constants.rb +10 -61
- data/lib/activerecord-spatial/spatial_scopes.rb +47 -49
- data/lib/activerecord-spatial/version.rb +1 -2
- data/lib/activerecord-spatial.rb +2 -6
- data/lib/tasks/test.rake +21 -19
- data/test/.rubocop.yml +35 -0
- data/test/accessors_geographies_tests.rb +19 -19
- data/test/accessors_geometries_tests.rb +19 -19
- data/test/adapter_tests.rb +1 -2
- data/test/associations_tests.rb +181 -203
- data/test/geography_column_tests.rb +2 -3
- data/test/geometry_column_tests.rb +1 -2
- data/test/models/bar.rb +2 -3
- data/test/models/blort.rb +1 -2
- data/test/models/foo.rb +2 -3
- data/test/models/foo3d.rb +2 -3
- data/test/models/foo_geography.rb +2 -3
- data/test/models/zortable.rb +2 -3
- data/test/spatial_function_tests.rb +12 -17
- data/test/spatial_scopes_geographies_tests.rb +17 -20
- data/test/spatial_scopes_tests.rb +84 -75
- data/test/test_helper.rb +66 -79
- metadata +16 -14
- data/lib/activerecord-spatial/associations/active_record_3.rb +0 -123
data/Gemfile
CHANGED
@@ -2,20 +2,19 @@ source 'https://rubygems.org'
|
|
2
2
|
|
3
3
|
gemspec
|
4
4
|
|
5
|
-
if RUBY_PLATFORM ==
|
6
|
-
gem
|
5
|
+
if RUBY_PLATFORM == 'java'
|
6
|
+
gem 'activerecord-jdbcpostgresql-adapter'
|
7
7
|
else
|
8
|
-
gem
|
8
|
+
gem 'pg'
|
9
9
|
end
|
10
10
|
|
11
|
-
gem
|
12
|
-
gem
|
13
|
-
gem
|
14
|
-
gem
|
15
|
-
gem
|
16
|
-
gem
|
17
|
-
|
18
|
-
|
19
|
-
instance_eval File.read('Gemfile.local')
|
20
|
-
end
|
11
|
+
gem 'activerecord-testcase'
|
12
|
+
gem 'guard'
|
13
|
+
gem 'guard-minitest'
|
14
|
+
gem 'minitest'
|
15
|
+
gem 'minitest-reporters'
|
16
|
+
gem 'rake'
|
17
|
+
gem 'rdoc'
|
18
|
+
gem 'simplecov'
|
21
19
|
|
20
|
+
instance_eval File.read('Gemfile.local') if File.exist?('Gemfile.local')
|
data/Guardfile
CHANGED
@@ -1,17 +1,14 @@
|
|
1
1
|
|
2
|
-
guard 'minitest', :
|
3
|
-
watch(%r
|
2
|
+
guard 'minitest', test_folders: 'test', test_file_patterns: '*_tests.rb' do
|
3
|
+
watch(%r{^test/(.+)_tests\.rb})
|
4
4
|
|
5
|
-
watch(%r
|
6
|
-
"test/#{m[
|
5
|
+
watch(%r{^lib/(.*/)?([^/]+)\.rb$}) do |m|
|
6
|
+
"test/#{m[2]}_tests.rb"
|
7
7
|
end
|
8
8
|
|
9
|
-
watch(%r
|
10
|
-
|
9
|
+
watch(%r{^test/test_helper\.rb}) do
|
10
|
+
'test'
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
if File.
|
15
|
-
instance_eval File.read('Guardfile.local')
|
16
|
-
end
|
17
|
-
|
14
|
+
instance_eval File.read('Guardfile.local') if File.exist?('Guardfile.local')
|
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -107,31 +107,21 @@ See the test/database.yml file for example settings.
|
|
107
107
|
|
108
108
|
== ActiveRecord Versions Supported
|
109
109
|
|
110
|
-
We're starting to standardize on Rails
|
111
|
-
this gem function on versions of Rails
|
110
|
+
We're starting to standardize on Rails 5 for our purposes, so future versions
|
111
|
+
this gem function on versions of Rails 5 and above. To use spatial scopes on
|
112
112
|
previous versions of ActiveRecord, see our geos-extensions gem available at
|
113
113
|
https://github.com/dark-panda/geos-extensions . We have pulled the ActiveRecord
|
114
114
|
extensions out of that gem and are instead packaging them here, thus allowing
|
115
115
|
you to use the actual Geos extensions in an unfettered way. If you wish to
|
116
|
-
use the spatial extensions with versions of Rails prior to
|
117
|
-
the
|
118
|
-
|
119
|
-
=== Note About ActiveRecord 4.0.0
|
120
|
-
|
121
|
-
Rails 4.0.0 introducted a backwards incompatible change involving `order`
|
122
|
-
scopes where `ORDER BY` would be added in the opposite order compared to
|
123
|
-
previous versions of Rails. This change was reverted in Rails 4.0.1. Because
|
124
|
-
the change only lasted for a single version, we have decided that we will
|
125
|
-
not be supporting Rails 4.0.0 and will only support versions of Rails that
|
126
|
-
feature `order` scopes that are consistent with the behaviour prior to Rails
|
127
|
-
4.0.0. This includes Rails 4.0.1 and above.
|
116
|
+
use the spatial extensions with versions of Rails prior to 5, see versions of
|
117
|
+
the ActiveRecordSpatial gem prior to version 1.0.0.
|
128
118
|
|
129
119
|
== PostGIS and PostgreSQL Versions Supported
|
130
120
|
|
131
|
-
As of this writing, things
|
132
|
-
|
133
|
-
|
134
|
-
|
121
|
+
As of this writing, things we test on PostgreSQL 9.4 and PostGIS 2.1+.
|
122
|
+
Some features are only available in PostGIS 2.0, such as the +st_3dintersects+
|
123
|
+
scope and the like, as that spatial relationship function was added in PostGIS
|
124
|
+
2.0.
|
135
125
|
|
136
126
|
PostgreSQL 9.0 and below are currently not supported as some of the SQL we
|
137
127
|
produce to create the spatial queries is not supported in older PostgreSQL
|
@@ -176,4 +166,3 @@ most projects.
|
|
176
166
|
|
177
167
|
This gem is licensed under an MIT-style license. See the +MIT-LICENSE+ file for
|
178
168
|
details.
|
179
|
-
|
data/Rakefile
CHANGED
@@ -7,7 +7,7 @@ require 'rake/testtask'
|
|
7
7
|
require 'rdoc/task'
|
8
8
|
require 'bundler/gem_tasks'
|
9
9
|
|
10
|
-
|
10
|
+
$LOAD_PATH.push File.expand_path(File.dirname(__FILE__), 'lib')
|
11
11
|
|
12
12
|
version = ActiveRecordSpatial::VERSION
|
13
13
|
|
@@ -26,3 +26,4 @@ Rake::RDocTask.new do |t|
|
|
26
26
|
t.rdoc_files.include('README.rdoc', 'MIT-LICENSE', 'lib/**/*.rb')
|
27
27
|
end
|
28
28
|
|
29
|
+
task default: :test
|
@@ -3,25 +3,24 @@
|
|
3
3
|
require File.expand_path('../lib/activerecord-spatial/version', __FILE__)
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
|
-
s.name =
|
6
|
+
s.name = 'activerecord-spatial'
|
7
7
|
s.version = ActiveRecordSpatial::VERSION
|
8
8
|
|
9
|
-
s.required_rubygems_version = Gem::Requirement.new(
|
10
|
-
s.authors = [
|
11
|
-
s.description =
|
9
|
+
s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
|
10
|
+
s.authors = ['J Smith']
|
11
|
+
s.description = 'ActiveRecord Spatial gives AR the ability to work with PostGIS columns.'
|
12
12
|
s.summary = s.description
|
13
|
-
s.email =
|
14
|
-
s.license =
|
13
|
+
s.email = 'dark.panda@gmail.com'
|
14
|
+
s.license = 'MIT'
|
15
15
|
s.extra_rdoc_files = [
|
16
|
-
|
16
|
+
'README.rdoc'
|
17
17
|
]
|
18
|
-
s.files = `git ls-files`.split(
|
18
|
+
s.files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
|
19
19
|
s.executables = s.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
20
20
|
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
21
|
-
s.homepage =
|
22
|
-
s.require_paths = [
|
21
|
+
s.homepage = 'https://github.com/dark-panda/activerecord-spatial'
|
22
|
+
s.require_paths = ['lib']
|
23
23
|
|
24
|
-
s.add_dependency(
|
25
|
-
s.add_dependency(
|
24
|
+
s.add_dependency('rails', ['>= 5.0'])
|
25
|
+
s.add_dependency('geos-extensions', ['>= 0.5'])
|
26
26
|
end
|
27
|
-
|
@@ -0,0 +1,46 @@
|
|
1
|
+
|
2
|
+
module ActiveRecord
|
3
|
+
module Type
|
4
|
+
class Geometry < Value
|
5
|
+
def type
|
6
|
+
:geometry
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Geography < Value
|
11
|
+
def type
|
12
|
+
:geography
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module ConnectionAdapters
|
18
|
+
module PostgreSQL
|
19
|
+
module OID
|
20
|
+
class Geometry < Type::Geometry
|
21
|
+
end
|
22
|
+
|
23
|
+
class Geography < Type::Geography
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::NATIVE_DATABASE_TYPES[:geometry] = {
|
31
|
+
name: 'geometry'
|
32
|
+
}
|
33
|
+
|
34
|
+
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::NATIVE_DATABASE_TYPES[:geometry] = {
|
35
|
+
name: 'geography'
|
36
|
+
}
|
37
|
+
|
38
|
+
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.class_eval do
|
39
|
+
prepend(Module.new do
|
40
|
+
def initialize_type_map(type_map)
|
41
|
+
super
|
42
|
+
type_map.register_type 'geometry', ::ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Geometry.new
|
43
|
+
type_map.register_type 'geography', ::ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Geography.new
|
44
|
+
end
|
45
|
+
end)
|
46
|
+
end
|
data/lib/activerecord-spatial/active_record/connection_adapters/postgresql/adapter_extensions.rb
CHANGED
@@ -1,26 +1,15 @@
|
|
1
1
|
|
2
2
|
require 'active_record/connection_adapters/postgresql_adapter'
|
3
|
+
require 'activerecord-spatial/active_record/connection_adapters/postgresql/adapter_extensions/active_record'
|
4
|
+
|
5
|
+
module ActiveRecordSpatial
|
6
|
+
autoload :POSTGIS, 'activerecord-spatial/active_record/connection_adapters/postgresql/postgis'
|
7
|
+
autoload :UNKNOWN_SRID, 'activerecord-spatial/active_record/connection_adapters/postgresql/unknown_srid'
|
8
|
+
autoload :UNKNOWN_SRIDS, 'activerecord-spatial/active_record/connection_adapters/postgresql/unknown_srid'
|
9
|
+
end
|
3
10
|
|
4
11
|
module ActiveRecord
|
5
12
|
module ConnectionAdapters
|
6
|
-
class PostgreSQLColumn
|
7
|
-
def simplified_type_with_spatial_type(field_type)
|
8
|
-
case field_type
|
9
|
-
# This is a special internal type used by PostgreSQL. In this case,
|
10
|
-
# it is being used by the `geography_columns` view in PostGIS.
|
11
|
-
when 'name'
|
12
|
-
:string
|
13
|
-
when /^geometry(\(|$)/
|
14
|
-
:geometry
|
15
|
-
when /^geography(\(|$)/
|
16
|
-
:geography
|
17
|
-
else
|
18
|
-
simplified_type_without_spatial_type(field_type)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
alias_method_chain :simplified_type, :spatial_type
|
22
|
-
end
|
23
|
-
|
24
13
|
class PostgreSQLAdapter
|
25
14
|
def geometry_columns?
|
26
15
|
true
|
@@ -29,26 +18,6 @@ module ActiveRecord
|
|
29
18
|
def geography_columns?
|
30
19
|
ActiveRecordSpatial::POSTGIS[:lib] >= '1.5'
|
31
20
|
end
|
32
|
-
|
33
|
-
if defined?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::OID)
|
34
|
-
module OID
|
35
|
-
class Spatial < Type
|
36
|
-
def type_cast(value)
|
37
|
-
value
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
register_type 'geometry', OID::Spatial.new
|
42
|
-
register_type 'geography', OID::Spatial.new
|
43
|
-
end
|
44
|
-
end
|
45
21
|
end
|
46
22
|
end
|
47
23
|
end
|
48
|
-
|
49
|
-
module ActiveRecordSpatial
|
50
|
-
autoload :POSTGIS, 'activerecord-spatial/active_record/connection_adapters/postgresql/postgis'
|
51
|
-
autoload :UNKNOWN_SRID, 'activerecord-spatial/active_record/connection_adapters/postgresql/unknown_srid'
|
52
|
-
autoload :UNKNOWN_SRIDS, 'activerecord-spatial/active_record/connection_adapters/postgresql/unknown_srid'
|
53
|
-
end
|
54
|
-
|
@@ -1,16 +1,16 @@
|
|
1
1
|
|
2
2
|
module ActiveRecordSpatial
|
3
3
|
POSTGIS = begin
|
4
|
-
if (version_string = ::ActiveRecord::Base.connection.select_rows(
|
4
|
+
if (version_string = ::ActiveRecord::Base.connection.select_rows('SELECT postgis_full_version()').flatten.first).present?
|
5
5
|
hash = {
|
6
|
-
:
|
6
|
+
use_stats: version_string =~ /USE_STATS/
|
7
7
|
}
|
8
8
|
|
9
9
|
{
|
10
|
-
:
|
11
|
-
:
|
12
|
-
:
|
13
|
-
:
|
10
|
+
lib: /POSTGIS="([^"]+)"/,
|
11
|
+
geos: /GEOS="([^"]+)"/,
|
12
|
+
proj: /PROJ="([^"]+)"/,
|
13
|
+
libxml: /LIBXML="([^"]+)"/
|
14
14
|
}.each do |k, v|
|
15
15
|
hash[k] = version_string.scan(v).flatten.first
|
16
16
|
end
|
@@ -21,4 +21,3 @@ module ActiveRecordSpatial
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
24
|
-
|
@@ -3,13 +3,13 @@ module ActiveRecordSpatial
|
|
3
3
|
UNKNOWN_SRIDS = begin
|
4
4
|
if ActiveRecordSpatial::POSTGIS[:lib] >= '2.0'
|
5
5
|
{
|
6
|
-
:
|
7
|
-
:
|
6
|
+
geography: 0,
|
7
|
+
geometry: 0
|
8
8
|
}.freeze
|
9
9
|
else
|
10
10
|
{
|
11
|
-
:
|
12
|
-
:
|
11
|
+
geography: 0,
|
12
|
+
geometry: -1
|
13
13
|
}.freeze
|
14
14
|
end
|
15
15
|
end
|
@@ -18,4 +18,3 @@ module ActiveRecordSpatial
|
|
18
18
|
ActiveRecordSpatial::UNKNOWN_SRIDS[:geometry]
|
19
19
|
end
|
20
20
|
end
|
21
|
-
|
@@ -11,7 +11,7 @@ module ActiveRecordSpatial
|
|
11
11
|
self.inheritance_column = 'nonexistent_column_name_type'
|
12
12
|
|
13
13
|
belongs_to :spatial_ref_sys,
|
14
|
-
:
|
14
|
+
foreign_key: :srid
|
15
15
|
end
|
16
16
|
|
17
17
|
def readonly?
|
@@ -19,4 +19,3 @@ module ActiveRecordSpatial
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
22
|
-
|
@@ -5,16 +5,15 @@ module ActiveRecordSpatial
|
|
5
5
|
self.primary_key = 'srid'
|
6
6
|
|
7
7
|
has_many :geometry_columns,
|
8
|
-
:
|
9
|
-
:
|
8
|
+
foreign_key: :srid,
|
9
|
+
inverse_of: :spatial_ref_sys
|
10
10
|
|
11
11
|
has_many :geography_columns,
|
12
|
-
:
|
13
|
-
:
|
12
|
+
foreign_key: :srid,
|
13
|
+
inverse_of: :spatial_ref_sys
|
14
14
|
|
15
15
|
def spatial_columns
|
16
|
-
|
16
|
+
geometry_columns + geography_columns
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
20
|
-
|
@@ -1,146 +1,88 @@
|
|
1
|
-
# encoding: UTF-8
|
2
1
|
|
3
2
|
module ActiveRecord
|
4
|
-
module Associations
|
5
|
-
class Builder::Spatial < Builder::HasMany #:nodoc:
|
6
|
-
def macro
|
7
|
-
SPATIAL_MACRO
|
8
|
-
end
|
9
|
-
|
10
|
-
def valid_options
|
11
|
-
super + VALID_SPATIAL_OPTIONS - INVALID_SPATIAL_OPTIONS
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
3
|
+
module Associations #:nodoc:
|
15
4
|
class Preloader #:nodoc:
|
16
5
|
class SpatialAssociation < HasMany #:nodoc:
|
17
|
-
|
18
|
-
table_name = reflection.quoted_table_name
|
19
|
-
join_name = model.quoted_table_name
|
20
|
-
column = %{#{SPATIAL_JOIN_QUOTED_NAME}.#{model.quoted_primary_key}}
|
21
|
-
geom = {
|
22
|
-
:class => model,
|
23
|
-
:table_alias => SPATIAL_JOIN_NAME
|
24
|
-
}
|
25
|
-
|
26
|
-
if reflection.options[:geom].is_a?(Hash)
|
27
|
-
geom.merge!(reflection.options[:geom])
|
28
|
-
else
|
29
|
-
geom[:column] = reflection.options[:geom]
|
30
|
-
end
|
6
|
+
private
|
31
7
|
|
32
|
-
|
33
|
-
|
34
|
-
joins(
|
35
|
-
"INNER JOIN #{join_name} AS #{SPATIAL_JOIN_QUOTED_NAME} ON (" <<
|
36
|
-
klass.send("st_#{reflection.options[:relationship]}",
|
37
|
-
geom,
|
38
|
-
(reflection.options[:scope_options] || {}).merge(
|
39
|
-
:column => reflection.options[:foreign_geom]
|
40
|
-
)
|
41
|
-
).where_values.join(' AND ') <<
|
42
|
-
")"
|
43
|
-
).
|
44
|
-
where(model.arel_table.alias(SPATIAL_JOIN_NAME)[model.primary_key].in(ids)).
|
45
|
-
group(table[klass.primary_key])
|
46
|
-
|
47
|
-
if reflection.options[:conditions]
|
48
|
-
scoped = scoped.where(reflection.options[:conditions])
|
49
|
-
end
|
8
|
+
def load_records(&block)
|
9
|
+
return {} if owner_keys.empty?
|
50
10
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
11
|
+
slices = owner_keys.each_slice(klass.connection.in_clause_length || owner_keys.size)
|
12
|
+
@preloaded_records = slices.flat_map do |slice|
|
13
|
+
records_for(slice).load(&block)
|
14
|
+
end
|
55
15
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
table, foreign_table = tables.shift, tables.first
|
64
|
-
|
65
|
-
geom_options = {
|
66
|
-
:class => self.association.klass
|
67
|
-
}
|
68
|
-
|
69
|
-
if self.association.geom.is_a?(Hash)
|
70
|
-
geom_options.merge!(
|
71
|
-
:value => owner[self.association.geom[:name]]
|
72
|
-
)
|
73
|
-
geom_options.merge!(self.association.geom)
|
74
|
-
else
|
75
|
-
geom_options.merge!(
|
76
|
-
:value => owner[self.association.geom],
|
77
|
-
:name => self.association.geom
|
78
|
-
)
|
16
|
+
@preloaded_records.each_with_object({}) do |record, memo|
|
17
|
+
keys = record[association_key_name].split(',')
|
18
|
+
keys.each do |key|
|
19
|
+
memo[key] ||= []
|
20
|
+
memo[key] << record
|
21
|
+
end
|
22
|
+
end
|
79
23
|
end
|
80
24
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
constraint = scope.where(
|
89
|
-
scope.send(
|
90
|
-
"st_#{self.association.relationship}",
|
91
|
-
owner[self.association.foreign_geom],
|
92
|
-
self.association.scope_options
|
93
|
-
).where_values
|
94
|
-
).join(' AND ')
|
95
|
-
|
96
|
-
if reflection.type
|
97
|
-
type = chain[i + 1].klass.base_class.name
|
98
|
-
constraint = table[reflection.type].eq(type).and(constraint)
|
25
|
+
def associated_records_by_owner(_preloader)
|
26
|
+
records = load_records do |record|
|
27
|
+
record[association_key_name].split(',').each do |key|
|
28
|
+
owner = owners_by_key[convert_key(key)]
|
29
|
+
association = owner.association(reflection.name)
|
30
|
+
association.set_inverse_instance(record)
|
31
|
+
end
|
99
32
|
end
|
100
33
|
|
101
|
-
|
34
|
+
owners.each_with_object({}) do |owner, result|
|
35
|
+
result[owner] = records[convert_key(owner[owner_key_name])] || []
|
36
|
+
end
|
102
37
|
end
|
38
|
+
end
|
39
|
+
end
|
103
40
|
|
104
|
-
|
105
|
-
|
106
|
-
|
41
|
+
class SpatialAssociation < HasManyAssociation #:nodoc:
|
42
|
+
def association_scope
|
43
|
+
return unless klass
|
107
44
|
|
108
|
-
|
109
|
-
|
110
|
-
scope_chain[i].each do |scope_chain_item|
|
111
|
-
klass = i == 0 ? self.klass : reflection.klass
|
112
|
-
item = eval_scope(klass, scope_chain_item)
|
45
|
+
@association_scope ||= SpatialAssociationScope.scope(self, klass.connection)
|
46
|
+
end
|
113
47
|
|
114
|
-
|
115
|
-
scope.merge! item.except(:where, :includes)
|
116
|
-
end
|
48
|
+
private
|
117
49
|
|
118
|
-
|
119
|
-
|
120
|
-
scope.order_values |= item.order_values
|
121
|
-
end
|
50
|
+
def get_records
|
51
|
+
scope.to_a
|
122
52
|
end
|
53
|
+
end
|
123
54
|
|
124
|
-
|
55
|
+
class SpatialAssociationScope < AssociationScope #:nodoc:
|
56
|
+
INSTANCE = create
|
57
|
+
|
58
|
+
class << self
|
59
|
+
def scope(association, connection)
|
60
|
+
INSTANCE.scope(association, connection)
|
61
|
+
end
|
125
62
|
end
|
126
|
-
alias_method_chain :add_constraints, :spatial
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
130
63
|
|
64
|
+
def last_chain_scope(scope, table, reflection, owner, assoc_klass)
|
65
|
+
geom_options = {
|
66
|
+
class: assoc_klass
|
67
|
+
}
|
68
|
+
|
69
|
+
if reflection.geom.is_a?(Hash)
|
70
|
+
geom_options[:value] = owner[reflection.geom[:name]]
|
71
|
+
geom_options.merge!(reflection.geom)
|
72
|
+
else
|
73
|
+
geom_options[:value] = owner[reflection.geom]
|
74
|
+
geom_options[:name] = reflection.geom
|
75
|
+
end
|
131
76
|
|
132
|
-
|
133
|
-
module ClassMethods #:nodoc:
|
134
|
-
def has_many_spatially(name, *args, &extension)
|
135
|
-
options = build_options(args.extract_options!)
|
136
|
-
scope = args.first
|
77
|
+
scope = scope.send("st_#{reflection.relationship}", geom_options, reflection.scope_options)
|
137
78
|
|
138
|
-
|
139
|
-
|
140
|
-
|
79
|
+
if reflection.type
|
80
|
+
polymorphic_type = transform_value(owner.class.base_class.name)
|
81
|
+
scope = scope.where(table.name => { reflection.type => polymorphic_type })
|
82
|
+
end
|
141
83
|
|
142
|
-
|
84
|
+
scope
|
85
|
+
end
|
143
86
|
end
|
144
87
|
end
|
145
88
|
end
|
146
|
-
|