Skip to content

refactor: move SponsorsSearch from models to queries layer#2697

Merged
mroderick merged 4 commits into
masterfrom
feature/move-sponsors-search
Jul 10, 2026
Merged

refactor: move SponsorsSearch from models to queries layer#2697
mroderick merged 4 commits into
masterfrom
feature/move-sponsors-search

Conversation

@mroderick

Copy link
Copy Markdown
Collaborator

What

Move SponsorsSearch from app/models/ (domain layer) to app/queries/ (application layer), where query objects belong in layered architecture.

Why

As identified in the layered-architecture analysis, SponsorsSearch is a query object — it wraps a search/filter operation using ActiveModel::Model and #call. It has no domain identity, no persistence, and no business invariants. The domain layer should not host query objects.

Changes

  • app/models/sponsors_search.rbapp/queries/sponsors_search.rb — no code changes, just a rename (Rails 8 autoloads all app/ subdirectories, so no require path updates needed)
  • spec/models/sponsors_search_spec.rbspec/queries/sponsors_search_spec.rb — test follows the file
  • Strengthened test coverage — replaced message-expectation tests with real-data assertions, added chapter filter, case-insensitive name, combined name+chapter filter, and empty-results edge case

Verification

  • All unit, controller, and feature tests pass (20 examples)
  • All sponsor-related tests pass (50 examples)
  • SponsorsSearch resolves correctly via autoloading from new location

@mroderick mroderick force-pushed the feature/move-sponsors-search branch from 992b276 to 7dee8dd Compare July 10, 2026 06:25
SponsorsSearch is a query object (ActiveModel with #call), not a domain
model. Place it in the correct architectural layer.

Move both the source file and its spec to mirror the new location.
Rails 8 autoloads all app/ subdirectories, so no require path updates
are needed.
@mroderick mroderick force-pushed the feature/move-sponsors-search branch from 7dee8dd to 9ce1b5a Compare July 10, 2026 06:28
…h spec

Replace the shared let(:search_params) that generated random values via
Faker with inline literal hashes. This makes the test deterministic and
removes a source of test flake.

Also adopt described_class.new(...) call style instead of the local
variable invocation pattern. No test semantics changed — same assertions,
same message-expectation approach.
The previous tests used expect(Sponsor).to receive(:by_name) which verifies
that a method was *called*, not that the right records were *returned*.
A caller passing the wrong args to by_name, or a by_name scope with a bug,
would still pass.

Drop message expectations entirely. Seed the database with specific
sponsors, invoke #call, and assert on the actual returned records.
This tests the contract (what comes back) rather than implementation
(what gets called).
The core filter tests (name, no-filter, empty) were covered in the
previous commit. These three additions fill the gaps:

- nil params in initialization: ensures the object handles blank form
  submissions without errors
- case-insensitive name filter: the SQL uses LOWER() — this tests that
  lowercase and uppercase input both match
- chapter filter: exercises the by_chapter join path with a workshop
  that has no auto-created sponsor (workshop_no_sponsor) to avoid false
  passes from the workshop fabricator cascade
- combined name + chapter filter: the query object chains scopes — this
  verifies that the AND combination works correctly
@mroderick mroderick force-pushed the feature/move-sponsors-search branch from 9ce1b5a to 19bff26 Compare July 10, 2026 06:33
@mroderick mroderick marked this pull request as ready for review July 10, 2026 06:39
@mroderick mroderick requested a review from olleolleolle July 10, 2026 06:39
@mroderick mroderick merged commit d63f1c9 into master Jul 10, 2026
9 checks passed
@mroderick mroderick deleted the feature/move-sponsors-search branch July 10, 2026 09:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants