From fdb287be2164c2978bfa5937f28da12e09091d3d Mon Sep 17 00:00:00 2001
From: Arnaud Levy <contact@arnaudlevy.com>
Date: Wed, 18 May 2022 06:42:10 +0200
Subject: [PATCH] clean programs with traits

---
 app/models/education/program.rb               | 78 ++-----------------
 app/models/education/program/with_alumni.rb   | 38 +++++++++
 app/models/education/program/with_team.rb     | 32 ++++++++
 app/models/education/program/with_websites.rb | 21 +++++
 app/models/education/school.rb                |  4 +-
 5 files changed, 100 insertions(+), 73 deletions(-)
 create mode 100644 app/models/education/program/with_alumni.rb
 create mode 100644 app/models/education/program/with_team.rb
 create mode 100644 app/models/education/program/with_websites.rb

diff --git a/app/models/education/program.rb b/app/models/education/program.rb
index a64575637..a6a96da03 100644
--- a/app/models/education/program.rb
+++ b/app/models/education/program.rb
@@ -59,6 +59,9 @@ class Education::Program < ApplicationRecord
   include WithInheritance
   include WithPosition
   include WithBlocks
+  include WithAlumni
+  include WithWebsites
+  include WithTeam
 
   rich_text_areas_with_inheritance  :main_information,
                                     :accessibility,
@@ -76,88 +79,26 @@ class Education::Program < ApplicationRecord
                                     :content,
                                     :results
 
-  attr_accessor :skip_websites_categories_callback
-
   belongs_to :parent,
              class_name: 'Education::Program',
              optional: true
+
   has_many   :children,
              class_name: 'Education::Program',
              foreign_key: :parent_id,
              dependent: :destroy
+
   belongs_to :diploma,
              class_name: 'Education::Diploma',
              optional: true
-  has_many   :university_roles,
-             class_name: 'University::Role',
-             as: :target,
-             dependent: :destroy
-  has_many   :involvements_through_roles,
-             through: :university_roles,
-             source: :involvements
-  has_many   :university_people_through_role_involvements,
-             through: :involvements_through_roles,
-             source: :person
-  has_many   :university_person_involvements,
-             class_name: 'University::Person::Involvement',
-             as: :target,
-             inverse_of: :target,
-             dependent: :destroy
-  has_many   :university_people_through_involvements,
-             through: :university_person_involvements,
-             source: :person
-  has_many   :website_categories,
-             class_name: 'Communication::Website::Category',
-             dependent: :destroy
+
   has_and_belongs_to_many :schools,
                           class_name: 'Education::School',
                           join_table: 'education_programs_schools',
                           foreign_key: 'education_program_id',
                           association_foreign_key: 'education_school_id'
-  has_many   :websites,
-             -> { distinct },
-             through: :schools
-
-  has_many   :education_cohorts,
-             class_name: 'Education::Cohort'
-  alias_attribute :cohorts, :education_cohorts
-
-  has_many   :alumni,
-             through: :education_cohorts,
-             source: :people
-  alias_attribute :university_person_alumni, :alumni
-
-  has_many   :alumni_experiences,
-             -> { distinct },
-             class_name: 'University::Person::Experience',
-             through: :alumni,
-             source: :experiences
-  alias_attribute :university_person_experiences, :alumni_experiences
-
-  has_many   :alumni_organizations,
-             -> { distinct },
-             class_name: 'University::Organization',
-             through: :alumni_experiences,
-             source: :organization
-  alias_attribute :university_person_alumni_organizations, :alumni_organizations
-
-  has_many   :education_academic_years,
-             -> { distinct },
-             class_name: 'Education::AcademicYear',
-             through: :education_cohorts,
-             source: :academic_year
-             alias_attribute :academic_years, :education_academic_years
-
-  # Dénormalisation des alumni pour le faceted search
-  has_and_belongs_to_many :university_people,
-                          class_name: 'University::Person',
-                          foreign_key: 'education_program_id',
-                          association_foreign_key: 'university_person_id'
-
-  accepts_nested_attributes_for :university_person_involvements,
-                                reject_if: :all_blank,
-                                allow_destroy: true
 
