From eaa43d582aee8e5c1baa55de1c3a6d403c316816 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Gaya?= <sebastien.gaya@gmail.com>
Date: Thu, 6 Jan 2022 14:02:49 +0100
Subject: [PATCH] roles

---
 app/models/communication/website/category.rb  | 15 ++------
 app/models/communication/website/menu/item.rb | 10 ++----
 app/models/communication/website/page.rb      |  6 +++-
 app/models/concerns/with_position.rb          | 18 ++++++++++
 app/models/education/program.rb               | 11 +++++-
 app/models/education/program/role.rb          | 34 +++++++++++++++++++
 ...06104521_create_education_program_roles.rb | 12 +++++++
 db/schema.rb                                  | 15 +++++++-
 test/fixtures/education/program/roles.yml     | 34 +++++++++++++++++++
 test/fixtures/education/program/teachers.yml  |  1 -
 test/models/education/program/role_test.rb    | 29 ++++++++++++++++
 11 files changed, 162 insertions(+), 23 deletions(-)
 create mode 100644 app/models/concerns/with_position.rb
 create mode 100644 app/models/education/program/role.rb
 create mode 100644 db/migrate/20220106104521_create_education_program_roles.rb
 create mode 100644 test/fixtures/education/program/roles.yml
 create mode 100644 test/models/education/program/role_test.rb

diff --git a/app/models/communication/website/category.rb b/app/models/communication/website/category.rb
index bbe7fc968..c933b3526 100644
--- a/app/models/communication/website/category.rb
+++ b/app/models/communication/website/category.rb
@@ -36,6 +36,7 @@ class Communication::Website::Category < ApplicationRecord
   include WithMenuItemTarget
   include WithSlug # We override slug_unavailable? method
   include WithTree
+  include WithPosition
 
   has_one                 :imported_category,
                           class_name: 'Communication::Website::Imported::Category',
@@ -66,10 +67,6 @@ class Communication::Website::Category < ApplicationRecord
 
   after_save :update_children_paths, if: :saved_change_to_path?
 
-  scope :ordered, -> { order(:position) }
-
-  before_create :set_position
-
   def to_s
     "#{name}"
   end
@@ -99,14 +96,8 @@ class Communication::Website::Category < ApplicationRecord
 
   protected
 
-  def set_position
-    last_element = website.categories.where(parent_id: parent_id).ordered.last
-
-    unless last_element.nil?
-      self.position = last_element.position + 1
-    else
-      self.position = 1
-    end
+  def last_ordered_element
+    website.categories.where(parent_id: parent_id).ordered.last
   end
 
   def slug_unavailable?(slug)
diff --git a/app/models/communication/website/menu/item.rb b/app/models/communication/website/menu/item.rb
index 6327f27ba..b8c1f9a79 100644
--- a/app/models/communication/website/menu/item.rb
+++ b/app/models/communication/website/menu/item.rb
@@ -33,6 +33,7 @@
 #
 class Communication::Website::Menu::Item < ApplicationRecord
   include WithTree
+  include WithPosition
 
   attr_accessor :skip_publication_callback
 
@@ -61,11 +62,8 @@ class Communication::Website::Menu::Item < ApplicationRecord
   validates :title, presence: true
   validates :about, presence: true, if: :has_about?
 
-  before_create :set_position
   after_commit :sync_menu
 
-  scope :ordered, -> { order(position: :asc) }
-
   def to_s
     "#{title}"
   end
@@ -125,9 +123,7 @@ class Communication::Website::Menu::Item < ApplicationRecord
 
   protected
 
-  def set_position
-    last_element = menu.items.where(parent_id: parent_id).ordered.last
-    self.position = last_element.nil? ? 1
-                                      : last_element.position + 1
+  def last_ordered_element
+    menu.items.where(parent_id: parent_id).ordered.last
   end
 end
diff --git a/app/models/communication/website/page.rb b/app/models/communication/website/page.rb
index 2fece1a8a..6bb784199 100644
--- a/app/models/communication/website/page.rb
+++ b/app/models/communication/website/page.rb
@@ -43,6 +43,7 @@ class Communication::Website::Page < ApplicationRecord
   include WithMenuItemTarget
   include WithSlug # We override slug_unavailable? method
   include WithTree
+  include WithPosition
 
   has_rich_text :text
   has_one_attached_deletable :featured_image
