Class: Alchemy::PageTreePreloader

Inherits:
Object
  • Object
show all
Defined in:
app/services/alchemy/page_tree_preloader.rb

Overview

Preloads page trees with all associations and children

This service efficiently loads page trees to avoid N+1 queries. It handles folded pages and preloads all necessary associations.

Examples:

Preload subtree from a specific page

preloader = Alchemy::PageTreePreloader.new(page: page, user: current_user)
page_with_descendants = preloader.call

Instance Method Summary collapse

Constructor Details

#initialize(page:, user: nil, admin_includes: false) ⇒ PageTreePreloader

Returns a new instance of PageTreePreloader.

Parameters:

  • page (Page)

    Starting page for loading descendants

  • user (User, nil) (defaults to: nil)

    User for folding support

  • admin_includes (Boolean) (defaults to: false)

    Whether to include admin-only associations like :locker



17
18
19
20
21
# File 'app/services/alchemy/page_tree_preloader.rb', line 17

def initialize(page:, user: nil, admin_includes: false)
  @page = page
  @user = user
  @admin_includes = admin_includes
end

Instance Method Details

#callArray<Page>

Preloads and returns the page tree

Returns:

  • (Array<Page>)

    Pages with preloaded children, or array with single page when using from:



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'app/services/alchemy/page_tree_preloader.rb', line 26

def call
  pages = page.self_and_descendants
  folded_page_ids = load_folded_page_ids
  if folded_page_ids.any?
    pages = pages.where(
      "parent_id IS NULL OR parent_id NOT IN (?)",
      folded_page_ids
    )
  end
  pages = pages.preload(*preload_associations)
  pages = pages.map { PageTreePage.new(_1) }

  preload_children_associations(pages, folded_page_ids:)

  # Return the starting page, which now has preloaded descendants
  # We need to return the actual instance from the pages array, not the @page instance
  # because the children associations were set on the pages array instances
  pages.find { |p| p.id == page.id }
end