76 lines
3.4 KiB
Ruby
76 lines
3.4 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Gitlab
|
|
module Database
|
|
module MigrationHelpers
|
|
module CascadingNamespaceSettings
|
|
include Gitlab::Database::MigrationHelpers
|
|
|
|
# Creates the four required columns that constitutes a single cascading
|
|
# namespace settings attribute. This helper is only appropriate if the
|
|
# setting is not already present as a non-cascading attribute.
|
|
#
|
|
# Creates the `setting_name` column along with the `lock_setting_name`
|
|
# column in both `namespace_settings` and `application_settings`.
|
|
#
|
|
# This helper is not reversible and must be defined in conjunction with
|
|
# `remove_cascading_namespace_setting` in separate up and down directions.
|
|
#
|
|
# setting_name - The name of the cascading attribute - same as defined
|
|
# in `NamespaceSetting` with the `cascading_attr` method.
|
|
# type - The column type for the setting itself (:boolean, :integer, etc.)
|
|
# options - Standard Rails column options hash. Accepts keys such as
|
|
# `null` and `default`.
|
|
#
|
|
# `null` and `default` options will only be applied to the `application_settings`
|
|
# column. In most cases, a non-null default value should be specified.
|
|
def add_cascading_namespace_setting(setting_name, type, **options)
|
|
lock_column_name = "lock_#{setting_name}".to_sym
|
|
|
|
check_cascading_namespace_setting_consistency(setting_name, lock_column_name)
|
|
|
|
namespace_options = options.merge(null: true, default: nil)
|
|
|
|
with_lock_retries do
|
|
add_column(:namespace_settings, setting_name, type, namespace_options)
|
|
add_column(:namespace_settings, lock_column_name, :boolean, default: false, null: false)
|
|
end
|
|
|
|
add_column(:application_settings, setting_name, type, options)
|
|
add_column(:application_settings, lock_column_name, :boolean, default: false, null: false)
|
|
end
|
|
|
|
def remove_cascading_namespace_setting(setting_name)
|
|
lock_column_name = "lock_#{setting_name}".to_sym
|
|
|
|
with_lock_retries do
|
|
remove_column(:namespace_settings, setting_name) if column_exists?(:namespace_settings, setting_name)
|
|
remove_column(:namespace_settings, lock_column_name) if column_exists?(:namespace_settings, lock_column_name)
|
|
end
|
|
|
|
remove_column(:application_settings, setting_name) if column_exists?(:application_settings, setting_name)
|
|
remove_column(:application_settings, lock_column_name) if column_exists?(:application_settings, lock_column_name)
|
|
end
|
|
|
|
private
|
|
|
|
def check_cascading_namespace_setting_consistency(setting_name, lock_name)
|
|
existing_columns = []
|
|
|
|
%w(namespace_settings application_settings).each do |table|
|
|
existing_columns << "#{table}.#{setting_name}" if column_exists?(table.to_sym, setting_name)
|
|
existing_columns << "#{table}.#{lock_name}" if column_exists?(table.to_sym, lock_name)
|
|
end
|
|
|
|
return if existing_columns.empty?
|
|
|
|
raise <<~ERROR
|
|
One or more cascading namespace columns already exist. `add_cascading_namespace_setting` helper
|
|
can only be used for new settings, when none of the required columns already exist.
|
|
Existing columns: #{existing_columns.join(', ')}
|
|
ERROR
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|