@@ -68,7 +69,6 @@ class Communication::Website::Page < ApplicationRecord
 
   after_save :update_children_paths, if: :saved_change_to_path?
 
-  scope :ordered, -> { order(:position) }
   scope :recent, -> { order(updated_at: :desc).limit(5) }
 
   def git_path_static
@@ -107,6 +107,10 @@ class Communication::Website::Page < ApplicationRecord
 
   protected
 
+  def last_ordered_element
+    website.pages.where(parent_id: parent_id).ordered.last
+  end
+
   def slug_unavailable?(slug)
     self.class.unscoped
               .where(communication_website_id: self.communication_website_id, slug: slug)
diff --git a/app/models/concerns/with_position.rb b/app/models/concerns/with_position.rb
new file mode 100644
index 000000000..2319b508c
--- /dev/null
+++ b/app/models/concerns/with_position.rb
@@ -0,0 +1,18 @@
+module WithPosition
+  extend ActiveSupport::Concern
+
+  included do
+    before_create :set_position
+    scope :ordered, -> { order(position: :asc) }
+  end
+
+  protected
+
+  def set_position
+    self.position = last_ordered_element.nil? ? 1 : last_ordered_element.position + 1
+  end
+
+  def last_ordered_element
+    self.class.unscoped.where(university_id: university_id).ordered.last
+  end
+end
diff --git a/app/models/education/program.rb b/app/models/education/program.rb
index 8a873afe2..f2f771577 100644
--- a/app/models/education/program.rb
+++ b/app/models/education/program.rb
@@ -36,6 +36,7 @@ class Education::Program < ApplicationRecord
   include WithSlug
   include WithTree
   include WithInheritance
+  include WithPosition
 
   rich_text_areas_with_inheritance  :accessibility,
                                     :contacts,
@@ -67,6 +68,9 @@ class Education::Program < ApplicationRecord
   has_many   :people,
              through: :teachers,
              dependent: :destroy
+  has_many   :roles,
+             class_name: 'Education::Program::Role',
+             dependent: :destroy
   has_and_belongs_to_many :schools,
                           class_name: 'Education::School',
                           join_table: 'education_programs_schools',
@@ -89,7 +93,6 @@ class Education::Program < ApplicationRecord
   after_save_commit :set_websites_categories, unless: :skip_websites_categories_callback
 
   scope :published, -> { where(published: true) }
-  scope :ordered, -> { order(:position) }
 
   def to_s
     "#{name}"
@@ -125,4 +128,10 @@ class Education::Program < ApplicationRecord
   def set_websites_categories
     websites.find_each(&:set_programs_categories!)
   end
+
+  protected
+
+  def last_ordered_element
+    university.programs.where(parent_id: parent_id).ordered.last
+  end
 end
diff --git a/app/models/education/program/role.rb b/app/models/education/program/role.rb
new file mode 100644
index 000000000..2bb9dd6c7
--- /dev/null
+++ b/app/models/education/program/role.rb
@@ -0,0 +1,34 @@
+# == Schema Information
+#
+# Table name: education_program_roles
+#
+#  id            :uuid             not null, primary key
+#  position      :integer
+#  title         :string
+#  created_at    :datetime         not null
+#  updated_at    :datetime         not null
+#  program_id    :uuid             not null
+#  university_id :uuid             not null
+#
+# Indexes
+#
+#  index_education_program_roles_on_program_id     (program_id)
+#  index_education_program_roles_on_university_id  (university_id)
+#
+# Foreign Keys
+#
+#  fk_rails_...  (program_id => education_programs.id)
+#  fk_rails_...  (university_id => universities.id)
+#
+class Education::Program::Role < ApplicationRecord
+  include WithPosition
+
+  belongs_to :university
+  belongs_to :program, class_name: 'Education::Program'
+
+  protected
+
+  def last_ordered_element
+    program.roles.ordered.last
+  end
+end
diff --git a/db/migrate/20220106104521_create_education_program_roles.rb b/db/migrate/20220106104521_create_education_program_roles.rb
new file mode 100644
index 000000000..57bd86e07
--- /dev/null
+++ b/db/migrate/20220106104521_create_education_program_roles.rb
@@ -0,0 +1,12 @@
+class CreateEducationProgramRoles < ActiveRecord::Migration[6.1]
+  def change
+    create_table :education_program_roles, id: :uuid do |t|
+      t.string :title
+      t.integer :position
+      t.references :program, null: false, foreign_key: { to_table: :education_programs }, type: :uuid
+      t.references :university, null: false, foreign_key: true, type: :uuid
+
+      t.timestamps
+    end
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 39bb00f08..4e15658bf 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 2022_01_05_151606) do
+ActiveRecord::Schema.define(version: 2022_01_06_104521) do
 
   # These are extensions that must be enabled in order to support this database
   enable_extension "pgcrypto"
