spatial_features 2.7.4 → 2.7.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eca12b6b107350864c5a353d6a7fe587676c1661e1d54bd8cbccb57733e49926
4
- data.tar.gz: 7272b1807b1335b7ea22fc1cae398780f13acd095f5d5c8a0436dfa2ed6c6b17
3
+ metadata.gz: 13dafdeb45681a5a529ee77c0c54d8306d35858e7c715c8f6845bf7bac4ff51e
4
+ data.tar.gz: 9789d728e2a2fcd7cb3903637bb3fa61c01e323c99b38bf677fbfcdc06cc2bb4
5
5
  SHA512:
6
- metadata.gz: eec0cf39ea56064d74eb3b7efc90be1903377dd9035f5e0be8a8de8b4cb6088ab607087b025f7bee1178f6a974386dd74b59f1f4f5045b5af3959d25eb8669d5
7
- data.tar.gz: bce6ce396af2a8ba10f11eded504d26e00be348ca15211ba04adca5310698b11e66a177fe0d081a0511d94a14eed89b8d8f280db0de54cc0019895b6a7d67eab
6
+ metadata.gz: f0f614d22d3df5c3fbdeda0875d95b31b7a2b843ee012aafa240996a3ffe6ea00c1854b470945dcf3151ed3427daac680856c176b72419fad3f18dfa00418307
7
+ data.tar.gz: e0b1535e925c8376fcfb20a13e70d1f1ae80dcfc7b709f755140aae94b70f8118dd95c7cd040d7f8441493d79d339e106838e3f757cac7eec2249023b0f7657c
@@ -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.to_s)
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.permutation(2).each do |klass, clazz|
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.combination(2).each do |klass, clazz|
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.to_s).delete_all
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.class.to_s < klass.to_s ? [record, klass_record] : [klass_record, 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.class
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.class
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 = '#{klass}'").where("#{SpatialCache.table_name}.spatial_model_id IS NULL") }
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.class_of(other)
116
+ other_class = Utils.base_class_of(other)
117
+ self_class = Utils.base_class_of(self)
117
118
 
118
- other_column = other_class.name < self.name ? :model_a : :model_b
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 = '#{self}' 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
+ 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.class_of(other))
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, SpatialFeatures::Utils.class_of(other)).first
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, class_of(scope)]
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
@@ -1,3 +1,3 @@
1
1
  module SpatialFeatures
2
- VERSION = "2.7.4"
2
+ VERSION = "2.7.5"
3
3
  end
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
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-06-24 00:00:00.000000000 Z
12
+ date: 2019-07-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails