Skip to content

Commit aab986e

Browse files
committed
Add support for autoloading nested related objects on ingredients
This takes the capabilities from AlchemyCMS/alchemy_cms#2523 and allows pre-loading object graphs on ingredient's related objects.
1 parent 44784da commit aab986e

File tree

2 files changed

+31
-8
lines changed

2 files changed

+31
-8
lines changed

app/controllers/alchemy/json_api/pages_controller.rb

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ def show
3838
def render_pages_json(allowed)
3939
# Only load pages with all includes when browser cache is stale
4040
jsonapi_filter(page_scope_with_includes, allowed) do |filtered|
41-
# decorate with our page model that has a eager loaded elements collection
42-
filtered_pages = filtered.result.map { |page| api_page(page) }
43-
jsonapi_paginate(filtered_pages) do |paginated|
44-
render jsonapi: paginated
41+
jsonapi_paginate(filtered.result) do |paginated|
42+
# decorate with our page model that has a eager loaded elements collection
43+
decorated_pages = preload_ingredient_relations(paginated).map { |page| api_page(page) }
44+
render jsonapi: decorated_pages
4545
end
4646
end
4747
end
@@ -74,7 +74,9 @@ def jsonapi_meta(pages)
7474
end
7575

7676
def load_page
77-
@page = load_page_by_id || load_page_by_urlname || raise(ActiveRecord::RecordNotFound)
77+
@page = preload_ingredient_relations(
78+
[load_page_by_id || load_page_by_urlname || raise(ActiveRecord::RecordNotFound)]
79+
).first
7880
end
7981

8082
def load_page_by_id
@@ -109,6 +111,21 @@ def page_scope_with_includes
109111
)
110112
end
111113

114+
def preload_ingredient_relations(pages)
115+
pages.map { |page| page.send(page_version_type) }.flat_map(&:elements).flat_map(&:ingredients).group_by(&:preload_relations).each do |preload_relations, ingredients|
116+
preload(records: ingredients.map(&:related_object).compact, associations: preload_relations)
117+
end
118+
pages
119+
end
120+
121+
def preload(records:, associations:)
122+
if Rails::VERSION::MAJOR >= 7
123+
ActiveRecord::Associations::Preloader.new(records: records, associations: associations).call
124+
else
125+
ActiveRecord::Associations::Preloader.new.preload(records, associations)
126+
end
127+
end
128+
112129
def page_version_type
113130
:public_version
114131
end

app/serializers/alchemy/json_api/page_serializer.rb

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,21 @@ class PageSerializer < BaseSerializer
3333

3434
# All public elements of this page regardless of if they are fixed or nested.
3535
# Used for eager loading and should be used as the +include+ parameter of your query
36-
has_many :all_elements, record_type: :element, serializer: ELEMENT_SERIALIZER
36+
has_many :all_elements, record_type: :element, serializer: ELEMENT_SERIALIZER do |record|
37+
record.public_version.element_repository.visible
38+
end
3739

3840
# The top level public, non-fixed elements of this page that - if present -
3941
# contains their nested_elements.
40-
has_many :elements, record_type: :element, serializer: ELEMENT_SERIALIZER
42+
has_many :elements, record_type: :element, serializer: ELEMENT_SERIALIZER do |record|
43+
record.public_version.element_repository.visible.unfixed
44+
end
4145

4246
# The top level public, fixed elements of this page that - if present -
4347
# contains their nested_elements.
44-
has_many :fixed_elements, record_type: :element, serializer: ELEMENT_SERIALIZER
48+
has_many :fixed_elements, record_type: :element, serializer: ELEMENT_SERIALIZER do |record|
49+
record.public_version.element_repository.visible.unfixed
50+
end
4551
end
4652
end
4753
end

0 commit comments

Comments
 (0)