spatial_features 2.13.0 → 2.14.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: 88c320989e3fc2fa794540eceda94ca135c83992bdb8d95beae96cb23547253b
4
- data.tar.gz: '08acd270a048acc72c637876d36f7d4d39b4270f47f02f8cd51d80a834348c07'
3
+ metadata.gz: 0aa9e8be0d78cabc65695247e3000bcc2d69ce75aeffe1333b0dd5ce423eb562
4
+ data.tar.gz: 587dc7a4be41c38acd66de43864ed3b8b51f22186996fcdd2c906c01ee97102e
5
5
  SHA512:
6
- metadata.gz: 4597a17999f3503d80ae00d40072c9335a9a0141fc277f952328a868b3d339cdcc236929b2bdc914f42eafe1229cde317202eb7064cab956d467257747d44152
7
- data.tar.gz: e859fc1b6fb70a1f2ad453d5e8017799f2d7b6c9212fd04f8abaf3c4c7958e7383ebd71b23fd51accb9f5ed168955afcfa49ae20b5d0486b44f0580a907a2586
6
+ metadata.gz: 75293b351a8bfa078b1eac5c02a7d5dcce3e6eaa15a1779e660d0ca1c8a1cf93be2ad30190946e8934f51301c8535cfda4a75d0af2d86d051ffdd79646f170eb
7
+ data.tar.gz: a725a65315d15a5885bd475dc6575969823cac93bc865f4dca3f583e602342a7b40a1afef2478264e74f29a79d44be8fb3528648144b10fe9d4c0a3d8f5858ab
@@ -3,9 +3,6 @@ require 'delayed_job_active_record'
3
3
  require 'rgeo/shapefile'
4
4
  require 'nokogiri'
5
5
  require 'zip'
6
- require 'googleauth'
7
- require 'google/apis/fusiontables_v2'
8
- require 'google/apis/drive_v3'
9
6
 
10
7
  # LIB
11
8
  require 'spatial_features/caching'
@@ -20,11 +17,6 @@ require 'spatial_features/has_spatial_features'
20
17
  require 'spatial_features/has_spatial_features/queued_spatial_processing'
21
18
  require 'spatial_features/has_spatial_features/feature_import'
22
19
 
23
- require 'spatial_features/has_fusion_table_features'
24
- require 'spatial_features/has_fusion_table_features/api'
25
- require 'spatial_features/has_fusion_table_features/configuration'
26
- require 'spatial_features/has_fusion_table_features/service'
27
-
28
20
  require 'spatial_features/importers/base'
29
21
  require 'spatial_features/importers/file'
30
22
  require 'spatial_features/importers/kml'
@@ -38,7 +30,6 @@ require 'spatial_features/engine'
38
30
 
39
31
  # Load the act method
40
32
  ActiveRecord::Base.send :extend, SpatialFeatures::ActMethod
41
- ActiveRecord::Base.send :extend, SpatialFeatures::FusionTables::ActMethod
42
33
 
43
34
  # Suppress date warnings when unzipping KMZ saved by Google Earth, see https://github.com/rubyzip/rubyzip/issues/112
44
35
  Zip.warn_invalid_date = false
@@ -14,10 +14,14 @@ module SpatialFeatures
14
14
  else
15
15
  metadata = {}
16
16
  end
17
-
17
+
18
18
  next if blank_feature?(feature)
19
19
 
20
- yield OpenStruct.new(:feature_type => sql_type, :geog => geom_from_kml(feature), :name => name, :metadata => metadata)
20
+ geog = geom_from_kml(feature)
21
+
22
+ next if geog.blank?
23
+
24
+ yield OpenStruct.new(:feature_type => sql_type, :geog => geog, :name => name, :metadata => metadata)
21
25
  end
22
26
  end
23
27
  end
@@ -27,7 +31,16 @@ module SpatialFeatures
27
31
  end
28
32
 
29
33
  def geom_from_kml(kml)
30
- ActiveRecord::Base.connection.select_value("SELECT ST_GeomFromKML(#{ActiveRecord::Base.connection.quote(kml.to_s)})")
34
+ geom = nil
35
+
36
+ # Do query in a new thread so we use a new connection (if the query fails it will poison the transaction of the current connection)
37
+ Thread.new do
38
+ geom = ActiveRecord::Base.connection.select_value("SELECT ST_GeomFromKML(#{ActiveRecord::Base.connection.quote(kml.to_s)})")
39
+ rescue ActiveRecord::StatementInvalid => e # Discard Invalid KML features
40
+ geom = nil
41
+ end.join
42
+
43
+ return geom
31
44
  end
