From c581b063c42c46018eaa6d8079d9c5569c1559ca Mon Sep 17 00:00:00 2001 From: Matchu Date: Wed, 26 Jul 2023 13:18:19 -0700 Subject: [PATCH] Oops, fix not_occupies logic error Right, previously we were querying "has *at least one asset* that is not in zone X" instead of "has NO assets that are in zone X". I don't know a fast way to query for that, this will have to do for now! --- app/models/item.rb | 12 +++++++----- app/models/swf_asset.rb | 1 + 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/models/item.rb b/app/models/item.rb index 6a5febcf..095340b3 100644 --- a/app/models/item.rb +++ b/app/models/item.rb @@ -82,14 +82,16 @@ class Item < ActiveRecord::Base joins(:swf_assets).where(sa[:zone_id].in(zone_ids)).distinct } scope :not_occupies, ->(zone_label, locale = I18n.locale) { - # TODO: The perf on this is miserable on its own, the query plan chooses - # a bad index for the join on parents_swf_assets here (but not in the - # `occupies` scope?) and I don't know why! But it makes a better plan when - # combined with `name_includes` so this is probably fine in practice? + # TODO: This is pretty slow! But I imagine it's uncommon so that's probably + # fine in practice? Querying for "has NO records matching X" is hard! zone_ids = Zone.matching_label(zone_label, locale).map(&:id) i = Item.arel_table sa = SwfAsset.arel_table - joins(:swf_assets).where(sa[:zone_id].not_in(zone_ids)).distinct + psa = ParentSwfAssetRelationship.arel_table + subquery = SwfAsset.select('COUNT(*)').joins(:parent_swf_asset_relationships). + where(psa[:parent_type].eq('Item')).where(psa[:parent_id].eq(i[:id])). + where(sa[:zone_id].in(zone_ids)) + where("(#{subquery.to_sql}) = 0") } scope :restricts, ->(zone_label, locale = I18n.locale) { zone_ids = Zone.matching_label(zone_label, locale).map(&:id) diff --git a/app/models/swf_asset.rb b/app/models/swf_asset.rb index e8b4ca78..1a9be536 100644 --- a/app/models/swf_asset.rb +++ b/app/models/swf_asset.rb @@ -29,6 +29,7 @@ class SwfAsset < ActiveRecord::Base converts_swfs :size => IMAGE_SIZES[:large], :output_sizes => IMAGE_SIZES.values belongs_to :zone + has_many :parent_swf_asset_relationships scope :includes_depth, -> { includes(:zone) }