diff --git a/app/services/osuny/category/optimizer.rb b/app/services/osuny/category/optimizer.rb new file mode 100644 index 000000000..920d309e3 --- /dev/null +++ b/app/services/osuny/category/optimizer.rb @@ -0,0 +1,66 @@ +# Charge toutes les catégories d'une université en une seule requête et remonte +# la chaîne de parents en mémoire, pour afficher un objet categorizable groupé +# par taxonomie sans le N+1 de la récursion `descendants_and_self`. +module Osuny + module Category + class Optimizer + def initialize(about) + @about = about + end + + # { taxonomie => [catégories de about rattachées à cette taxonomie] }, + # ordonné, limité aux taxonomies qui ont au moins une catégorie utilisée. + # + # Exemple : { # => [#, #] } + def groups_by_taxonomy + @groups_by_taxonomy ||= taxonomies.each_with_object({}) do |taxonomy, hash| + used = about_categories_by_root[taxonomy] + hash[taxonomy] = used if used.present? + end + end + + # Catégories de about qui sont elles-mêmes racines et non-taxonomies. + # + # Exemple : [#, #] + def free_categories + @free_categories ||= about_categories.select { |c| c.parent_id.nil? && !c.is_taxonomy } + end + + protected + + def about_categories + @about_categories ||= @about.categories.includes(:localizations).to_a + end + + def categories_by_id + @categories_by_id ||= categories_class.where(university: university) + .includes(:localizations) + .index_by(&:id) + end + + def categories_class + @categories_class ||= @about.categories.klass + end + + def university + @university ||= @about.university + end + + def taxonomies + @taxonomies ||= categories_by_id.values + .select { |c| c.parent_id.nil? && c.is_taxonomy } + .sort_by(&:position) + end + + def about_categories_by_root + @about_categories_by_root ||= about_categories.group_by { |c| root_of(c) } + end + + def root_of(category) + current = category + current = categories_by_id[current.parent_id] while current && current.parent_id + current + end + end + end +end diff --git a/app/views/admin/application/categories/widget/_show.html.erb b/app/views/admin/application/categories/widget/_show.html.erb index 539f00cce..18f3ec59f 100644 --- a/app/views/admin/application/categories/widget/_show.html.erb +++ b/app/views/admin/application/categories/widget/_show.html.erb @@ -1,20 +1,11 @@ <% -categories_class = about.categories.klass -categories_in_university = categories_class.where(university: current_university) -taxonomies = categories_in_university.taxonomies.ordered -free_categories = categories_in_university.free -free_categories_in_use = about.categories.merge(free_categories) +optimizer = Osuny::Category::Optimizer.new(about) columns ||= 1 classes = "col-lg-#{12/columns}" # TODO manage child free categories %>
-<% -# First, taxonomies -taxonomies.each do |taxonomy| - taxons_in_use = about.categories.merge(taxonomy.descendants_and_self) - next if taxons_in_use.none? - %> +<% optimizer.groups_by_taxonomy.each do |taxonomy, taxons_in_use| %>
<%= osuny_label taxonomy.to_s_in(current_language) %>
    @@ -24,13 +15,11 @@ taxonomies.each do |taxonomy|
<% end %> -<% -# Then, free categories -if free_categories_in_use.any? %> +<% if optimizer.free_categories.any? %>
<%= osuny_label t('category.title') %>
    - <% free_categories_in_use.each do |category| %> + <% optimizer.free_categories.each do |category| %>
  • <%= osuny_link_localized_if can?(:read, category), category, [:admin, category] %>
  • <% end %>
diff --git a/config/initializers/bugsnag.rb b/config/initializers/bugsnag.rb index fcb07f2ae..ca5fca160 100644 --- a/config/initializers/bugsnag.rb +++ b/config/initializers/bugsnag.rb @@ -26,4 +26,15 @@ next unless user_agent.include?('ChatGPT-User') false end) + + config.add_on_error(proc do |event| + next unless event.metadata.key?(:active_job) + ignored_error_classes = [ + "GoodJob::ActiveJobExtensions::Concurrency::ConcurrencyExceededError", + "Communication::Website::LockError" + ] + error_class = event.exceptions.first[:errorClass] + next unless ignored_error_classes.include?(error_class) + false + end) end