require_dependency SpatialFeatures::Engine.root.join('app/models/abstract_feature')

class AggregateFeature < AbstractFeature
  has_many :features, lambda { |aggregate| where(:spatial_model_type => aggregate.spatial_model_type) }, :foreign_key => :spatial_model_id, :primary_key => :spatial_model_id

  # Aggregate the features for the spatial model into a single feature
  def refresh
    feature_array_sql = <<~SQL
      ARRAY[
        (#{features.select('ST_UNION(ST_CollectionExtract(geog::geometry, 1))').to_sql}),
        (#{features.select('ST_UNION(ST_CollectionExtract(geog::geometry, 2))').to_sql}),
        (#{features.select('ST_UNION(ST_CollectionExtract(geog::geometry, 3))').to_sql})
      ]
    SQL

    # Remove empty features so ST_COLLECT doesn't choke. This seems to be a difference between PostGIS 2.x and 3.x
    compacted_feature_array_sql = <<~SQL
      array_remove(
        array_remove(
          array_remove(#{feature_array_sql},
          ST_GeomFromText('Point EMPTY')),
        ST_GeomFromText('Linestring EMPTY')),
      ST_GeomFromText('Polygon EMPTY'))
    SQL

    self.geog = ActiveRecord::Base.connection.select_value <<~SQL
      SELECT ST_Collect(#{compacted_feature_array_sql})::geography
    SQL
    self.save!
  end
end

require_dependency SpatialFeatures::Engine.root.join('app/models/abstract_feature')

class AggregateFeature < AbstractFeature
  has_many :features, lambda { |aggregate| where(:spatial_model_type => aggregate.spatial_model_type) }, :foreign_key => :spatial_model_id, :primary_key => :spatial_model_id

  # Aggregate the features for the spatial model into a single feature
  def refresh
    feature_array_sql = <<~SQL
      ARRAY[
        (#{features.select('ST_Multi(ST_Union(ST_CollectionExtract(geog::geometry, 1)))').to_sql}),
        (#{features.select('ST_Multi(ST_Union(ST_CollectionExtract(geog::geometry, 2)))').to_sql}),
        (#{features.select('ST_Multi(ST_Union(ST_CollectionExtract(geog::geometry, 3)))').to_sql})
      ]
    SQL

    # Remove empty features so ST_COLLECT doesn't choke. This seems to be a difference between PostGIS 2.x and 3.x
    compacted_feature_array_sql = <<~SQL
      array_remove(
        array_remove(
          array_remove(#{feature_array_sql},
          ST_GeomFromText('MultiPoint EMPTY')),
        ST_GeomFromText('MultiLinestring EMPTY')),
      ST_GeomFromText('MultiPolygon EMPTY'))
    SQL

    self.geog = ActiveRecord::Base.connection.select_value <<~SQL
      SELECT ST_Collect(#{compacted_feature_array_sql})::geography
    SQL
    self.save!
  end
end

Tweak PostGIS 3.x compat fix.
Tweak PostGIS 3.x compat fix.

In d0c2e54c1a07aa935a905a30e5be2dc443eb1a7f, we added a fix for PostGIS 3.x. This fix was still failing if the CollectionExtract returned a Multi* geometry since we weren’t removing empty Multis.

One example of this is when refreshing the aggregate feature for Community 16 in Sto:lo Connect.

We now convert all geometries to Multis before removing empties to ensure the correct behaviour.

This is starting to turn into a bit of a Rube Goldberg machine so we should see if there is a simpler way to do this at some future point.
