Skip to content

Add strict paginated model data hook - #1680

Open
GiuseppeXD wants to merge 2 commits into
masterfrom
feat/strict-pagination-model-hook
Open

Add strict paginated model data hook#1680
GiuseppeXD wants to merge 2 commits into
masterfrom
feat/strict-pagination-model-hook

Conversation

@GiuseppeXD

@GiuseppeXD GiuseppeXD commented Jul 27, 2026

Copy link
Copy Markdown

Description ✍️

Adds two explicit model-class stages for generated pagination data:

def self.graphoid_prepare_paginated_scope(scope, lookahead:)
  # Translate GraphQL selections into lazy scope changes.
end

def self.graphoid_load_paginated_data(scope, lookahead:)
  # Materialize or enrich the prepared collection when needed.
end

Graphoid previously called lookahead and eager_load only through the resolved query object. With Mongoid criteria, application hooks depended on Criteria#method_missing; Mongoid 9.1 adding Criteria#eager_load changed dispatch and bypassed the model loader.

The new stages call the captured model directly while retaining the former query-object methods as fallbacks for models that have not migrated.

Overview 🔍

flowchart LR
  A[Resolved pagination scope] --> B{Prepare model hook?}
  B -->|Yes| C[Prepare scope directly]
  B -->|No| D[Legacy scope.lookahead fallback]
  C --> E{Load model hook?}
  D --> E
  E -->|Yes| F[Load data directly]
  E -->|No| G[Legacy scope.eager_load fallback]
  F --> H[GraphQL serialization]
  G --> H
Loading

Responsibilities

Stage Responsibility Expected database behavior
graphoid_prepare_paginated_scope Convert lookahead selections into scope instructions Remains lazy
graphoid_load_paginated_data Perform custom materialization or batching May execute queries
Legacy lookahead fallback Preserve the previous preparation convention Consumer-defined
Legacy eager_load fallback Preserve native/previous eager loading Query-object-defined
  • Passes the fully resolved filter/order/limit/skip scope into preparation.
  • Passes the exact prepared scope into loading.
  • Passes GraphQL data lookahead as a required keyword to direct hooks.
  • Gives direct model hooks precedence over legacy query-object methods.
  • Preserves the old positional scope.lookahead(scope, lookahead) contract as fallback.
  • Preserves nil-result behavior for legacy lookahead by retaining the incoming scope.
  • Supports criteria or materialized collection return values.

Checks ☑️

  • Primary Mongo tester: 88 examples, 0 failures, 7 existing pending
  • Alternate GraphQL tester: 88 examples, 0 failures, 7 existing pending
  • Focused pagination coverage: 7 examples, 0 failures in both tester bundles
  • Direct prepare/load sequencing covered
  • Legacy lookahead fallback covered
  • git diff --check

Test Guidance

  1. Run ASDF_RUBY_VERSION=3.4.8 DRIVER=mongo bundle exec rspec spec/graphoid/queries/pagination_spec.rb from spec/tester_mongo.
  2. Repeat from spec/tester_mongo_rails_6 for the alternate GraphQL dependency.
  3. Define both direct hooks and confirm the loader receives the exact criteria returned by preparation.
  4. Return a materialized collection from the loader and confirm GraphQL serializes it.
  5. Remove the direct hooks, define legacy lookahead, and confirm fallback behavior remains available.
  6. Query a model without custom hooks and confirm normal filtering, ordering, limit, and skip behavior remains unchanged.

EXPLANATION: Added a direct `graphoid_load_paginated_data(scope, lookahead:)` model hook for generated pagination data and removed indirect `lookahead`/zero-argument `eager_load` dispatch through query objects. Added integration coverage for the strict hook, returned collections, unchanged no-hook pagination, and ignored legacy methods. Evaluated further N+1 architectures and retained the bounded first/second-hop API loader as the simplest query-efficient design. Verified both Mongo tester suites with 88 examples, 0 failures, and 7 existing pending examples each.
---
PROMPT: great, since we are access to oxeanbits/graphoid implementation (and digitalize-api is the only consumer of this repo), search if an even more performance improvement could be done (address this n+1 solution in another query level, or another architeture to optimize memory and mongo finds).
if we already achived a good point, lets target the simplest solution. portalize current PR solution into another PR (keep current one as it is), open a new branch in graphoid fork (and a PR), the new api PR could updated the submodule sha to the new-branch one (including several bumps already merged in master)
EXPLANATION: Split paginated data resolution into direct `graphoid_prepare_paginated_scope` and `graphoid_load_paginated_data` model stages, preserving the transformed scope between them. Added independent legacy `lookahead` and `eager_load` fallbacks for unmigrated models, plus integration coverage for direct hook sequencing and legacy lookahead behavior. Verified both Graphoid tester suites with 88 examples, 0 failures, and 7 existing pending examples each.
---
PROMPT: ok agree with the architecture, lets update both api and graphoid prs
@GiuseppeXD GiuseppeXD self-assigned this Jul 28, 2026
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.

1 participant