Module: ForestAdminDatasourceMambuPayments::Plugins::Relations::PivotResolution
- Defined in:
- lib/forest_admin_datasource_mambu_payments/plugins/relations/pivot_resolution.rb
Overview
Shared machinery for the “two-step” relation filters. Forest’s native OneToMany navigation emits a leaf on a virtual foreign key; these filters pre-resolve that key against an intermediate collection and rewrite the predicate as ‘target_field IN [resolved ids]`.
Centralising it here keeps the four concrete filters in sync: the match-nothing sentinel, the EQUAL/IN normalisation, and — crucially —the paginated intermediate read all live in one place. A single un-paginated ‘list` would silently cap resolution at one API page and drop matching records for large relations.
Constant Summary collapse
- Operators =
ForestAdminDatasourceToolkit::Components::Query::ConditionTree::Operators
- ConditionTreeLeaf =
ForestAdminDatasourceToolkit::Components::Query::ConditionTree::Nodes::ConditionTreeLeaf
- ConditionTreeBranch =
ForestAdminDatasourceToolkit::Components::Query::ConditionTree::Nodes::ConditionTreeBranch
- Filter =
ForestAdminDatasourceToolkit::Components::Query::Filter
- Projection =
ForestAdminDatasourceToolkit::Components::Query::Projection
- Page =
ForestAdminDatasourceToolkit::Components::Query::Page
- NO_MATCH_SENTINEL =
All-zero UUID: guaranteed not to exist in Numeral, so the native list returns []. Expresses “match nothing” without tripping the empty-IN guard in ConditionTreeTranslator.
'00000000-0000-0000-0000-000000000000'.freeze
- SUPPORTED_OPS =
Only EQUAL/IN are rewritten — the operators Forest’s OneToMany navigation actually emits.
[Operators::EQUAL, Operators::IN].freeze
- MAX_RESOLVED =
Upper bound on resolved ids. The host collection walks Numeral’s cursor pages under the hood; we ask for one large window so it fetches them all in O(n / page) rather than re-walking per offset. A relation resolving to more than this is logged rather than silently truncated.
10_000
Class Method Summary collapse
- .and_branch(*leaves) ⇒ Object
-
.collect(context, collection_name, condition_tree, field) ⇒ Object
Lists every row of ‘collection_name` matching `condition_tree` and returns the unique non-empty values of `field` (handles both scalar columns and array columns such as InternalAccount.connected_account_ids).
- .no_match(target_field) ⇒ Object
- .normalize(value, operator) ⇒ Object
Class Method Details
.and_branch(*leaves) ⇒ Object
48 49 50 |
# File 'lib/forest_admin_datasource_mambu_payments/plugins/relations/pivot_resolution.rb', line 48 def and_branch(*leaves) ConditionTreeBranch.new('And', leaves) end |
.collect(context, collection_name, condition_tree, field) ⇒ Object
Lists every row of ‘collection_name` matching `condition_tree` and returns the unique non-empty values of `field` (handles both scalar columns and array columns such as InternalAccount.connected_account_ids). One large-window request lets the collection’s cursor pagination fetch all matching rows in a single forward walk.
57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/forest_admin_datasource_mambu_payments/plugins/relations/pivot_resolution.rb', line 57 def collect(context, collection_name, condition_tree, field) rows = context.datasource.get_collection(collection_name).list( Filter.new(condition_tree: condition_tree, page: Page.new(offset: 0, limit: MAX_RESOLVED)), Projection.new([field]) ) if rows.size >= MAX_RESOLVED ForestAdminDatasourceMambuPayments.logger.warn( "[forest_admin_datasource_mambu_payments] #{collection_name} relation resolution hit the " \ "#{MAX_RESOLVED}-row cap on '#{field}'; results may be truncated." ) end rows.flat_map { |row| Array(row[field]) }.compact.reject { |v| v.to_s.empty? }.uniq end |
.no_match(target_field) ⇒ Object
44 45 46 |
# File 'lib/forest_admin_datasource_mambu_payments/plugins/relations/pivot_resolution.rb', line 44 def no_match(target_field) ConditionTreeLeaf.new(target_field, Operators::EQUAL, NO_MATCH_SENTINEL) end |
.normalize(value, operator) ⇒ Object
39 40 41 42 |
# File 'lib/forest_admin_datasource_mambu_payments/plugins/relations/pivot_resolution.rb', line 39 def normalize(value, operator) values = operator == Operators::IN ? Array(value) : [value] values.compact.reject { |v| v.to_s.empty? }.uniq end |