Skip to content

Avoid ActiveStorage n+1s#6477

Closed
BenAkroyd wants to merge 5 commits into
solidusio:mainfrom
BenAkroyd:image-includes
Closed

Avoid ActiveStorage n+1s#6477
BenAkroyd wants to merge 5 commits into
solidusio:mainfrom
BenAkroyd:image-includes

Conversation

@BenAkroyd

@BenAkroyd BenAkroyd commented May 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Spree::Asset (and therefore Image) can be setup for ActiveStorage or paperclip. When its ActiveStorage, there are extra classes involved- attachment, blob, and in some cases, variant. None of those are preloaded currently in most places.

As things would break if preload were attempted and kt-paperclip was being used, a helper method has been added that checks config, and defines the appropriate includes. This helper is referenced in a variety of controllers, addressing some n+1s.

Checklist

Check out our PR guidelines for more details.

The following are mandatory for all PRs:

The following are not always needed:

  • 📖 I have updated the README to account for my changes.
  • 📑 I have documented new code with YARD.
  • 🛣️ I have opened a PR to update the guides.
  • ✅ I have added automated tests to cover my changes.
  • 📸 I have attached screenshots to demo visual changes.

BenAkroyd added 2 commits May 1, 2026 09:41
Returns the right preload args for the configured image attachment
backend (deep AS chain in ActiveStorage mode, [] in Paperclip mode),
letting callers preload uniformly without branching on configuration.
Thread Spree::Asset.attachment_preloads through the include_images
preload so search results don't N+1 on AS attachment + blob lookups.
Adds a regression spec.
@BenAkroyd BenAkroyd requested a review from a team as a code owner May 1, 2026 14:23
@github-actions github-actions Bot added changelog:solidus_api Changes to the solidus_api gem changelog:solidus_backend Changes to the solidus_backend gem changelog:solidus_core Changes to the solidus_core gem changelog:solidus_admin labels May 1, 2026
@codecov

codecov Bot commented May 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.68%. Comparing base (61e08a6) to head (038fd75).
⚠️ Report is 24 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #6477   +/-   ##
=======================================
  Coverage   89.68%   89.68%           
=======================================
  Files         991      991           
  Lines       20832    20835    +3     
=======================================
+ Hits        18683    18686    +3     
  Misses       2149     2149           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

BenAkroyd added 3 commits May 1, 2026 10:47
Thread Spree::Asset.attachment_preloads through product_includes and
StockItemsController#variant_scope so styled thumbnail URLs don't N+1
under ActiveStorage.
…trollers

Thread Spree::Asset.attachment_preloads through the products index
and the orders variant picker so styled thumbnail URLs don't N+1
under ActiveStorage. Replaces the bespoke ActiveStorage conditional
in OrdersController#variants_for with the helper.
Thread Spree::Asset.attachment_preloads through find_order so variant
image URLs in the order JSON response don't N+1 under ActiveStorage.
jarednorman
jarednorman previously approved these changes May 1, 2026

@tvdeyen tvdeyen left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice, Ben. Thanks. I think it would be more future proof if we would add the preload config into the appropriate adapter. Also ActiveStorage has a build in preload method that is named after the has_one_attached association

def self.attachment_preloads
return [] unless reflect_on_association(:attachment_attachment)

[{attachment_attachment: {blob: {variant_records: {image_attachment: :blob}}}}]

@tvdeyen tvdeyen May 1, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can make use of the ActiveStorage preloading

with_attached_attachment

Also, maybe we should add this into the adapter instead of making the duck typing here.

@jarednorman jarednorman dismissed their stale review May 4, 2026 21:23

I agree with @tvdeyen.

@BenAkroyd

Copy link
Copy Markdown
Contributor Author

thanks yall. @tvdeyen I've done something similar on CS's repo. I'll update today/tomorrow here

@tvdeyen

tvdeyen commented May 27, 2026

Copy link
Copy Markdown
Member

@BenAkroyd do you want to continue working on this?

@BenAkroyd BenAkroyd closed this Jul 5, 2026
@kennyadsl kennyadsl moved this from Done to Todo in Solidus Admin Jul 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog:solidus_admin changelog:solidus_api Changes to the solidus_api gem changelog:solidus_backend Changes to the solidus_backend gem changelog:solidus_core Changes to the solidus_core gem

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

4 participants