spatial_features 3.3.0 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
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