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 +4 -4
- data/README.md +12 -0
- data/app/models/abstract_feature.rb +4 -0
- data/config/initializers/mime_types.rb +0 -4
- data/lib/spatial_features/has_spatial_features/feature_import.rb +4 -4
- data/lib/spatial_features/has_spatial_features.rb +10 -1
- data/lib/spatial_features/importers/base.rb +12 -2
- data/lib/spatial_features/importers/file.rb +19 -17
- data/lib/spatial_features/importers/shapefile.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: 4b15396511a7b6b6d17f4a2181793d9b2a35a3a88ba10b49106c9e43cada84b5
|
4
|
+
data.tar.gz: 92c9d1a6b207e1999f63b1e5ab20aec4625b17663e411bcfc7836146c8af4666
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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:
|
@@ -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!(
|
16
|
+
def update_features!(**options)
|
17
17
|
find_each do |record|
|
18
|
-
record.update_features!(
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
26
|
+
@current_file = current_file || Download.open_each(data, unzip: FILE_PATTERNS, downcase: true, tmpdir: options[:tmpdir]).first
|
34
27
|
rescue Unzip::PathNotFound
|
35
|
-
|
28
|
+
raise ImportError, INVALID_ARCHIVE
|
36
29
|
end
|
37
30
|
|
38
|
-
|
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
|
46
|
+
import_error
|
49
47
|
end
|
50
48
|
end
|
51
49
|
|
52
50
|
private
|
53
51
|
|
54
|
-
def import_error!
|
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
|
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.
|
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-
|
12
|
+
date: 2023-10-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|