app/models/feature.rb in spatial_features-2.1.6 vs app/models/feature.rb in spatial_features-2.1.7

- old
+ new

@@ -5,14 +5,13 @@ FEATURE_TYPES = %w(polygon point line) before_validation :sanitize_feature_type validates_presence_of :geog - validate :geometry_is_valid + validate :validate_geometry validates_inclusion_of :feature_type, :in => FEATURE_TYPES before_save :sanitize - before_save :make_valid, if: :make_valid? after_save :cache_derivatives def self.with_metadata(k, v) if k.present? && v.present? where('metadata->? = ?', k, v) @@ -109,11 +108,11 @@ end private def make_valid - self.geog = ActiveRecord::Base.connection.select_value("SELECT ST_CollectionExtract(ST_MakeValid('#{sanitize}'),3)") + self.geog = ActiveRecord::Base.connection.select_value("SELECT ST_Buffer('#{sanitize}', 0)") end # Use ST_Force2D to discard z-coordinates that cause failures later in the process def sanitize self.geog = ActiveRecord::Base.connection.select_value("SELECT ST_Force2D('#{geog}')") @@ -125,14 +124,25 @@ def self.join_other_features(other) joins('INNER JOIN features AS other_features ON true').where(:other_features => {:id => other}) end - def geometry_is_valid - if geog? - instance = self.class.unscoped.invalid.from("(SELECT '#{sanitize_input_for_sql(self.geog)}'::geometry AS geog) #{self.class.table_name}").to_a.first - errors.add :geog, instance.invalid_geometry_message if instance + def validate_geometry + return unless geog? + + error = geometry_validation_message + if error && make_valid? + make_valid + self.make_valid = false + validate_geometry + elsif error + errors.add :geog, error end + end + + def geometry_validation_message + error = self.class.connection.select_one(self.class.unscoped.invalid.from("(SELECT '#{sanitize_input_for_sql(self.geog)}'::geometry AS geog) #{self.class.table_name}")) + return error.fetch('invalid_geometry_message') if error end def sanitize_feature_type self.feature_type = FEATURE_TYPES.find {|type| self.feature_type.to_s.strip.downcase.include?(type) } end