summaryrefslogtreecommitdiff
path: root/app/models/concerns
diff options
context:
space:
mode:
Diffstat (limited to 'app/models/concerns')
-rw-r--r--app/models/concerns/issuable.rb28
-rw-r--r--app/models/concerns/issuable_states.rb22
-rw-r--r--app/models/concerns/milestoneish.rb6
-rw-r--r--app/models/concerns/versioned_description.rb31
-rw-r--r--app/models/concerns/worker_attributes.rb48
5 files changed, 117 insertions, 18 deletions
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index 94a0de556f4..852576dbbc2 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -25,12 +25,20 @@ module Issuable
include UpdatedAtFilterable
include IssuableStates
include ClosedAtFilterable
+ include VersionedDescription
TITLE_LENGTH_MAX = 255
TITLE_HTML_LENGTH_MAX = 800
DESCRIPTION_LENGTH_MAX = 1.megabyte
DESCRIPTION_HTML_LENGTH_MAX = 5.megabytes
+ STATE_ID_MAP = {
+ opened: 1,
+ closed: 2,
+ merged: 3,
+ locked: 4
+ }.with_indifferent_access.freeze
+
# This object is used to gather issuable meta data for displaying
# upvotes, downvotes, notes and closing merge requests count for issues and merge requests
# lists avoiding n+1 queries and improving performance.
@@ -172,13 +180,17 @@ module Issuable
fuzzy_search(query, [:title])
end
- # Available state values persisted in state_id column using state machine
+ def available_states
+ @available_states ||= STATE_ID_MAP.slice(*available_state_names)
+ end
+
+ # Available state names used to persist state_id column using state machine
#
# Override this on subclasses if different states are needed
#
- # Check MergeRequest.available_states for example
- def available_states
- @available_states ||= { opened: 1, closed: 2 }.with_indifferent_access
+ # Check MergeRequest.available_states_names for example
+ def available_state_names
+ [:opened, :closed]
end
# Searches for records with a matching title or description.
@@ -297,6 +309,14 @@ module Issuable
end
end
+ def state
+ self.class.available_states.key(state_id)
+ end
+
+ def state=(value)
+ self.state_id = self.class.available_states[value]
+ end
+
def resource_parent
project
end
diff --git a/app/models/concerns/issuable_states.rb b/app/models/concerns/issuable_states.rb
index 33bc41d7f44..f0b9f0d1f3a 100644
--- a/app/models/concerns/issuable_states.rb
+++ b/app/models/concerns/issuable_states.rb
@@ -4,22 +4,20 @@ module IssuableStates
extend ActiveSupport::Concern
# The state:string column is being migrated to state_id:integer column
- # This is a temporary hook to populate state_id column with new values
- # and should be removed after the state column is removed.
- # Check https://gitlab.com/gitlab-org/gitlab-foss/issues/51789 for more information
+ # This is a temporary hook to keep state column in sync until it is removed.
+ # Check https: https://gitlab.com/gitlab-org/gitlab/issues/33814 for more information
+ # The state column can be safely removed after 2019-10-27
included do
- before_save :set_state_id
+ before_save :sync_issuable_deprecated_state
end
- def set_state_id
- return if state.nil? || state.empty?
+ def sync_issuable_deprecated_state
+ return if self.is_a?(Epic)
+ return unless respond_to?(:state)
+ return if state_id.nil?
- # Needed to prevent breaking some migration specs that
- # rollback database to a point where state_id does not exist.
- # We can use this guard clause for now since this file will
- # be removed in the next release.
- return unless self.has_attribute?(:state_id)
+ deprecated_state = self.class.available_states.key(state_id)
- self.state_id = self.class.available_states[state]
+ self.write_attribute(:state, deprecated_state)
end
end
diff --git a/app/models/concerns/milestoneish.rb b/app/models/concerns/milestoneish.rb
index 3deb86da6cf..42b370990ac 100644
--- a/app/models/concerns/milestoneish.rb
+++ b/app/models/concerns/milestoneish.rb
@@ -6,7 +6,9 @@ module Milestoneish
end
def closed_issues_count(user)
- count_issues_by_state(user)['closed'].to_i
+ closed_state_id = Issue.available_states[:closed]
+
+ count_issues_by_state(user)[closed_state_id].to_i
end
def complete?(user)
@@ -117,7 +119,7 @@ module Milestoneish
def count_issues_by_state(user)
memoize_per_user(user, :count_issues_by_state) do
- issues_visible_to_user(user).reorder(nil).group(:state).count
+ issues_visible_to_user(user).reorder(nil).group(:state_id).count
end
end
diff --git a/app/models/concerns/versioned_description.rb b/app/models/concerns/versioned_description.rb
new file mode 100644
index 00000000000..63a24aadc8a
--- /dev/null
+++ b/app/models/concerns/versioned_description.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module VersionedDescription
+ extend ActiveSupport::Concern
+
+ included do
+ attr_accessor :saved_description_version
+
+ has_many :description_versions
+
+ after_update :save_description_version
+ end
+
+ private
+
+ def save_description_version
+ self.saved_description_version = nil
+
+ return unless Feature.enabled?(:save_description_versions, issuing_parent)
+ return unless saved_change_to_description?
+
+ unless description_versions.exists?
+ description_versions.create!(
+ description: description_before_last_save,
+ created_at: created_at
+ )
+ end
+
+ self.saved_description_version = description_versions.create!(description: description)
+ end
+end
diff --git a/app/models/concerns/worker_attributes.rb b/app/models/concerns/worker_attributes.rb
new file mode 100644
index 00000000000..af40e9e3b19
--- /dev/null
+++ b/app/models/concerns/worker_attributes.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module WorkerAttributes
+ extend ActiveSupport::Concern
+
+ class_methods do
+ def feature_category(value)
+ raise "Invalid category. Use `feature_category_not_owned!` to mark a worker as not owned" if value == :not_owned
+
+ worker_attributes[:feature_category] = value
+ end
+
+ # Special case: mark this work as not associated with a feature category
+ # this should be used for cross-cutting concerns, such as mailer workers.
+ def feature_category_not_owned!
+ worker_attributes[:feature_category] = :not_owned
+ end
+
+ def get_feature_category
+ get_worker_attribute(:feature_category)
+ end
+
+ def feature_category_not_owned?
+ get_worker_attribute(:feature_category) == :not_owned
+ end
+
+ protected
+
+ # Returns a worker attribute declared on this class or its parent class.
+ # This approach allows declared attributes to be inherited by
+ # child classes.
+ def get_worker_attribute(name)
+ worker_attributes[name] || superclass_worker_attributes(name)
+ end
+
+ private
+
+ def worker_attributes
+ @attributes ||= {}
+ end
+
+ def superclass_worker_attributes(name)
+ return unless superclass.include? WorkerAttributes
+
+ superclass.get_worker_attribute(name)
+ end
+ end
+end