spatial_features 3.3.0 → 3.4.1

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: 7ba1ab9dfa18160f48292f26a63f75031187e44cc04aff73dba792832d482063
4
- data.tar.gz: b25d8a6f4bd0412c3d2d9dd34a57c620a0593979304ddb9061c7f3b3e2d7f834
3
+ metadata.gz: 4b15396511a7b6b6d17f4a2181793d9b2a35a3a88ba10b49106c9e43cada84b5
4
+ data.tar.gz: 92c9d1a6b207e1999f63b1e5ab20aec4625b17663e411bcfc7836146c8af4666
5
5
  SHA512:
6
- metadata.gz: 1be4b279b3341582262bdb8d802c0786b1eb3607cef070f2a03813b2bc987d21fb0aa92323d7b49dbec01aa8b2e128f0b9982ce356dc4836875ccd5ad89f7092
7
- data.tar.gz: 8e70dfe6f6bad6545c29fc5dbf1406b308b9cb44ff48ebfc849469912af6cf30640c829c2baf363a6790e9207f78d3c039276c002a50ce6319ccf0d9450f9df7
6
+ metadata.gz: c15ac3afdd9d23f6e12204a775ad2c8c2777a4c65c494f25560c16db189407a513cd694a71b6d289c81fb4b3872a9621d31da31aaa7bec2830bb233a901ad2d4
7
+ data.tar.gz: c318e7c0897727c41d950451ae7ee65fded8332ded5ec73233660dd8c3285eea571c3160e46eae2b8447131ae8fe0b0559182724719fae3548082ac082e3a3f5
data/README.md CHANGED
@@ -31,6 +31,7 @@ Adds spatial methods to a model.
31
31
  feature_type character varying(255),
32
32
  geog geography,
33
33
  geom geometry(Geometry,4326),
34
+ geom_lowres geometry(Geometry,4326),
34
35
  tilegeom geometry(Geometry,3857),
35
36
  metadata hstore,
36
37
  area double precision,
@@ -49,6 +50,7 @@ Adds spatial methods to a model.
49
50
  CREATE INDEX index_features_on_feature_type ON features USING btree (feature_type);
50
51
  CREATE INDEX index_features_on_spatial_model_id_and_spatial_model_type ON features USING btree (spatial_model_id, spatial_model_type);
51
52
  CREATE INDEX index_features_on_geom ON features USING gist (geom);
53
+ CREATE INDEX index_features_on_geom_lowres ON features USING gist (geom_lowres);
52
54
  CREATE INDEX index_features_on_tilegeom ON features USING gist (tilegeom);
53
55
 