32
45
 
33
46
  def extract_metadata(placemark)
@@ -1,3 +1,3 @@
1
1
  module SpatialFeatures
2
- VERSION = "2.13.0"
2
+ VERSION = "2.14.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: 2.13.0
4
+ version: 2.14.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: 2020-09-08 00:00:00.000000000 Z
12
+ date: 2021-02-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -87,34 +87,6 @@ dependencies:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
89
  version: '1.6'
90
- - !ruby/object:Gem::Dependency
91
- name: googleauth
92
- requirement: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: 0.5.1
97
- type: :runtime
98
- prerelease: false
99
- version_requirements: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - "~>"
102
- - !ruby/object:Gem::Version
103
- version: 0.5.1
104
- - !ruby/object:Gem::Dependency
105
- name: google-api-client
106
- requirement: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: '0.9'
111
- type: :runtime
112
- prerelease: false
113
- version_requirements: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - "~>"
116
- - !ruby/object:Gem::Version
117
- version: '0.9'
118
90
  - !ruby/object:Gem::Dependency
119
91
  name: chroma
120
92
  requirement: !ruby/object:Gem::Requirement
@@ -180,10 +152,6 @@ files:
180
152
  - lib/spatial_features/controller_helpers/spatial_extensions.rb
181
153
  - lib/spatial_features/download.rb
182
154
  - lib/spatial_features/engine.rb
183
- - lib/spatial_features/has_fusion_table_features.rb
184
- - lib/spatial_features/has_fusion_table_features/api.rb
185
- - lib/spatial_features/has_fusion_table_features/configuration.rb
186
- - lib/spatial_features/has_fusion_table_features/service.rb
187
155
  - lib/spatial_features/has_spatial_features.rb
188
156
  - lib/spatial_features/has_spatial_features/feature_import.rb
189
157
  - lib/spatial_features/has_spatial_features/queued_spatial_processing.rb
