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

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.

diff --git a/app/controllers/admin/themes_controller.rb b/app/controllers/admin/themes_controller.rb
index eec5659..95f9bbe 100644
--- a/app/controllers/admin/themes_controller.rb
+++ b/app/controllers/admin/themes_controller.rb
@@ -128,16 +128,7 @@ class Admin::ThemesController < Admin::AdminController
   end
 
   def index
-    @themes = Theme.order(:name).includes(:child_themes,
-                                          :parent_themes,
-                                          :remote_theme,
-                                          :theme_settings,
-                                          :settings_field,
-                                          :locale_fields,
-                                          :user,
-                                          :color_scheme,
-                                          theme_fields: :upload
-                                          )
+    @themes = Theme.include_relations.order(:name)
     @color_schemes = ColorScheme.all.includes(:theme, color_scheme_colors: :color_scheme).to_a
 
     payload = {
@@ -175,7 +166,7 @@ class Admin::ThemesController < Admin::AdminController
   end
 
   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
 
     original_json = ThemeSerializer.new(@theme, root: false).to_json
@@ -213,7 +204,7 @@ class Admin::ThemesController < Admin::AdminController
       if @theme.save
         update_default_theme
 
-        @theme.reload
+        @theme = Theme.include_relations.find(@theme.id)
 
         if (!disables_component && !enables_component) || theme_params.keys.size > 1
           log_theme_change(original_json, @theme)
@@ -249,7 +240,7 @@ class Admin::ThemesController < Admin::AdminController
   end
 
   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
 
     render json: ThemeSerializer.new(@theme)
diff --git a/app/models/theme.rb b/app/models/theme.rb
index 1ac7d34..3c5ce54 100644
--- a/app/models/theme.rb
+++ b/app/models/theme.rb
@@ -38,6 +38,19 @@ class Theme < ActiveRecord::Base
     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)
     scheme ||= color.color_scheme
     changed_colors << color if color

GitHub sha: 657dff35

This commit appears in #12842 which was approved by eviltrout. It was merged by davidtaylorhq.