From d2283aa1597a5588f2d4f10fe3982463ba63db2f Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 12 Sep 2016 19:13:56 -0300 Subject: Add service to create labels for a group/project --- app/controllers/groups/labels_controller.rb | 2 +- app/controllers/projects/labels_controller.rb | 2 +- app/models/label.rb | 2 +- app/services/labels/create_service.rb | 42 +++++++++++++++++++++ spec/models/label_spec.rb | 2 + spec/services/labels/create_service_spec.rb | 53 +++++++++++++++++++++++++++ 6 files changed, 100 insertions(+), 3 deletions(-) create mode 100644 app/services/labels/create_service.rb create mode 100644 spec/services/labels/create_service_spec.rb diff --git a/app/controllers/groups/labels_controller.rb b/app/controllers/groups/labels_controller.rb index 2e847d65df9..51605a9586c 100644 --- a/app/controllers/groups/labels_controller.rb +++ b/app/controllers/groups/labels_controller.rb @@ -15,7 +15,7 @@ class Groups::LabelsController < Groups::ApplicationController end def create - @label = @group.labels.create(label_params) + @label = Labels::CreateService.new(@group, current_user, label_params).execute if @label.valid? redirect_to group_labels_path(@group) diff --git a/app/controllers/projects/labels_controller.rb b/app/controllers/projects/labels_controller.rb index 28fa4a5b141..8d1935eff59 100644 --- a/app/controllers/projects/labels_controller.rb +++ b/app/controllers/projects/labels_controller.rb @@ -27,7 +27,7 @@ class Projects::LabelsController < Projects::ApplicationController end def create - @label = @project.labels.create(label_params) + @label = Labels::CreateService.new(@project, current_user, label_params).execute if @label.valid? redirect_to namespace_project_labels_path(@project.namespace, @project) diff --git a/app/models/label.rb b/app/models/label.rb index 9b5f0044544..53c7eb581aa 100644 --- a/app/models/label.rb +++ b/app/models/label.rb @@ -26,7 +26,7 @@ class Label < ActiveRecord::Base validates :title, presence: true, format: { with: /\A[^,]+\z/ }, - uniqueness: { scope: :subject_id } + uniqueness: { scope: [:subject_id, :subject_type] } before_save :nullify_priority diff --git a/app/services/labels/create_service.rb b/app/services/labels/create_service.rb new file mode 100644 index 00000000000..1462d07326e --- /dev/null +++ b/app/services/labels/create_service.rb @@ -0,0 +1,42 @@ +module Labels + class CreateService + def initialize(subject, user, params = {}) + @subject, @user, @params = subject, user, params.dup + end + + def execute + label = subject.labels.build(params) + + return label if subject.is_a?(Project) && subject.group.present? && subject.group.labels.where(title: title).exists? + + if label.save + if subject.is_a?(Group) + subject.projects.each do |project| + project.labels.find_or_create_by!(title: title) do |label| + label.color = color + label.description = description + end + end + end + end + + label + end + + private + + attr_reader :subject, :user, :params + + def title + params[:title] + end + + def color + params[:color] + end + + def description + params[:description] + end + end +end diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb index a8bd01e1a73..80b963c9433 100644 --- a/spec/models/label_spec.rb +++ b/spec/models/label_spec.rb @@ -43,6 +43,8 @@ describe Label, models: true do expect(label).to allow_value('G&ITLAB').for(:title) expect(label).to allow_value("customer's request").for(:title) end + + it { is_expected.to validate_uniqueness_of(:title).scoped_to([:subject_id, :subject_type]) } end describe '#title' do diff --git a/spec/services/labels/create_service_spec.rb b/spec/services/labels/create_service_spec.rb new file mode 100644 index 00000000000..b06424bcde4 --- /dev/null +++ b/spec/services/labels/create_service_spec.rb @@ -0,0 +1,53 @@ +require 'spec_helper' + +describe Labels::CreateService, services: true do + describe '#execute' do + let(:group) { create(:group) } + let!(:project) { create(:empty_project, group: group) } + + let(:params) do + { + title: 'Security', + color: '#5CB85C', + description: 'Security related stuff.' + } + end + + context 'with a group as subject' do + subject(:service) { described_class.new(group, double, params) } + + it 'creates a label' do + expect { service.execute }.to change(group.labels, :count).by(1) + end + + it 'becames available to all already existing projects of the group' do + service.execute + + expect(project.labels.where(params)).not_to be_empty + end + + it 'does not overwrite label that already exists in the project' do + params = { title: 'Security', color: '#FF0000', description: 'Sample' } + project.labels.create(params) + + service.execute + + expect(project.labels.where(params)).not_to be_empty + end + end + + context 'with a project as subject' do + subject(:service) { described_class.new(project, double, params) } + + it 'creates a label' do + expect { service.execute }.to change(project.labels, :count).by(1) + end + + it 'does not create a label that already exists on the group level' do + group.labels.create(params) + + expect { service.execute }.not_to change(project.labels, :count) + end + end + end +end -- cgit v1.2.1