@@ -1,95 +0,0 @@
1
- module SpatialFeatures
2
- module FusionTables
3
- module ActMethod
4
- def has_fusion_table_features(options = {})
5
- class_attribute :fusion_table_features_options
6
- self.fusion_table_features_options = options
7
-
8
- after_update_features :expire_fusion_table
9
-
10
- include InstanceMethods
11
- extend ClassMethods
12
- end
13
- end
14
-
15
- module ClassMethods
16
- def to_fusion_condition
17
- sanitize_sql(["spatial_model_id IN (?)", pluck(:id)])
18
- end
19
-
20
- def update_fusion_tables(group_options = {})
21
- fusion_table_groups(group_options) do |fusion_table_id, records, group_features|
22
- API.set_features(fusion_table_id, group_features, :colour => fusion_table_features_options[:colour])
23
- end
24
- end
25
-
26
- def delete_fusion_tables(group_options = {})
27
- fusion_table_groups(group_options) do |fusion_table_id, records, group_features|
28
- API.delete_table(fusion_table_id)
29
- end
30
- @fusion_table_id_cache = nil
31
- end
32
-
33
- def acts_like_fusion_table_features?
34
- true
35
- end
36
-
37
- def fusion_table_id_cache
38
- @fusion_table_id_cache ||= Hash.new {|hash, table_name| hash[table_name] = API.find_or_create_table(table_name) }
39
- .merge(API.tables.collect {|table| [table.name, table.table_id] }.to_h) # Warm the cache
40
- end
41
-
42
- private
43
-
44
- def fusion_table_groups(only: [], except: [])
45
- groups = all.group_by(&:fusion_table_id)
46
- groups.select! {|fusion_table_id, _| Array.wrap(only).include?(fusion_table_id) } if only.present?
47
- groups.select! {|fusion_table_id, _| !Array.wrap(except).include?(fusion_table_id) } if except.present?
48
- groups.each do |fusion_table_id, records|
49
- yield fusion_table_id, records, features.where(:spatial_model_id => records)
50
- end
51
- end
52
- end
53
-
54
- module InstanceMethods
55
- def acts_like_fusion_table_features?
56
- true
57
- end
58
-
59
- def stale_fusion_table?
60
- @stale_fusion_table
61
- end
62
-
63
- def expire_fusion_table
64
- @stale_fusion_table = true
65
- end
66
-
67
- def update_fusion_table
68
- self.class.update_fusion_tables(only: fusion_table_id)
69
- end
70
-
71
- def delete_fusion_table
72
- self.class.delete_fusion_tables(only: fusion_table_id)
73
- end
74
-
75
- def fusion_table_id
76
- self.class.fusion_table_id_cache[fusion_table_name]
77
- end
78
-
79
- def fusion_table_name
80
- case fusion_table_features_options[:table_name]
81
- when Symbol
82
- send(fusion_table_features_options[:table_name])
83
- when String
84
- fusion_table_features_options[:table_name]
85
- else
86
- self.class.table_name
87
- end
88
- end
89
-
90
- def to_fusion_condition
91
- self.class.where(:id => self).to_fusion_condition
92
- end
93
- end
94
- end
95
- end
@@ -1,111 +0,0 @@
1
- module SpatialFeatures
2
- module FusionTables
3
- module API
4
- extend self
5
-
6
- FEATURE_COLUMNS = {
7
- :name => 'STRING',
8
- :spatial_model_type => 'STRING',
9
- :spatial_model_id => 'NUMBER',
10
- :kml_lowres => 'LOCATION',
11
- :colour => 'STRING',
12
- :metadata => 'STRING'
13
- }
14
- TABLE_STYLE = {
15
- :polygon_options => { :fill_color_styler => { :kind => 'fusiontables#fromColumn', :column_name => 'colour' },
16
- :stroke_color_styler => { :kind => 'fusiontables#fromColumn', :column_name => 'colour' },
17
- :stroke_weight => 1
18
- },
19
- :polyline_options => { :stroke_color_styler => { :kind => 'fusiontables#fromColumn', :column_name => 'colour'} }
20
- }
21
-
22
- TABLE_TEMPLATE = {
23
- :body => "<h3>{name}</h3>{metadata}"
24
- }
25
-
26
- def find_or_create_table(name)
27
- find_table(name) || create_table(name)
28
- end
29
-
30
- def create_table(name)
31
- table_id = service.create_table(name, FEATURE_COLUMNS.collect {|name, type| {:name => name, :type => type} })
32
- service.share_table(table_id)
33
- service.insert_style(table_id, TABLE_STYLE)
34
- service.insert_template(table_id, TABLE_TEMPLATE)
35
- return table_id
36
- end
37
-
38
- def find_table(name)
39
- service.tables.find {|table| table.name == name }.try(:table_id)
40
- end
41
-
42
- def delete_table(table_id)
43
- service.delete_table(table_id)
44
- end
45
-
46
- def tables
47
- service.tables
48
- end
49
-
50
- def set_features(table_id, features, colour: nil)
51
- service.replace_rows(table_id, features_to_csv(features, colour))
52
- end
53
-
54
- def set_style(table_id, style)
55
- service.style_ids(table_id).each do |style_id|
56
- service.delete_style(table_id, style_id)
57
- end
58
- service.insert_style(table_id, style)
59
- end
60
-
61
- def service
62
- @service ||= Service.new(Configuration.service_account_credentials)
63
- end
64
-
65
- private
66
-
67
- def features_to_csv(features, colour)
68
- ActiveRecord::Associations::Preloader.new.preload(features, :spatial_model) if colour.is_a?(Symbol)
69
-
70
- csv = CSV.generate do |csv|
71
- features.each do |feature|
72
- csv << FEATURE_COLUMNS.keys.collect do |attribute|
73
- case attribute
74
- when :colour
75
- render_feature_colour(feature, colour)
76
- when :metadata
77
- render_feature_metadata(feature)
78
- else
79
- feature.send(attribute)
80
- end
81
- end
82
- end
83
- end
84
-
85
- file = Tempfile.new('features')
86
- file.write(csv)
87
- return file
88
- end
89
-
90
- def render_feature_metadata(feature)
91
- feature.metadata.collect do |name, val|
92
- "<b>#{name}:</b> #{val}"
93
- end.join('<br/>')
94
- end
95
-
96
- def render_feature_colour(feature, colour)
97
- case colour
98
- when Symbol
99
- feature.spatial_model.send(colour)
100
- when Proc
101
- colour.call(feature)
102
- else
103
- colour
104
- end.paint.to_ft_hex
105
-
106
- rescue Chroma::Errors::UnrecognizedColor
107
- nil
108
- end
109
- end
110
- end
111
- end
@@ -1,15 +0,0 @@
1
- module SpatialFeatures
2
- module FusionTables
3
- def self.config
4
- if block_given?
5
- yield Configuration
6
- else
7
- Configuration
8
- end
9
- end
10
-
11
- module Configuration
12
- mattr_accessor :service_account_credentials
13
- end
14
- end
15
- end
@@ -1,104 +0,0 @@
1
- module SpatialFeatures
2
- module FusionTables
3
- class Service
4
- APPLICATION_NAME = 'Fusion Tables + Spatial Features'
5
- GOOGLE_AUTH_SCOPES = %w(https://www.googleapis.com/auth/fusiontables https://www.googleapis.com/auth/drive)
6
-
7
- def initialize(service_account_credentials_path)
8
- @authorization = get_authorization(service_account_credentials_path, GOOGLE_AUTH_SCOPES)
9
- end
10
-
11
- def table_ids
12
- tables.collect(&:table_id)
13
- end
14
-
15
- def tables
16
- fusion_tables_service.list_tables(max_results: 10000).items || []
17
- end
18
-
19
- def create_table(name, columns = [], table_options = {})
20
- table_object = {:name => name, :columns => columns, :is_exportable => true}.merge(table_options)
21
- fusion_tables_service.insert_table(table_object, :fields => 'table_id').table_id
22
- end
23
-
24
- def delete_table(table_id)
25
- fusion_tables_service.delete_table(table_id)
26
- end
27
-
28
- def style_ids(table_id)
29
- styles(table_id).collect(&:style_id)
30
- end
31
-
32
- def styles(table_id)
33
- fusion_tables_service.list_styles(table_id).items
34
- end
35
-
36
- def delete_style(table_id, style_id)
37
- fusion_tables_service.delete_style(table_id, style_id, :fields => nil)
38
- end
39
-
40
- def insert_style(table_id, style)
41
- style.reverse_merge! 'name' => 'default_table_style', 'isDefaultForTable' => true
42
- fusion_tables_service.insert_style(table_id, style, :fields => 'styleId')
43
- end
44
-
45
- def delete_template(table_id, template_id)
46
- fusion_tables_service.delete_template(table_id, template_id, :fields => nil)
47
- end
48
-
49
- def insert_template(table_id, template)
50
- template.reverse_merge! 'name' => 'default_table_template'
51
- fusion_tables_service.insert_template(table_id, template, :fields => 'templateId')
52
- end
53
-
54
- def delete_row(table_id, row_id)
55
- fusion_tables_service.sql_query("DELETE FROM #{table_id} WHERE ROWID = #{row_id}")
56
- end
57
-
58
- def row_ids(table_id, conditions = {})
59
- clause = conditions.collect {|column, value| ActiveRecord::Base.send(:sanitize_sql_array, ["? IN (?)", column, value]) }.join(' AND ')
60
- where = "WHERE #{clause}" if clause.present?
61
- return fusion_tables_service.sql_query_get("SELECT rowid FROM #{table_id} #{where}}").rows.flatten
62
- end
63
-
64
- # Process mutliple commands in a single HTTP request
65
- def bulk(&block)
66
- fusion_tables_service.batch do
67
- block.call(self)
68
- end
69
- end
70
-
71
- def replace_rows(table_id, csv)
72
- fusion_tables_service.replace_table_rows(table_id, :upload_source => csv, :options => {:open_timeout_sec => 1.hour})
73
- end
74
-
75
- def upload_rows(table_id, csv)
76
- fusion_tables_service.import_rows(table_id, :upload_source => csv, :options => {:open_timeout_sec => 1.hour})
77
- end
78
-
79
- def share_table(table_id)
80
- permission = {:type => 'anyone', :role => 'reader', :withLink => true}
81
- drive_service.create_permission(table_id, permission, :fields => 'id')
82
- end
83
-
84
- def fusion_tables_service
85
- @fusion_tables_service ||= Google::Apis::FusiontablesV2::FusiontablesService.new.tap do |service|
86
- service.client_options.application_name = APPLICATION_NAME
87
- service.authorization = @authorization
88
- end
89
- end
90
-
91
- def drive_service
92
- @drive_service ||= Google::Apis::DriveV3::DriveService.new.tap do |drive|
93
- drive.client_options.application_name = APPLICATION_NAME
94
- drive.authorization = @authorization
95
- end
96
- end
97
-
98
- def get_authorization(service_account_credentials_path, scopes)
99
- ENV['GOOGLE_APPLICATION_CREDENTIALS'] = service_account_credentials_path
100
- return Google::Auth.get_application_default(scopes)
101
- end
102
- end
103
- end
104
- end