Skip to content

Commit 45b3c0d

Browse files
etewiahclaude
andcommitted
Fix N+1 queries on home page property listings
Before: 83 queries, 579ms response time After: 28 queries, 278ms response time Changes: - Convert sale_listing/rental_listing methods to belongs_to associations in Pwb::ListedProperty so they can be eager loaded - Update with_eager_loading scope to include :sale_listing and :rental_listing associations The N+1 was caused by sale_listing and rental_listing being methods that called find_by individually for each property, instead of associations that could be preloaded in a single query. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 2b88ae8 commit 45b3c0d

File tree

2 files changed

+12
-11
lines changed

2 files changed

+12
-11
lines changed

app/models/concerns/listed_property/searchable.rb

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,16 @@ module Searchable
88

99
included do
1010
# Eager load photos with their ActiveStorage attachments for efficient image access
11-
# Also includes :website to prevent N+1 when accessing area_unit, currency, etc.
12-
scope :with_eager_loading, -> { includes(:website, prop_photos: { image_attachment: :blob }) }
11+
# Also includes :website, :sale_listing, :rental_listing to prevent N+1 queries
12+
# when accessing area_unit, currency, title, description, prices, etc.
13+
scope :with_eager_loading, -> {
14+
includes(:website, :sale_listing, :rental_listing, prop_photos: { image_attachment: :blob })
15+
}
1316

1417
# Use this when you need both website and photos (e.g., cross-tenant operations)
15-
scope :with_full_eager_loading, -> { includes(:website, prop_photos: { image_attachment: :blob }) }
18+
scope :with_full_eager_loading, -> {
19+
includes(:website, :sale_listing, :rental_listing, prop_photos: { image_attachment: :blob })
20+
}
1621

1722
# Lighter scope for widgets - only loads photos without attachment blob data
1823
# Use when you only need first photo or just need to check has_image?

app/models/pwb/listed_property.rb

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ class ListedProperty < ApplicationRecord
108108

109109
belongs_to :website, class_name: 'Pwb::Website', optional: true
110110

111+
# Listing associations - these can be eager loaded to avoid N+1 queries
112+
belongs_to :sale_listing, class_name: 'Pwb::SaleListing', optional: true
113+
belongs_to :rental_listing, class_name: 'Pwb::RentalListing', optional: true
114+
111115
has_many :prop_photos,
112116
-> { order(:sort_order) },
113117
class_name: 'Pwb::PropPhoto',
@@ -127,14 +131,6 @@ def realty_asset
127131
Pwb::RealtyAsset.find(id)
128132
end
129133

130-
def sale_listing
131-
Pwb::SaleListing.find_by(id: sale_listing_id) if sale_listing_id.present?
132-
end
133-
134-
def rental_listing
135-
Pwb::RentalListing.find_by(id: rental_listing_id) if rental_listing_id.present?
136-
end
137-
138134
# ============================================
139135
# Read-Only Protection
140136
# ============================================

0 commit comments

Comments
 (0)