Commit 85332a46 authored by Etienne Baqué's avatar Etienne Baqué

Set up has_many relation on Milestone and Release

Updated Release model and its spec file.
Updated Milestone model and its spec file.
parent 4c382ecc
...@@ -30,8 +30,8 @@ class Milestone < ApplicationRecord ...@@ -30,8 +30,8 @@ class Milestone < ApplicationRecord
# A one-to-one relationship is set up here as part of a MVC: https://gitlab.com/gitlab-org/gitlab-ce/issues/62402 # A one-to-one relationship is set up here as part of a MVC: https://gitlab.com/gitlab-org/gitlab-ce/issues/62402
# However, on the long term, we will want a many-to-many relationship between Release and Milestone. # However, on the long term, we will want a many-to-many relationship between Release and Milestone.
# The "has_one through" allows us today to set up this one-to-one relationship while setting up the architecture for the long-term (ie intermediate table). # The "has_one through" allows us today to set up this one-to-one relationship while setting up the architecture for the long-term (ie intermediate table).
has_one :milestone_release has_many :milestone_releases
has_one :release, through: :milestone_release has_many :releases, through: :milestone_releases
has_internal_id :iid, scope: :project, init: ->(s) { s&.project&.milestones&.maximum(:iid) } has_internal_id :iid, scope: :project, init: ->(s) { s&.project&.milestones&.maximum(:iid) }
has_internal_id :iid, scope: :group, init: ->(s) { s&.group&.milestones&.maximum(:iid) } has_internal_id :iid, scope: :group, init: ->(s) { s&.group&.milestones&.maximum(:iid) }
...@@ -68,7 +68,7 @@ class Milestone < ApplicationRecord ...@@ -68,7 +68,7 @@ class Milestone < ApplicationRecord
validate :milestone_type_check validate :milestone_type_check
validate :start_date_should_be_less_than_due_date, if: proc { |m| m.start_date.present? && m.due_date.present? } validate :start_date_should_be_less_than_due_date, if: proc { |m| m.start_date.present? && m.due_date.present? }
validate :dates_within_4_digits validate :dates_within_4_digits
validates_associated :milestone_release, message: -> (_, obj) { obj[:value].errors.full_messages.join(",") } validates_associated :milestone_releases, message: -> (_, obj) { obj[:value].map(&:errors).map(&:full_messages).join(",") }
strip_attributes :title strip_attributes :title
......
...@@ -15,8 +15,8 @@ class Release < ApplicationRecord ...@@ -15,8 +15,8 @@ class Release < ApplicationRecord
# A one-to-one relationship is set up here as part of a MVC: https://gitlab.com/gitlab-org/gitlab-ce/issues/62402 # A one-to-one relationship is set up here as part of a MVC: https://gitlab.com/gitlab-org/gitlab-ce/issues/62402
# However, on the long term, we will want a many-to-many relationship between Release and Milestone. # However, on the long term, we will want a many-to-many relationship between Release and Milestone.
# The "has_one through" allows us today to set up this one-to-one relationship while setting up the architecture for the long-term (ie intermediate table). # The "has_one through" allows us today to set up this one-to-one relationship while setting up the architecture for the long-term (ie intermediate table).
has_one :milestone_release has_many :milestone_releases
has_one :milestone, through: :milestone_release has_many :milestones, through: :milestone_releases
default_value_for :released_at, allows_nil: false do default_value_for :released_at, allows_nil: false do
Time.zone.now Time.zone.now
...@@ -26,7 +26,7 @@ class Release < ApplicationRecord ...@@ -26,7 +26,7 @@ class Release < ApplicationRecord
validates :description, :project, :tag, presence: true validates :description, :project, :tag, presence: true
validates :name, presence: true, on: :create validates :name, presence: true, on: :create
validates_associated :milestone_release, message: -> (_, obj) { obj[:value].errors.full_messages.join(",") } validates_associated :milestone_releases, message: -> (_, obj) { obj[:value].map(&:errors).map(&:full_messages).join(",") }
scope :sorted, -> { order(released_at: :desc) } scope :sorted, -> { order(released_at: :desc) }
......
...@@ -55,20 +55,20 @@ describe Milestone do ...@@ -55,20 +55,20 @@ describe Milestone do
end end
end end
describe 'milestone_release' do describe 'milestone_releases' do
let(:milestone) { build(:milestone, project: project) } let(:milestone) { build(:milestone, project: project) }
context 'when it is tied to a release for another project' do context 'when it is tied to a release for another project' do
it 'creates a validation error' do it 'creates a validation error' do
other_project = create(:project) other_project = create(:project)
milestone.release = build(:release, project: other_project) milestone.releases << build(:release, project: other_project)
expect(milestone).not_to be_valid expect(milestone).not_to be_valid
end end
end end
context 'when it is tied to a release for the same project' do context 'when it is tied to a release for the same project' do
it 'is valid' do it 'is valid' do
milestone.release = build(:release, project: project) milestone.releases << build(:release, project: project)
expect(milestone).to be_valid expect(milestone).to be_valid
end end
end end
...@@ -78,7 +78,7 @@ describe Milestone do ...@@ -78,7 +78,7 @@ describe Milestone do
describe "Associations" do describe "Associations" do
it { is_expected.to belong_to(:project) } it { is_expected.to belong_to(:project) }
it { is_expected.to have_many(:issues) } it { is_expected.to have_many(:issues) }
it { is_expected.to have_one(:release) } it { is_expected.to have_many(:releases) }
end end
let(:project) { create(:project, :public) } let(:project) { create(:project, :public) }
......
...@@ -13,7 +13,7 @@ RSpec.describe Release do ...@@ -13,7 +13,7 @@ RSpec.describe Release do
it { is_expected.to belong_to(:project) } it { is_expected.to belong_to(:project) }
it { is_expected.to belong_to(:author).class_name('User') } it { is_expected.to belong_to(:author).class_name('User') }
it { is_expected.to have_many(:links).class_name('Releases::Link') } it { is_expected.to have_many(:links).class_name('Releases::Link') }
it { is_expected.to have_one(:milestone) } it { is_expected.to have_many(:milestones) }
end end
describe 'validation' do describe 'validation' do
...@@ -38,15 +38,15 @@ RSpec.describe Release do ...@@ -38,15 +38,15 @@ RSpec.describe Release do
context 'when a release is tied to a milestone for another project' do context 'when a release is tied to a milestone for another project' do
it 'creates a validation error' do it 'creates a validation error' do
release.milestone = build(:milestone, project: create(:project)) milestone = build(:milestone, project: create(:project))
expect(release).not_to be_valid expect { release.milestones << milestone }.to raise_error
end end
end end
context 'when a release is tied to a milestone linked to the same project' do context 'when a release is tied to a milestone linked to the same project' do
it 'is valid' do it 'successfully links this release to this milestone' do
release.milestone = build(:milestone, project: project) milestone = build(:milestone, project: project)
expect(release).to be_valid expect { release.milestones << milestone }.to change { MilestoneRelease.count }.by(1)
end end
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment