diff --git a/app/models/schooling.rb b/app/models/schooling.rb index 19ab3d1a4..2ebb53d42 100644 --- a/app/models/schooling.rb +++ b/app/models/schooling.rb @@ -15,8 +15,8 @@ class Schooling < ApplicationRecord has_one :mef, through: :classe has_one :establishment, through: :classe - scope :current, -> { where(end_date: nil) } scope :former, -> { where.not(end_date: nil).where(end_date: ..Date.current) } + scope :current, -> { where.not(id: former) } scope :with_attributive_decisions, -> { joins(:attributive_decision_attachment) } scope :without_attributive_decisions, -> { where.missing(:attributive_decision_attachment) } diff --git a/app/models/student.rb b/app/models/student.rb index 1c42500c4..41931c703 100644 --- a/app/models/student.rb +++ b/app/models/student.rb @@ -18,11 +18,7 @@ class Student < ApplicationRecord # rubocop:disable Metrics/ClassLength has_many :pfmps, -> { order "pfmps.created_at" }, through: :schoolings - has_one :current_schooling, - -> { where(end_date: nil).or(where("end_date > ?", Date.current)) }, - class_name: "Schooling", - dependent: :destroy, - inverse_of: :student + has_one :current_schooling, -> { current }, class_name: "Schooling", dependent: :destroy, inverse_of: :student has_one :classe, through: :current_schooling diff --git a/spec/models/schooling_spec.rb b/spec/models/schooling_spec.rb index a383cfcd0..9820e3459 100644 --- a/spec/models/schooling_spec.rb +++ b/spec/models/schooling_spec.rb @@ -12,6 +12,52 @@ it { is_expected.to have_one(:mef).class_name("Mef") } end + describe "scopes" do + let!(:current_schooling_no_end_date) { create(:schooling, end_date: nil) } + let!(:current_schooling_future_end_date) { create(:schooling, end_date: 1.day.from_now) } + let!(:former_schooling_past_end_date) { create(:schooling, end_date: 1.day.ago) } + + describe ".former" do + subject { described_class.former } + + it { is_expected.to include(former_schooling_past_end_date) } + it { is_expected.not_to include(current_schooling_no_end_date) } + it { is_expected.not_to include(current_schooling_future_end_date) } + + it "includes schoolings with end_date on or before the current date" do + expect(described_class.former.to_a).to eq([former_schooling_past_end_date]) + end + end + + describe ".current" do + subject { described_class.current } + + it { is_expected.to include(current_schooling_no_end_date) } + it { is_expected.to include(current_schooling_future_end_date) } + it { is_expected.not_to include(former_schooling_past_end_date) } + + it "includes schoolings with no end_date or end_date after the current date" do + expect(described_class.current.to_a).to contain_exactly(current_schooling_no_end_date, + current_schooling_future_end_date) + end + end + + describe "mutual exclusivity" do + it "ensures every schooling is either current or former" do + all_schoolings = described_class.all + current_and_former = described_class.current.or(described_class.former) + + expect(all_schoolings).to match_array(current_and_former) + end + + it "ensures no schooling is both current and former" do + overlap = described_class.current.where(id: described_class.former) + + expect(overlap).to be_empty + end + end + end + describe "validations" do describe "end_date" do context "when the end date is before the start" do @@ -140,22 +186,6 @@ end end - describe ".current" do - subject { described_class.current } - - context "when the schooling is over" do - let(:schooling) { create(:schooling, :closed) } - - it { is_expected.not_to include schooling } - end - - context "when the schooling is active" do - let(:schooling) { create(:schooling) } - - it { is_expected.to include schooling } - end - end - describe "#closed?" do subject(:schooling) { create(:schooling, end_date: Date.tomorrow) }