debian-mirror-gitlab/app/models/concerns/safely_change_column_default.rb
2023-03-17 16:20:25 +05:30

46 lines
1.5 KiB
Ruby

# 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