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/safely_change_column_default.rb')
-rw-r--r--app/models/concerns/safely_change_column_default.rb46
1 files changed, 46 insertions, 0 deletions
diff --git a/app/models/concerns/safely_change_column_default.rb b/app/models/concerns/safely_change_column_default.rb
new file mode 100644
index 00000000000..567f690d950
--- /dev/null
+++ b/app/models/concerns/safely_change_column_default.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+# == SafelyChangeColumnDefault concern.
+#
+# Contains functionality that allows safely changing a column default without downtime.
+# Without this concern, Rails can mutate the old default value to the new default value if the old default is explicitly
+# specified.
+#
+# Usage:
+#
+# class SomeModel < ApplicationRecord
+# include SafelyChangeColumnDefault
+#
+# columns_changing_default :value
+# end
+#
+# # Assume a default of 100 for value
+# SomeModel.create!(value: 100) # INSERT INTO some_model (value) VALUES (100)
+# change_column_default('some_model', 'value', from: 100, to: 101)
+# SomeModel.create!(value: 100) # INSERT INTO some_model (value) VALUES (100)
+# # Without this concern, would be INSERT INTO some_model (value) DEFAULT VALUES and would insert 101.
+module SafelyChangeColumnDefault
+ extend ActiveSupport::Concern
+
+ class_methods do
+ # Indicate that one or more columns will have their database default change.
+ #
+ # By indicating those columns here, this helper prevents a case where explicitly writing the old database default
+ # will be mutated to the new database default.
+ def columns_changing_default(*columns)
+ self.columns_with_changing_default = columns.map(&:to_s)
+ end
+ end
+
+ included do
+ class_attribute :columns_with_changing_default, default: []
+
+ before_create do
+ columns_with_changing_default.to_a.each do |attr_name|
+ attr = @attributes[attr_name]
+
+ attribute_will_change!(attr_name) if !attr.changed? && attr.came_from_user?
+ end
+ end
+ end
+end