spatial_features 3.3.0 → 3.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7ba1ab9dfa18160f48292f26a63f75031187e44cc04aff73dba792832d482063
4
- data.tar.gz: b25d8a6f4bd0412c3d2d9dd34a57c620a0593979304ddb9061c7f3b3e2d7f834
3
+ metadata.gz: 60a558353e17d6facde9b9dccccb43022f3c46af98401bf6ad4ceccee6a62b65
4
+ data.tar.gz: f2bfcad2b407e9b9329d79650fa3098260524b083b7031caeaa323012fb2fa60
5
5
  SHA512:
6
- metadata.gz: 1be4b279b3341582262bdb8d802c0786b1eb3607cef070f2a03813b2bc987d21fb0aa92323d7b49dbec01aa8b2e128f0b9982ce356dc4836875ccd5ad89f7092
7
- data.tar.gz: 8e70dfe6f6bad6545c29fc5dbf1406b308b9cb44ff48ebfc849469912af6cf30640c829c2baf363a6790e9207f78d3c039276c002a50ce6319ccf0d9450f9df7
6
+ metadata.gz: 065fa148ffcdd4e221f9aa117117302aa51d805e3b5d0b984d76bae81cd163681a428dec37adf9c51e993065ac93c88c75487545ac353b309ff321b3934a3b62
7
+ data.tar.gz: 0ffb13eae72eacdc0a96ec06da6e1e4ee1ffd304f36f80f72fdadebb54269ed8e208b66279c3325217729b36d14727fef03246a989ab5172625fdd3f5694e7fb
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:
@@ -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)
@@ -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.0"
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.0
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-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails