Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/models/concerns/issuable_link.rb')
-rw-r--r--app/models/concerns/issuable_link.rb55
1 files changed, 55 insertions, 0 deletions
diff --git a/app/models/concerns/issuable_link.rb b/app/models/concerns/issuable_link.rb
new file mode 100644
index 00000000000..3e14507bc70
--- /dev/null
+++ b/app/models/concerns/issuable_link.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+# == IssuableLink concern
+#
+# Contains common functionality shared between related Issues and related Epics
+#
+# Used by IssueLink, Epic::RelatedEpicLink
+#
+module IssuableLink
+ extend ActiveSupport::Concern
+
+ TYPE_RELATES_TO = 'relates_to'
+ TYPE_BLOCKS = 'blocks' ## EE-only. Kept here to be used on link_type enum.
+
+ class_methods do
+ def inverse_link_type(type)
+ type
+ end
+
+ def issuable_type
+ raise NotImplementedError
+ end
+ end
+
+ included do
+ validates :source, presence: true
+ validates :target, presence: true
+ validates :source, uniqueness: { scope: :target_id, message: 'is already related' }
+ validate :check_self_relation
+ validate :check_opposite_relation
+
+ enum link_type: { TYPE_RELATES_TO => 0, TYPE_BLOCKS => 1 }
+
+ private
+
+ def check_self_relation
+ return unless source && target
+
+ if source == target
+ errors.add(:source, 'cannot be related to itself')
+ end
+ end
+
+ def check_opposite_relation
+ return unless source && target
+
+ if self.class.base_class.find_by(source: target, target: source)
+ errors.add(:source, "is already related to this #{self.class.issuable_type}")
+ end
+ end
+ end
+end
+
+IssuableLink.prepend_mod_with('IssuableLink')
+IssuableLink::ClassMethods.prepend_mod_with('IssuableLink::ClassMethods')