PERF: Remove N+1s from ThemeController#update and #show (#12842)

These endpoints only return one `Theme` row, but the one-many relations were not being preloaded efficiently. This commit moves the `includes` statement to a scope, and makes use of it in `#index`, `#show`, and `#update`.
This commit is contained in:
David Taylor
2021-04-27 12:30:29 +01:00
committed by GitHub
parent 40e545dc30
commit 657dff3544
2 changed files with 17 additions and 13 deletions

View File

@ -128,16 +128,7 @@ class Admin::ThemesController < Admin::AdminController
end end
def index def index
@themes = Theme.order(:name).includes(:child_themes, @themes = Theme.include_relations.order(:name)
:parent_themes,
:remote_theme,
:theme_settings,
:settings_field,
:locale_fields,
:user,
:color_scheme,
theme_fields: :upload
)
@color_schemes = ColorScheme.all.includes(:theme, color_scheme_colors: :color_scheme).to_a @color_schemes = ColorScheme.all.includes(:theme, color_scheme_colors: :color_scheme).to_a
payload = { payload = {
@ -175,7 +166,7 @@ class Admin::ThemesController < Admin::AdminController
end end
def update def update
@theme = Theme.find_by(id: params[:id]) @theme = Theme.include_relations.find_by(id: params[:id])
raise Discourse::InvalidParameters.new(:id) unless @theme raise Discourse::InvalidParameters.new(:id) unless @theme
original_json = ThemeSerializer.new(@theme, root: false).to_json original_json = ThemeSerializer.new(@theme, root: false).to_json
@ -213,7 +204,7 @@ class Admin::ThemesController < Admin::AdminController
if @theme.save if @theme.save
update_default_theme update_default_theme
@theme.reload @theme = Theme.include_relations.find(@theme.id)
if (!disables_component && !enables_component) || theme_params.keys.size > 1 if (!disables_component && !enables_component) || theme_params.keys.size > 1
log_theme_change(original_json, @theme) log_theme_change(original_json, @theme)
@ -249,7 +240,7 @@ class Admin::ThemesController < Admin::AdminController
end end
def show def show
@theme = Theme.find_by(id: params[:id]) @theme = Theme.include_relations.find_by(id: params[:id])
raise Discourse::InvalidParameters.new(:id) unless @theme raise Discourse::InvalidParameters.new(:id) unless @theme
render json: ThemeSerializer.new(@theme) render json: ThemeSerializer.new(@theme)

View File

@ -38,6 +38,19 @@ class Theme < ActiveRecord::Base
where('user_selectable OR id = ?', SiteSetting.default_theme_id) where('user_selectable OR id = ?', SiteSetting.default_theme_id)
} }
scope :include_relations, -> {
includes(:child_themes,
:parent_themes,
:remote_theme,
:theme_settings,
:settings_field,
:locale_fields,
:user,
:color_scheme,
theme_fields: :upload
)
}
def notify_color_change(color, scheme: nil) def notify_color_change(color, scheme: nil)
scheme ||= color.color_scheme scheme ||= color.color_scheme
changed_colors << color if color changed_colors << color if color