noesya/osuny

View on GitHub
app/models/university/person/with_alumnus.rb

Summary

Maintainability
A
25 mins
Test Coverage
A
91%
module University::Person::WithAlumnus
  extend ActiveSupport::Concern

  included do
    has_and_belongs_to_many       :cohorts,
                                  class_name: '::Education::Cohort',
                                  foreign_key: :university_person_id,
                                  association_foreign_key: :education_cohort_id
    accepts_nested_attributes_for :cohorts,
                                  reject_if: :all_blank,
                                  allow_destroy: true
    before_validation :find_cohorts
    validates_associated :cohorts

    # Dénormalisation des liens via cohorts, pour la recherche par facettes
    has_and_belongs_to_many       :diploma_years,
                                  class_name: 'Education::AcademicYear',
                                  foreign_key: :university_person_id,
                                  association_foreign_key: :education_academic_year_id

    has_and_belongs_to_many       :diploma_programs,
                                  class_name: 'Education::Program',
                                  foreign_key: :university_person_id,
                                  association_foreign_key: :education_program_id

    has_many                      :experiences,
                                  class_name: "University::Person::Experience",
                                  dependent: :destroy

    accepts_nested_attributes_for :experiences,
                                  reject_if: :all_blank,
                                  allow_destroy: true

    validates_associated :experiences

    scope :for_alumni_organization, -> (organization_ids, language = nil) {
      left_joins(:experiences)
        .where(university_person_experiences: { organization_id: organization_ids })
        .select("university_people.*")
        .distinct
    }

    scope :for_alumni_program, -> (program_ids, language = nil) {
      left_joins(:cohorts)
        .where(education_cohorts: { program_id: program_ids })
        .select("university_people.*")
        .distinct
    }
    scope :for_alumni_year, -> (academic_year_ids, language = nil) {
      left_joins(:cohorts)
        .where(education_cohorts: { academic_year_id: academic_year_ids })
        .select("university_people.*")
        .distinct
    }
  end

  def find_cohorts
    # based on https://stackoverflow.com/questions/3579924/accepts-nested-attributes-for-with-find-or-create
    cohorts_to_set = []
    cohorts_ids_to_set = []
    undestroyed_cohorts = self.cohorts.reject(&:_destroy)
    undestroyed_cohorts.each do |object|
      cohort = find_cohort_for_nested(object)
      next if cohorts_ids_to_set.include?(cohort.id)
      cohorts_ids_to_set << cohort.id unless cohort.id.nil?
      cohorts_to_set << cohort
    end
    self.cohorts = cohorts_to_set
  end

  private

  def find_cohort_for_nested(object)
    academic_year = Education::AcademicYear.where(university_id: university_id, year: object.year).first_or_create
    cohort = Education::Cohort.where(university_id: university_id, school_id: object.school_id, program_id: object.program_id, academic_year_id: academic_year.id).first_or_initialize
    return unless cohort.valid?
    cohort.save if cohort.new_record?
    cohort.reload
  end
end