activerecord-spatial 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
-
|