+  # Deprecated, now in diploma
   enum level: {
     not_applicable: 0,
     primary: 40,
@@ -174,7 +115,6 @@ class Education::Program < ApplicationRecord
   validates_presence_of :name
 
   after_save :update_children_paths, if: :saved_change_to_path?
-  after_save_commit :set_websites_categories, unless: :skip_websites_categories_callback
 
   scope :published, -> { where(published: true) }
   scope :ordered_by_name, -> { order(:name) }
@@ -231,10 +171,6 @@ class Education::Program < ApplicationRecord
     end
   end
 
-  def set_websites_categories
-    websites.find_each(&:set_programs_categories!)
-  end
-
   #####################
   # Aboutable methods #
   #####################
diff --git a/app/models/education/program/with_alumni.rb b/app/models/education/program/with_alumni.rb
new file mode 100644
index 000000000..602d0d2b1
--- /dev/null
+++ b/app/models/education/program/with_alumni.rb
@@ -0,0 +1,38 @@
+module Education::Program::WithAlumni
+  extend ActiveSupport::Concern
+
+  included do
+    has_many   :cohorts,
+               class_name: 'Education::Cohort'
+               alias_attribute :education_cohorts, :cohorts
+
+    has_many   :alumni,
+               through: :cohorts,
+               source: :people
+               alias_attribute :university_person_alumni, :alumni
+
+    has_many   :alumni_experiences, -> { distinct },
+               class_name: 'University::Person::Experience',
+               through: :alumni,
+               source: :experiences
+               alias_attribute :university_person_experiences, :alumni_experiences
+
+    has_many   :alumni_organizations, -> { distinct },
+               class_name: 'University::Organization',
+               through: :alumni_experiences,
+               source: :organization
+               alias_attribute :university_person_alumni_organizations, :alumni_organizations
+
+    has_many   :academic_years, -> { distinct },
+               class_name: 'Education::AcademicYear',
+               through: :cohorts,
+               source: :academic_year
+               alias_attribute :education_academic_years, :academic_years
+
+    # Dénormalisation des alumni pour le faceted search
+    has_and_belongs_to_many :university_people,
+                            class_name: 'University::Person',
+                            foreign_key: 'education_program_id',
+                            association_foreign_key: 'university_person_id'
+  end
+end
diff --git a/app/models/education/program/with_team.rb b/app/models/education/program/with_team.rb
new file mode 100644
index 000000000..513fdf9fe
--- /dev/null
+++ b/app/models/education/program/with_team.rb
@@ -0,0 +1,32 @@
+module Education::Program::WithTeam
+  extend ActiveSupport::Concern
+
+  included do
+    has_many   :university_roles,
+               class_name: 'University::Role',
+               as: :target,
+               dependent: :destroy
+
+    has_many   :involvements_through_roles,
+               through: :university_roles,
+               source: :involvements
+
+    has_many   :university_people_through_role_involvements,
+               through: :involvements_through_roles,
+               source: :person
+
+    has_many   :university_person_involvements,
+               class_name: 'University::Person::Involvement',
+               as: :target,
+               inverse_of: :target,
+               dependent: :destroy
+
+    accepts_nested_attributes_for :university_person_involvements,
+                                  reject_if: :all_blank,
+                                  allow_destroy: true
+
+    has_many   :university_people_through_involvements,
+               through: :university_person_involvements,
+               source: :person
+  end
+end
diff --git a/app/models/education/program/with_websites.rb b/app/models/education/program/with_websites.rb
new file mode 100644
index 000000000..a9b81dbe9
--- /dev/null
+++ b/app/models/education/program/with_websites.rb
@@ -0,0 +1,21 @@
+module Education::Program::WithWebsites
+  extend ActiveSupport::Concern
+
+  included do
+    attr_accessor :skip_websites_categories_callback
+
+    after_save_commit :set_websites_categories, unless: :skip_websites_categories_callback
+
+    # FIXME incorrect, forgets websites about programs
+    has_many   :websites, -> { distinct },
+               through: :schools
+
+    has_many   :website_categories,
+               class_name: 'Communication::Website::Category',
+               dependent: :destroy
+  end
+
+  def set_websites_categories
+    websites.find_each(&:set_programs_categories!)
+  end
+end
diff --git a/app/models/education/school.rb b/app/models/education/school.rb
index c7399a66d..93f6aac57 100644
--- a/app/models/education/school.rb
+++ b/app/models/education/school.rb
@@ -84,10 +84,10 @@ class Education::School < ApplicationRecord
               source: :organization
   alias_attribute :university_person_alumni_organizations, :alumni_organizations
 
-  has_many    :education_academic_years, -> { distinct },
+  has_many    :academic_years, -> { distinct },
               class_name: 'Education::AcademicYear',
               through: :programs
-  alias_attribute :academic_years, :education_academic_years
+  alias_attribute :education_academic_years, :academic_years
 
   has_many    :education_cohorts, -> { distinct },
               class_name: 'Education::Cohort',
-- 
GitLab