54
56
  CREATE TABLE spatial_caches (
@@ -188,6 +190,16 @@ queries can be optimized. Migrate existing SpatialProximity rows to this new sch
188
190
  SpatialProximity.normalize
189
191
  ```
190
192
 
193
+ ## Upgrading From 3.2/3.3 to 3.4
194
+ Features now record the source they were imported from in the new `source_identifier` column. This column is indexed and
195
+ can be used filter features by source.
196
+
197
+ ```ruby
198
+ add_column :features, :source_identifier, :string
199
+ add_index :features, :source_identifier
200
+ MyModel.update_features!(:force => true) # Force an `update_features!` will populate the source_identifier column.
201
+ ```
202
+
191
203
  ## Testing
192
204
 
193
205
  Create a postgres database:
@@ -37,6 +37,10 @@ class AbstractFeature < ActiveRecord::Base
37
37
  end
38
38
  end
39
39
 
40
+ def self.metadata_keys
41
+ unscope(:select, :order, :includes).distinct.pluck('skeys(metadata)')
42
+ end
43
+
40
44
  def self.polygons
41
45
  where(:feature_type => 'polygon')
42
46
  end
@@ -3,7 +3,3 @@ Mime::Type.register "application/vnd.bounds+json", :bounds
3
3
  Mime::Type.register "application/vnd.mapbox-vector-tile", :mvt
4
4
  Mime::Type.register "application/vnd.google-earth.kml+xml", :kml
5
5
  Mime::Type.register "application/vnd.google-earth.kmz", :kmz
6
- Mime::Type.register "application/zip", :zip
7
- Mime::Type.register "application/zip", :piz
8
- Mime::Type.register "application/zip", :zap
9
- Mime::Type.register "application/zip", :shpz
@@ -13,14 +13,14 @@ module SpatialFeatures
13
13
  end
14
14
 
15
15
  module ClassMethods
16
- def update_features!(skip_invalid: false, allow_blank: false, **options)
16
+ def update_features!(**options)
17
17
  find_each do |record|
18
- record.update_features!(skip_invalid: skip_invalid, allow_blank: allow_blank, **options)
18
+ record.update_features!(**options)
19
19
  end
20
20
  end
21
21
  end
22
22
 
23
- def update_features!(skip_invalid: false, allow_blank: false, **options)
23
+ def update_features!(skip_invalid: false, allow_blank: false, force: false, **options)
24
24
  options = options.reverse_merge(spatial_features_options)
25
25
  tmpdir = options.fetch(:tmpdir) { Dir.mktmpdir("ruby_spatial_features") }
26
26
 
@@ -28,7 +28,7 @@ module SpatialFeatures
28
28
  imports = spatial_feature_imports(options[:import], options[:make_valid], options[:tmpdir])
29
29
  cache_key = Digest::MD5.hexdigest(imports.collect(&:cache_key).join)
30
30
 
31
- return if features_cache_key_matches?(cache_key)
31
+ return if !force && features_cache_key_matches?(cache_key)
32
32
 
33
33
  run_callbacks :update_features do
34
34
  features = import_features(imports, skip_invalid)
@@ -186,7 +186,16 @@ module SpatialFeatures
186
186
  end
187
187
 
188
188
  def features_cache_key
189
- "#{self.class.name}/#{id}-#{has_spatial_features_hash? ? features_hash : (aggregate_feature || features).cache_key}"
189
+ fck =
190
+ if has_spatial_features_hash?
191
+ features_hash
192
+ elsif association(:aggregate_feature).loaded?
193
+ aggregate_feature.cache_key
194
+ else
195
+ aggregate_features.cache_key
196
+ end
197
+
198
+ "#{self.class.name}/#{id}-#{fck}"
190
199
  end
191
200
 
192
201
  def polygons?
@@ -4,12 +4,14 @@ module SpatialFeatures
4
4
  module Importers
5
5
  class Base
6
6
  attr_reader :errors
7
+ attr_accessor :source_identifier # An identifier for the source of the features. Used to differentiate groups of features on the spatial model.
7
8
 
8
- def initialize(data, make_valid: false, tmpdir: nil)
9
+ def initialize(data, make_valid: false, tmpdir: nil, source_identifier: nil)
9
10
  @make_valid = make_valid
10
11
  @data = data
11
12
  @errors = []
12
13
  @tmpdir = tmpdir
14
+ @source_identifier = source_identifier
13
15
  end
14
16
 
15
17
  def features
@@ -48,7 +50,15 @@ module SpatialFeatures
48
50
 
49
51
  def build_feature(record)
50
52
  importable_image_paths = record.importable_image_paths if record.respond_to?(:importable_image_paths)
51
- Feature.new(:name => record.name, :metadata => record.metadata, :feature_type => record.feature_type, :geog => record.geog, :importable_image_paths => importable_image_paths, :make_valid => @make_valid)
53
+ Feature.new do |feature|
54
+ feature.name = record.name
55
+ feature.metadata = record.metadata
56
+ feature.feature_type = record.feature_type
57
+ feature.geog = record.geog
58
+ feature.importable_image_paths = importable_image_paths
59
+ feature.make_valid = @make_valid
60
+ feature.source_identifier = source_identifier
61
+ end
52
62
  end
53
63
  end
54
64
  end
@@ -3,23 +3,16 @@ require 'open-uri'
3
3
  module SpatialFeatures
4
4
  module Importers
5
5
  class File < SimpleDelegator
6
- SUPPORTED_SPATIAL_FORMATS = %w(application/zip application/x-shp+zip application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz application/vnd.geo+json).freeze
7
- SUPPORTED_SPATIAL_FILE_EXTENSIONS = %w(.zip .zap .piz .shpz .kml .kmz .json .geojson).freeze
6
+ INVALID_ARCHIVE = "Archive did not contain a .kml, .shp, .json, or .geojson file.".freeze
8
7
  SUPPORTED_FORMATS = "Supported formats are KMZ, KML, zipped ArcGIS shapefiles, ESRI JSON, and GeoJSON.".freeze
9
8
 
10
- def self.invalid_archive!(filename)
11
- filename = ::File.basename(filename.to_s)
12
- raise ImportError, "#{filename} did not contain a spatial file. #{SUPPORTED_FORMATS}"
13
- end
14
- delegate :invalid_archive!, :to => :class
15
-
16
9
  FILE_PATTERNS = [/\.kml$/, /\.shp$/, /\.json$/, /\.geojson$/]
17
10
  def self.create_all(data, **options)
18
11
  Download.open_each(data, unzip: FILE_PATTERNS, downcase: true, tmpdir: options[:tmpdir]).map do |file|
19
12
  new(data, **options, current_file: file)
20
13
  end
21
14
  rescue Unzip::PathNotFound
22
- invalid_archive!(data)
15
+ raise ImportError, INVALID_ARCHIVE + " " + SUPPORTED_FORMATS
23
16
  end
24
17
 
25
18
  # The File importer may be initialized multiple times by `::create_all` if it
@@ -30,30 +23,39 @@ module SpatialFeatures
30
23
  # If no `current_file` is passed then we just take the first valid file that we find.
31
24
  def initialize(data, current_file: nil, **options)
32
25
  begin
33
- current_file ||= Download.open_each(data, unzip: FILE_PATTERNS, downcase: true, tmpdir: options[:tmpdir]).first
26
+ @current_file = current_file || Download.open_each(data, unzip: FILE_PATTERNS, downcase: true, tmpdir: options[:tmpdir]).first
34
27
  rescue Unzip::PathNotFound
35
- invalid_archive!(data)
28
+ raise ImportError, INVALID_ARCHIVE
36
29
  end
37
30
 
38
- filename = current_file.path.downcase
31
+ case ::File.extname(data).downcase
32
+ when '.kmz' # KMZ always has a single kml in it, so no need to show mention it
33
+ options[:source_identifier] = ::File.basename(data)
34
+ else
35
+ options[:source_identifier] = [::File.basename(data), ::File.basename(@current_file.path)].uniq.join('/')
36
+ end
39
37
 
40
38
  case ::File.extname(filename)
41
39
  when '.kml'
42
- __setobj__(KMLFile.new(current_file, **options))
40
+ __setobj__(KMLFile.new(@current_file, **options))
43
41
  when '.shp'
44
- __setobj__(Shapefile.new(current_file, **options))
42
+ __setobj__(Shapefile.new(@current_file, **options))
45
43
  when '.json', '.geojson'
46
- __setobj__(ESRIGeoJSON.new(current_file.path, **options))
44
+ __setobj__(ESRIGeoJSON.new(@current_file.path, **options))
47
45
  else
48
- import_error!(filename)
46
+ import_error
49
47
  end
50
48
  end
51
49
 
52
50
  private
53
51
 
54
- def import_error!(filename)
52
+ def import_error!
55
53
  raise ImportError, "Could not import #{filename}. " + SUPPORTED_FORMATS
56
54
  end
55
+
56
+ def filename
57
+ @filename ||= @current_file.path.downcase
58
+ end
57
59
  end
58
60
  end
59
61
  end
@@ -20,7 +20,7 @@ module SpatialFeatures
20
20
  new(file, **options)
21
21
  end
22
22
  rescue Unzip::PathNotFound
23
- invalid_archive!(data)
23
+ raise ImportError, INVALID_ARCHIVE
24
24
  end
25
25
 
26
26
  private
@@ -1,3 +1,3 @@
1
1
  module SpatialFeatures
2
- VERSION = "3.3.0"
2
+ VERSION = "3.4.1"
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: 3.3.0
4
+ version: 3.4.1
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: 2023-10-13 00:00:00.000000000 Z
12
+ date: 2023-10-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails