diff options
-rw-r--r-- | app/models/label.rb | 16 | ||||
-rw-r--r-- | app/models/project.rb | 4 | ||||
-rw-r--r-- | db/migrate/20160902152513_change_project_to_polymorphic_relationship_on_labels.rb | 20 | ||||
-rw-r--r-- | db/schema.rb | 8 | ||||
-rw-r--r-- | spec/factories/labels.rb | 2 | ||||
-rw-r--r-- | spec/models/concerns/issuable_spec.rb | 8 | ||||
-rw-r--r-- | spec/models/label_spec.rb | 8 |
7 files changed, 48 insertions, 18 deletions
diff --git a/app/models/label.rb b/app/models/label.rb index a23140b7d64..1a0ad02567b 100644 --- a/app/models/label.rb +++ b/app/models/label.rb @@ -12,7 +12,7 @@ class Label < ActiveRecord::Base default_value_for :color, DEFAULT_COLOR - belongs_to :project + belongs_to :subject, polymorphic: true has_many :lists, dependent: :destroy has_many :label_links, dependent: :destroy @@ -20,13 +20,13 @@ class Label < ActiveRecord::Base has_many :merge_requests, through: :label_links, source: :target, source_type: 'MergeRequest' validates :color, color: true, allow_blank: false - validates :project, presence: true, unless: Proc.new { |service| service.template? } + validates :subject, presence: true, unless: Proc.new { |service| service.template? } # Don't allow ',' for label titles validates :title, presence: true, format: { with: /\A[^,]+\z/ }, - uniqueness: { scope: :project_id } + uniqueness: { scope: :subject_id } before_save :nullify_priority @@ -92,7 +92,7 @@ class Label < ActiveRecord::Base reference = "#{self.class.reference_prefix}#{format_reference}" if cross_project_reference?(from_project) - project.to_reference + reference + subject.to_reference + reference else reference end @@ -124,6 +124,14 @@ class Label < ActiveRecord::Base private + def cross_project_reference?(from_project) + if self.is_a?(Project) + self != from_project + else + from_project && self.subject && self.subject != from_project + end + end + def label_format_reference(format = :id) raise StandardError, 'Unknown format' unless [:id, :name].include?(format) diff --git a/app/models/project.rb b/app/models/project.rb index 8b5a6f167bd..57b5e4f5973 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -101,7 +101,7 @@ class Project < ActiveRecord::Base # Merge requests from source project should be kept when source project was removed has_many :fork_merge_requests, foreign_key: 'source_project_id', class_name: MergeRequest has_many :issues, dependent: :destroy - has_many :labels, dependent: :destroy + has_many :labels, dependent: :destroy, as: :subject has_many :services, dependent: :destroy has_many :events, dependent: :destroy has_many :milestones, dependent: :destroy @@ -733,7 +733,7 @@ class Project < ActiveRecord::Base Label.templates.each do |label| label = label.dup label.template = nil - label.project_id = self.id + label.subject = self label.save end end diff --git a/db/migrate/20160902152513_change_project_to_polymorphic_relationship_on_labels.rb b/db/migrate/20160902152513_change_project_to_polymorphic_relationship_on_labels.rb new file mode 100644 index 00000000000..a2963109177 --- /dev/null +++ b/db/migrate/20160902152513_change_project_to_polymorphic_relationship_on_labels.rb @@ -0,0 +1,20 @@ +class ChangeProjectToPolymorphicRelationshipOnLabels < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = true + DOWNTIME_REASON = 'This migration renames an existing column' + + disable_ddl_transaction! + + def up + rename_column :labels, :project_id, :subject_id + add_column :labels, :subject_type, :string + update_column_in_batches :labels, :subject_type, 'Project' + add_concurrent_index :labels, :subject_type + end + + def down + rename_column :labels, :subject_id, :project_id + remove_column :labels, :subject_type + end +end diff --git a/db/schema.rb b/db/schema.rb index 974f5855cf9..8c30faa8df3 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -497,16 +497,18 @@ ActiveRecord::Schema.define(version: 20160913212128) do create_table "labels", force: :cascade do |t| t.string "title" t.string "color" - t.integer "project_id" + t.integer "subject_id" t.datetime "created_at" t.datetime "updated_at" - t.boolean "template", default: false + t.boolean "template", default: false t.string "description" t.integer "priority" + t.string "subject_type" end add_index "labels", ["priority"], name: "index_labels_on_priority", using: :btree - add_index "labels", ["project_id"], name: "index_labels_on_project_id", using: :btree + add_index "labels", ["subject_id"], name: "index_labels_on_subject_id", using: :btree + add_index "labels", ["subject_type"], name: "index_labels_on_subject_type", using: :btree create_table "lfs_objects", force: :cascade do |t| t.string "oid", null: false diff --git a/spec/factories/labels.rb b/spec/factories/labels.rb index eb489099854..942080b8644 100644 --- a/spec/factories/labels.rb +++ b/spec/factories/labels.rb @@ -2,6 +2,6 @@ FactoryGirl.define do factory :label do sequence(:title) { |n| "label#{n}" } color "#990000" - project + subject factory: :project end end diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb index 60e4bbc8564..bd1144b2c20 100644 --- a/spec/models/concerns/issuable_spec.rb +++ b/spec/models/concerns/issuable_spec.rb @@ -256,7 +256,7 @@ describe Issue, "Issuable" do describe '#labels_array' do let(:project) { create(:project) } - let(:bug) { create(:label, project: project, title: 'bug') } + let(:bug) { create(:label, subject: project, title: 'bug') } let(:issue) { create(:issue, project: project) } before(:each) do @@ -300,9 +300,9 @@ describe Issue, "Issuable" do describe ".with_label" do let(:project) { create(:project, :public) } - let(:bug) { create(:label, project: project, title: 'bug') } - let(:feature) { create(:label, project: project, title: 'feature') } - let(:enhancement) { create(:label, project: project, title: 'enhancement') } + let(:bug) { create(:label, subject: project, title: 'bug') } + let(:feature) { create(:label, subject: project, title: 'feature') } + let(:enhancement) { create(:label, subject: project, title: 'enhancement') } let(:issue1) { create(:issue, title: "Bugfix1", project: project) } let(:issue2) { create(:issue, title: "Bugfix2", project: project) } let(:issue3) { create(:issue, title: "Feature1", project: project) } diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb index 5a5d1a5d60c..bdd75cc760e 100644 --- a/spec/models/label_spec.rb +++ b/spec/models/label_spec.rb @@ -4,7 +4,7 @@ describe Label, models: true do let(:label) { create(:label) } describe 'associations' do - it { is_expected.to belong_to(:project) } + it { is_expected.to belong_to(:subject) } it { is_expected.to have_many(:label_links).dependent(:destroy) } it { is_expected.to have_many(:issues).through(:label_links).source(:target) } @@ -18,7 +18,7 @@ describe Label, models: true do end describe 'validation' do - it { is_expected.to validate_presence_of(:project) } + it { is_expected.to validate_presence_of(:subject) } it 'validates color code' do expect(label).not_to allow_value('G-ITLAB').for(:color) @@ -82,14 +82,14 @@ describe Label, models: true do context 'using name' do it 'returns cross reference with label name' do expect(label.to_reference(project, format: :name)) - .to eq %Q(#{label.project.to_reference}~"#{label.name}") + .to eq %Q(#{label.subject.to_reference}~"#{label.name}") end end context 'using id' do it 'returns cross reference with label id' do expect(label.to_reference(project, format: :id)) - .to eq %Q(#{label.project.to_reference}~#{label.id}) + .to eq %Q(#{label.subject.to_reference}~#{label.id}) end end end |