diff --git a/app/controllers/admin/themes_controller.rb b/app/controllers/admin/themes_controller.rb index e262230848c02..68ea28610a51d 100644 --- a/app/controllers/admin/themes_controller.rb +++ b/app/controllers/admin/themes_controller.rb @@ -169,8 +169,10 @@ def import end def index - @themes = Theme.include_relations.order(:name) - @color_schemes = ColorScheme.all.includes(:theme, color_scheme_colors: :color_scheme).to_a + @themes = Theme.strict_loading.include_relations.order(:name) + + @color_schemes = + ColorScheme.strict_loading.all.includes(:theme, color_scheme_colors: :color_scheme).to_a payload = { themes: serialize_data(@themes, ThemeSerializer), diff --git a/app/models/theme.rb b/app/models/theme.rb index dde8675fe64a4..319ffe2346ec6 100644 --- a/app/models/theme.rb +++ b/app/models/theme.rb @@ -84,11 +84,11 @@ def self.cache scope :include_relations, -> do include_basic_relations.includes( - :child_themes, :theme_settings, :settings_field, - :color_scheme, + color_scheme: %i[color_scheme_colors], theme_fields: %i[upload theme_settings_migration], + child_themes: %i[color_scheme locale_fields theme_translation_overrides], ) end @@ -99,7 +99,8 @@ def self.cache :user, :locale_fields, :theme_translation_overrides, - parent_themes: %i[locale_fields theme_translation_overrides], + color_scheme: %i[theme], + parent_themes: %i[color_scheme locale_fields theme_translation_overrides], ) end @@ -658,15 +659,16 @@ def add_relative_theme!(kind, theme) end end - def internal_translations - @internal_translations ||= translations(internal: true) + def internal_translations(preloaded_locale_fields: nil) + @internal_translations ||= + translations(internal: true, preloaded_locale_fields: preloaded_locale_fields) end - def translations(internal: false) + def translations(internal: false, preloaded_locale_fields: nil) fallbacks = I18n.fallbacks[I18n.locale] begin data = - locale_fields.first&.translation_data( + (preloaded_locale_fields&.first || locale_fields.first)&.translation_data( with_overrides: false, internal: internal, fallback_fields: locale_fields, diff --git a/app/serializers/basic_theme_serializer.rb b/app/serializers/basic_theme_serializer.rb index 3339209f4a8d1..7c909f05e7b1f 100644 --- a/app/serializers/basic_theme_serializer.rb +++ b/app/serializers/basic_theme_serializer.rb @@ -12,6 +12,9 @@ def default end def description - object.internal_translations.find { |t| t.key == "theme_metadata.description" }&.value + object + .internal_translations(preloaded_locale_fields: object.locale_fields) + .find { |t| t.key == "theme_metadata.description" } + &.value end end diff --git a/app/serializers/color_scheme_serializer.rb b/app/serializers/color_scheme_serializer.rb index cbc492db8c95b..e277d4cf7e4fb 100644 --- a/app/serializers/color_scheme_serializer.rb +++ b/app/serializers/color_scheme_serializer.rb @@ -8,10 +8,6 @@ def theme_name object.theme&.name end - def theme_id - object.theme&.id - end - def colors db_colors = object.colors.index_by(&:name) object.resolved_colors.map do |name, default| diff --git a/spec/requests/admin/themes_controller_spec.rb b/spec/requests/admin/themes_controller_spec.rb index cd9c3833447a3..261e6ba825841 100644 --- a/spec/requests/admin/themes_controller_spec.rb +++ b/spec/requests/admin/themes_controller_spec.rb @@ -476,6 +476,44 @@ expect(theme_json["remote_theme"]["remote_version"]).to eq("7") end + + it "does not result in N+1 queries" do + # warmup + get "/admin/themes.json" + expect(response.status).to eq(200) + + theme = Fabricate(:theme, color_scheme: Fabricate(:color_scheme)) + Fabricate( + :theme_field, + target_id: Theme.targets[:translations], + theme: theme, + name: "en", + value: + "en:\n theme_metadata:\n description: \"A simple, beautiful theme that improves the out of the box experience for Discourse sites.\"\n topic_pinned: \"Pinned\"\n topic_hot: \"Hot\"\n user_replied: \"replied\"\n user_posted: \"posted\"\n user_updated: \"updated\"\n", + ) + first_request_queries = + track_sql_queries do + get "/admin/themes.json" + expect(response.status).to eq(200) + end + + theme_2 = Fabricate(:theme, color_scheme: Fabricate(:color_scheme)) + Fabricate( + :theme_field, + target_id: Theme.targets[:translations], + theme: theme_2, + name: "en", + value: + "en:\n theme_metadata:\n description: \"A simple, beautiful theme that improves the out of the box experience for Discourse sites.\"\n topic_pinned: \"Pinned\"\n topic_hot: \"Hot\"\n user_replied: \"replied\"\n user_posted: \"posted\"\n user_updated: \"updated\"\n", + ) + second_request_queries = + track_sql_queries do + get "/admin/themes.json" + expect(response.status).to eq(200) + end + + expect(first_request_queries.count).to eq(second_request_queries.count) + end end it "allows themes and components to be edited" do