spatial_features 2.7.4 → 2.7.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/models/spatial_cache.rb +1 -1
- data/lib/spatial_features/caching.rb +16 -6
- data/lib/spatial_features/has_spatial_features.rb +9 -8
- data/lib/spatial_features/utils.rb +20 -1
- data/lib/spatial_features/venn_polygons.rb +1 -1
- data/lib/spatial_features/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 13dafdeb45681a5a529ee77c0c54d8306d35858e7c715c8f6845bf7bac4ff51e
|
4
|
+
data.tar.gz: 9789d728e2a2fcd7cb3903637bb3fa61c01e323c99b38bf677fbfcdc06cc2bb4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0f614d22d3df5c3fbdeda0875d95b31b7a2b843ee012aafa240996a3ffe6ea00c1854b470945dcf3151ed3427daac680856c176b72419fad3f18dfa00418307
|
7
|
+
data.tar.gz: e0b1535e925c8376fcfb20a13e70d1f1ae80dcfc7b709f755140aae94b70f8118dd95c7cd040d7f8441493d79d339e106838e3f757cac7eec2249023b0f7657c
|
data/app/models/spatial_cache.rb
CHANGED
@@ -3,7 +3,7 @@ class SpatialCache < ActiveRecord::Base
|
|
3
3
|
|
4
4
|
def self.between(spatial_model, klass)
|
5
5
|
where(SpatialFeatures::Utils.polymorphic_condition(spatial_model, 'spatial_model'))
|
6
|
-
.where(:intersection_model_type => klass
|
6
|
+
.where(:intersection_model_type => SpatialFeatures::Utils.class_name_with_ancestors(klass))
|
7
7
|
end
|
8
8
|
|
9
9
|
def stale?
|
@@ -3,7 +3,7 @@ module SpatialFeatures
|
|
3
3
|
self.default_cache_buffer_in_meters = 100
|
4
4
|
|
5
5
|
def self.update_proximity(*klasses)
|
6
|
-
klasses
|
6
|
+
class_permutations(klasses).each do |klass, clazz|
|
7
7
|
klass.without_spatial_cache(clazz).find_each do |record|
|
8
8
|
cache_record_proximity(record, clazz)
|
9
9
|
end
|
@@ -26,7 +26,7 @@ module SpatialFeatures
|
|
26
26
|
# NOTE: Arguments are order independent, so their names do not reflect the _a _b
|
27
27
|
# naming scheme used in other cache methods
|
28
28
|
def self.cache_proximity(*klasses)
|
29
|
-
klasses
|
29
|
+
class_combinations(klasses).each do |klass, clazz|
|
30
30
|
clear_cache(klass, clazz)
|
31
31
|
|
32
32
|
klass.find_each do |record|
|
@@ -40,6 +40,16 @@ module SpatialFeatures
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
+
# Returns a list of class pairs with each combination e.g. [a,b], [a,c] [b,c] and also [a,a], [b,b], [c,c]
|
44
|
+
def self.class_combinations(klasses)
|
45
|
+
klasses.zip(klasses) + klasses.combination(2).to_a
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns a list of class pairs with each permutation e.g. [a,b], [b,a] and also [a,a], [b,b]
|
49
|
+
def self.class_permutations(klasses)
|
50
|
+
klasses.zip(klasses) + klasses.permutation(2).to_a
|
51
|
+
end
|
52
|
+
|
43
53
|
# Create or update the spatial cache of a single record in relation to another spatial class
|
44
54
|
def self.cache_record_proximity(record, klass)
|
45
55
|
clear_record_cache(record, klass)
|
@@ -59,14 +69,14 @@ module SpatialFeatures
|
|
59
69
|
end
|
60
70
|
|
61
71
|
def self.clear_record_cache(record, klass)
|
62
|
-
record.spatial_caches.where(:intersection_model_type => klass
|
72
|
+
record.spatial_caches.where(:intersection_model_type => SpatialFeatures::Utils.class_name_with_ancestors(klass)).delete_all
|
63
73
|
SpatialProximity.between(record, klass).delete_all
|
64
74
|
end
|
65
75
|
|
66
76
|
def self.create_spatial_proximities(record, klass)
|
67
77
|
klass = klass.to_s.constantize
|
68
78
|
klass_record = klass.new
|
69
|
-
model_a, model_b = record.
|
79
|
+
model_a, model_b = Utils.base_class(record).to_s < Utils.base_class(klass).to_s ? [record, klass_record] : [klass_record, record]
|
70
80
|
|
71
81
|
scope = klass.within_buffer(record, default_cache_buffer_in_meters, :columns => :id, :intersection_area => true, :distance => true, :cache => false)
|
72
82
|
results = klass.connection.select_rows(scope.to_sql)
|
@@ -76,9 +86,9 @@ module SpatialFeatures
|
|
76
86
|
SpatialProximity.create! do |proximity|
|
77
87
|
# Set id and type instead of model to avoid autosaving the klass_record
|
78
88
|
proximity.model_a_id = model_a.id
|
79
|
-
proximity.model_a_type = model_a
|
89
|
+
proximity.model_a_type = Utils.base_class(model_a)
|
80
90
|
proximity.model_b_id = model_b.id
|
81
|
-
proximity.model_b_type = model_b
|
91
|
+
proximity.model_b_type = Utils.base_class(model_b)
|
82
92
|
proximity.distance_in_meters = distance
|
83
93
|
proximity.intersection_area_in_square_meters = area
|
84
94
|
end
|
@@ -13,10 +13,10 @@ module SpatialFeatures
|
|
13
13
|
has_many :features, lambda { extending FeaturesAssociationExtensions }, :as => :spatial_model, :dependent => :delete_all
|
14
14
|
|
15
15
|
scope :with_features, lambda { joins(:features).uniq }
|
16
|
-
scope :without_features, lambda { joins("LEFT OUTER JOIN features ON features.spatial_model_type = '#{name}' AND features.spatial_model_id = #{table_name}.id").where("features.id IS NULL") }
|
16
|
+
scope :without_features, lambda { joins("LEFT OUTER JOIN features ON features.spatial_model_type = '#{Utils.base_class(name)}' AND features.spatial_model_id = #{table_name}.id").where("features.id IS NULL") }
|
17
17
|
|
18
|
-
scope :with_spatial_cache, lambda {|klass| joins(:spatial_caches).where(:spatial_caches => { :intersection_model_type => klass }).uniq }
|
19
|
-
scope :without_spatial_cache, lambda {|klass| joins("LEFT OUTER JOIN #{SpatialCache.table_name} ON #{SpatialCache.table_name}.spatial_model_id = #{table_name}.id AND #{SpatialCache.table_name}.spatial_model_type = '#{name}' and intersection_model_type
|
18
|
+
scope :with_spatial_cache, lambda {|klass| joins(:spatial_caches).where(:spatial_caches => { :intersection_model_type => Utils.class_name_with_ancestors(klass) }).uniq }
|
19
|
+
scope :without_spatial_cache, lambda {|klass| joins("LEFT OUTER JOIN #{SpatialCache.table_name} ON #{SpatialCache.table_name}.spatial_model_id = #{table_name}.id AND #{SpatialCache.table_name}.spatial_model_type = '#{Utils.base_class(name)}' and intersection_model_type IN ('#{Utils.class_name_with_ancestors(klass).join("','") }')").where("#{SpatialCache.table_name}.spatial_model_id IS NULL") }
|
20
20
|
scope :with_stale_spatial_cache, lambda { joins(:spatial_caches).where("#{table_name}.features_hash != spatial_caches.features_hash").uniq } if has_spatial_features_hash?
|
21
21
|
|
22
22
|
has_many :spatial_caches, :as => :spatial_model, :dependent => :delete_all, :class_name => 'SpatialCache'
|
@@ -113,12 +113,13 @@ module SpatialFeatures
|
|
113
113
|
end
|
114
114
|
|
115
115
|
def cached_spatial_join(other)
|
116
|
-
other_class = Utils.
|
116
|
+
other_class = Utils.base_class_of(other)
|
117
|
+
self_class = Utils.base_class_of(self)
|
117
118
|
|
118
|
-
other_column = other_class.name <
|
119
|
+
other_column = other_class.name < self_class.name ? :model_a : :model_b
|
119
120
|
self_column = other_column == :model_a ? :model_b : :model_a
|
120
121
|
|
121
|
-
joins("INNER JOIN spatial_proximities ON spatial_proximities.#{self_column}_type = '#{
|
122
|
+
joins("INNER JOIN spatial_proximities ON spatial_proximities.#{self_column}_type = '#{self_class}' AND spatial_proximities.#{self_column}_id = #{table_name}.id AND spatial_proximities.#{other_column}_type = '#{other_class}' AND spatial_proximities.#{other_column}_id IN (#{Utils.id_sql(other)})")
|
122
123
|
end
|
123
124
|
|
124
125
|
def uncached_within_buffer_scope(other, buffer_in_meters, options)
|
@@ -153,7 +154,7 @@ module SpatialFeatures
|
|
153
154
|
|
154
155
|
def features_scope(other)
|
155
156
|
scope = Feature
|
156
|
-
scope = scope.where(:spatial_model_type => Utils.
|
157
|
+
scope = scope.where(:spatial_model_type => Utils.base_class_of(other))
|
157
158
|
scope = scope.where(:spatial_model_id => other) unless Utils.class_of(other) == other
|
158
159
|
return scope
|
159
160
|
end
|
@@ -205,7 +206,7 @@ module SpatialFeatures
|
|
205
206
|
end
|
206
207
|
|
207
208
|
def spatial_cache_for?(other, buffer_in_meters)
|
208
|
-
if cache = spatial_caches.between(self,
|
209
|
+
if cache = spatial_caches.between(self, Utils.class_of(other)).first
|
209
210
|
return cache.intersection_cache_distance.nil? if buffer_in_meters.nil? # cache must be total if no buffer_in_meters
|
210
211
|
return false if cache.stale? # cache must be for current features
|
211
212
|
return true if cache.intersection_cache_distance.nil? # always good if cache is total
|
@@ -6,7 +6,26 @@ module SpatialFeatures
|
|
6
6
|
sql = "#{column_name}_type = ?"
|
7
7
|
sql << " AND #{column_name}_id IN (#{id_sql(scope)})" unless scope.is_a?(Class)
|
8
8
|
|
9
|
-
return class_of(scope).send :sanitize_sql, [sql,
|
9
|
+
return class_of(scope).send :sanitize_sql, [sql, base_class_of(scope)]
|
10
|
+
end
|
11
|
+
|
12
|
+
def class_name_with_ancestors(object)
|
13
|
+
class_of(object).ancestors.select {|k| k < ActiveRecord::Base }.map(&:to_s)
|
14
|
+
end
|
15
|
+
|
16
|
+
def base_class_of(object)
|
17
|
+
base_class(class_of(object))
|
18
|
+
end
|
19
|
+
|
20
|
+
def base_class(klass)
|
21
|
+
case klass
|
22
|
+
when String
|
23
|
+
klass.constantize.base_class.to_s
|
24
|
+
when ActiveRecord::Base
|
25
|
+
klass.class.base_class
|
26
|
+
when Class
|
27
|
+
klass.base_class
|
28
|
+
end
|
10
29
|
end
|
11
30
|
|
12
31
|
# Returns the class for the given, class, scope, or record
|
@@ -29,7 +29,7 @@ module SpatialFeatures
|
|
29
29
|
if options[:target]
|
30
30
|
sql <<
|
31
31
|
"INNER JOIN features
|
32
|
-
ON features.spatial_model_type = '#{options[:target].class}' AND features.spatial_model_id = #{options[:target].id} AND ST_Intersects(features.geom, venn_polygons.geom) "
|
32
|
+
ON features.spatial_model_type = '#{Utils.base_class(options[:target].class)}' AND features.spatial_model_id = #{options[:target].id} AND ST_Intersects(features.geom, venn_polygons.geom) "
|
33
33
|
end
|
34
34
|
|
35
35
|
# Join with the original polygons so we can determine which original polygons each venn polygon came from
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spatial_features
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.7.
|
4
|
+
version: 2.7.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Wallace
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2019-
|
12
|
+
date: 2019-07-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|