@@ -347,6 +347,17 @@ ActiveRecord::Schema.define(version: 2022_01_05_151606) do
     t.index ["priority", "run_at"], name: "delayed_jobs_priority"
   end
 
+  create_table "education_program_roles", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+    t.string "title"
+    t.integer "position"
+    t.uuid "program_id", null: false
+    t.uuid "university_id", null: false
+    t.datetime "created_at", precision: 6, null: false
+    t.datetime "updated_at", precision: 6, null: false
+    t.index ["program_id"], name: "index_education_program_roles_on_program_id"
+    t.index ["university_id"], name: "index_education_program_roles_on_university_id"
+  end
+
   create_table "education_program_teachers", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
     t.text "description"
     t.uuid "program_id", null: false
@@ -579,6 +590,8 @@ ActiveRecord::Schema.define(version: 2022_01_05_151606) do
   add_foreign_key "communication_website_posts", "universities"
   add_foreign_key "communication_website_posts", "university_people", column: "author_id"
   add_foreign_key "communication_websites", "universities"
+  add_foreign_key "education_program_roles", "education_programs", column: "program_id"
+  add_foreign_key "education_program_roles", "universities"
   add_foreign_key "education_program_teachers", "education_programs", column: "program_id"
   add_foreign_key "education_program_teachers", "university_people", column: "person_id"
   add_foreign_key "education_programs", "education_programs", column: "parent_id"
diff --git a/test/fixtures/education/program/roles.yml b/test/fixtures/education/program/roles.yml
new file mode 100644
index 000000000..cce31b11f
--- /dev/null
+++ b/test/fixtures/education/program/roles.yml
@@ -0,0 +1,34 @@
+# == Schema Information
+#
+# Table name: education_program_roles
+#
+#  id            :uuid             not null, primary key
+#  position      :integer
+#  title         :string
+#  created_at    :datetime         not null
+#  updated_at    :datetime         not null
+#  program_id    :uuid             not null
+#  university_id :uuid             not null
+#
+# Indexes
+#
+#  index_education_program_roles_on_program_id     (program_id)
+#  index_education_program_roles_on_university_id  (university_id)
+#
+# Foreign Keys
+#
+#  fk_rails_...  (program_id => education_programs.id)
+#  fk_rails_...  (university_id => universities.id)
+#
+
+one:
+  title: MyString
+  position: 1
+  program: one
+  university: one
+
+two:
+  title: MyString
+  position: 1
+  program: two
+  university: two
diff --git a/test/fixtures/education/program/teachers.yml b/test/fixtures/education/program/teachers.yml
index 552fd1552..1029c55da 100644
--- a/test/fixtures/education/program/teachers.yml
+++ b/test/fixtures/education/program/teachers.yml
@@ -19,7 +19,6 @@
 #  fk_rails_...  (person_id => university_people.id)
 #  fk_rails_...  (program_id => education_programs.id)
 #
-# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
 
 one:
   description: MyText
diff --git a/test/models/education/program/role_test.rb b/test/models/education/program/role_test.rb
new file mode 100644
index 000000000..2b9d81195
--- /dev/null
+++ b/test/models/education/program/role_test.rb
@@ -0,0 +1,29 @@
+# == Schema Information
+#
+# Table name: education_program_roles
+#
+#  id            :uuid             not null, primary key
+#  position      :integer
+#  title         :string
+#  created_at    :datetime         not null
+#  updated_at    :datetime         not null
+#  program_id    :uuid             not null
+#  university_id :uuid             not null
+#
+# Indexes
+#
+#  index_education_program_roles_on_program_id     (program_id)
+#  index_education_program_roles_on_university_id  (university_id)
+#
+# Foreign Keys
+#
+#  fk_rails_...  (program_id => education_programs.id)
+#  fk_rails_...  (university_id => universities.id)
+#
+require "test_helper"
+
+class Education::Program::RoleTest < ActiveSupport::TestCase
+  # test "the truth" do
+  #   assert true
+  # end
+end
-- 
GitLab