diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ef437e4..c9fdc0f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.7.9 (2021-09-22) + +- Added `enabled_tables` option + ## 0.7.8 (2021-08-03) - Fixed issue with `add_reference ..., foreign_key: {to_table: ...}` with `safe_by_default` diff --git a/lib/generators/strong_migrations/templates/initializer.rb.tt b/lib/generators/strong_migrations/templates/initializer.rb.tt index c2e7b3d4..14ed72e7 100644 --- a/lib/generators/strong_migrations/templates/initializer.rb.tt +++ b/lib/generators/strong_migrations/templates/initializer.rb.tt @@ -23,3 +23,6 @@ StrongMigrations.auto_analyze = true # Make some operations safe by default # See https://github.com/ankane/strong_migrations#safe-by-default # StrongMigrations.safe_by_default = true<% end %> + +# Add special tables for checker +# StrongMigrations.enabled_tables = %i[] diff --git a/lib/strong_migrations.rb b/lib/strong_migrations.rb index c203f1b5..2643446e 100644 --- a/lib/strong_migrations.rb +++ b/lib/strong_migrations.rb @@ -19,12 +19,13 @@ class << self attr_accessor :auto_analyze, :start_after, :checks, :error_messages, :target_postgresql_version, :target_mysql_version, :target_mariadb_version, :enabled_checks, :lock_timeout, :statement_timeout, :check_down, :target_version, - :safe_by_default + :safe_by_default, :enabled_tables attr_writer :lock_timeout_limit end self.auto_analyze = false self.start_after = 0 self.checks = [] + self.enabled_tables = [] self.safe_by_default = false self.error_messages = { add_column_default: @@ -269,8 +270,8 @@ def self.disable_check(check) enabled_checks.delete(check) end - def self.check_enabled?(check, version: nil) - if enabled_checks[check] + def self.check_enabled?(check, version: nil, table: nil) + if enabled_checks[check] && (enabled_tables.include?(table) || check == :execute) start_after = enabled_checks[check][:start_after] || StrongMigrations.start_after !version || version > start_after else diff --git a/lib/strong_migrations/checker.rb b/lib/strong_migrations/checker.rb index 09bfcb2f..3820482f 100644 --- a/lib/strong_migrations/checker.rb +++ b/lib/strong_migrations/checker.rb @@ -52,23 +52,26 @@ def perform(method, *args) model: args[0].to_s.classify, code: code, command: command_str(method, args), - column_suffix: columns.size > 1 ? "s" : "" + column_suffix: columns.size > 1 ? "s" : "", + table: args[0] when :change_table - raise_error :change_table, header: "Possibly dangerous operation" + raise_error :change_table, header: "Possibly dangerous operation", table: args[0] when :rename_table - raise_error :rename_table + raise_error :rename_table, table: args[0] when :rename_column - raise_error :rename_column + raise_error :rename_column, table: args[0] when :add_index table, columns, options = args options ||= {} if columns.is_a?(Array) && columns.size > 3 && !options[:unique] - raise_error :add_index_columns, header: "Best practice" + raise_error :add_index_columns, header: "Best practice", table: table end if postgresql? && options[:algorithm] != :concurrently && !new_table?(table) return safe_add_index(table, columns, options) if StrongMigrations.safe_by_default - raise_error :add_index, command: command_str("add_index", [table, columns, options.merge(algorithm: :concurrently)]) + raise_error :add_index, + command: command_str("add_index", [table, columns, options.merge(algorithm: :concurrently)]), + table: table end when :remove_index table, options = args @@ -79,7 +82,9 @@ def perform(method, *args) if postgresql? && options[:algorithm] != :concurrently && !new_table?(table) return safe_remove_index(table, options) if StrongMigrations.safe_by_default - raise_error :remove_index, command: command_str("remove_index", [table, options.merge(algorithm: :concurrently)]) + raise_error :remove_index, + command: command_str("remove_index", [table, options.merge(algorithm: :concurrently)]), + table: table end when :add_column table, column, type, options = args @@ -101,12 +106,14 @@ def perform(method, *args) remove_command: command_str("remove_column", [table, column]), code: backfill_code(table, column, default), append: append, - rewrite_blocks: rewrite_blocks + rewrite_blocks: rewrite_blocks, + table: table end if type.to_s == "json" && postgresql? raise_error :add_column_json, - command: command_str("add_column", [table, column, :jsonb, options]) + command: command_str("add_column", [table, column, :jsonb, options]), + table: table end when :change_column table, column, type, options = args @@ -166,15 +173,15 @@ def perform(method, *args) # unsafe to set NOT NULL for safe types if safe && existing_column.null && options[:null] == false - raise_error :change_column_with_not_null + raise_error :change_column_with_not_null, table: table end - raise_error :change_column, rewrite_blocks: rewrite_blocks unless safe + raise_error :change_column, rewrite_blocks: rewrite_blocks, table: table unless safe when :create_table table, options = args options ||= {} - raise_error :create_table if options[:force] + raise_error :create_table, table: table if options[:force] # keep track of new tables of add_index check @new_tables << table.to_s @@ -208,7 +215,8 @@ def perform(method, *args) raise_error :add_reference, headline: headline, command: command_str(method, [table, reference, options]), - append: append + append: append, + table: table end end when :execute @@ -262,13 +270,14 @@ def perform(method, *args) raise_error :change_column_null_postgresql, add_constraint_code: add_constraint_code, - validate_constraint_code: validate_constraint_code + validate_constraint_code: validate_constraint_code, + table: table end elsif mysql? || mariadb? - raise_error :change_column_null_mysql + raise_error :change_column_null_mysql, table: table elsif !default.nil? raise_error :change_column_null, - code: backfill_code(table, column, default) + code: backfill_code(table, column, default), table: table end end when :add_foreign_key @@ -293,18 +302,20 @@ def perform(method, *args) raise_error :add_foreign_key, add_foreign_key_code: safety_assured_str(add_code), - validate_foreign_key_code: safety_assured_str(validate_code) + validate_foreign_key_code: safety_assured_str(validate_code), + table: from_table else return safe_add_foreign_key(from_table, to_table, options) if StrongMigrations.safe_by_default raise_error :add_foreign_key, add_foreign_key_code: command_str("add_foreign_key", [from_table, to_table, options.merge(validate: false)]), - validate_foreign_key_code: command_str("validate_foreign_key", [from_table, to_table]) + validate_foreign_key_code: command_str("validate_foreign_key", [from_table, to_table]), + table: from_table end end when :validate_foreign_key if postgresql? && writes_blocked? - raise_error :validate_foreign_key + raise_error :validate_foreign_key, table: args[0] end when :add_check_constraint table, expression, options = args @@ -320,14 +331,15 @@ def perform(method, *args) raise_error :add_check_constraint, add_check_constraint_code: command_str("add_check_constraint", [table, expression, add_options]), - validate_check_constraint_code: command_str("validate_check_constraint", [table, validate_options]) + validate_check_constraint_code: command_str("validate_check_constraint", [table, validate_options]), + table: table elsif mysql? || mariadb? - raise_error :add_check_constraint_mysql + raise_error :add_check_constraint_mysql, table: table end end when :validate_check_constraint if postgresql? && writes_blocked? - raise_error :validate_check_constraint + raise_error :validate_check_constraint, table: args[0] end end @@ -527,7 +539,7 @@ def constraints(table_name) end def raise_error(message_key, header: nil, append: nil, **vars) - return unless StrongMigrations.check_enabled?(message_key, version: version) + return unless StrongMigrations.check_enabled?(message_key, version: version, table: vars[:table]&.to_sym) message = StrongMigrations.error_messages[message_key] || "Missing message" message = message + append if append diff --git a/lib/strong_migrations/version.rb b/lib/strong_migrations/version.rb index 8ed36f82..f9ec9805 100644 --- a/lib/strong_migrations/version.rb +++ b/lib/strong_migrations/version.rb @@ -1,3 +1,3 @@ module StrongMigrations - VERSION = "0.7.8" + VERSION = "0.7.9" end diff --git a/test/add_check_constraint_test.rb b/test/add_check_constraint_test.rb index c7d258b8..f5a719e6 100644 --- a/test/add_check_constraint_test.rb +++ b/test/add_check_constraint_test.rb @@ -6,6 +6,12 @@ def setup super end + def test_add_check_constraint_without_enabled_tables + without_enabled_tables do + assert_safe AddCheckConstraint + end + end + def test_add_check_constraint assert_unsafe AddCheckConstraint end diff --git a/test/add_column_default_test.rb b/test/add_column_default_test.rb index 7eef8d69..cf375370 100644 --- a/test/add_column_default_test.rb +++ b/test/add_column_default_test.rb @@ -1,6 +1,12 @@ require_relative "test_helper" class AddColumnDefaultTest < Minitest::Test + def test_add_column_default_without_enabled_tables + without_enabled_tables do + assert_safe AddColumnDefault + end + end + def test_add_column_default with_target_version(postgresql? ? 10 : (mysql? ? "8.0.11" : "10.3.1")) do assert_unsafe AddColumnDefault diff --git a/test/add_foreign_key_test.rb b/test/add_foreign_key_test.rb index e06d10f2..a627cdf6 100644 --- a/test/add_foreign_key_test.rb +++ b/test/add_foreign_key_test.rb @@ -1,6 +1,12 @@ require_relative "test_helper" class AddForeignKeyTest < Minitest::Test + def test_add_foreign_key_without_enabled_tables + without_enabled_tables do + assert_safe AddForeignKey + end + end + def test_add_foreign_key if postgresql? assert_unsafe AddForeignKey diff --git a/test/add_index_test.rb b/test/add_index_test.rb index cb182c8e..2d4510d4 100644 --- a/test/add_index_test.rb +++ b/test/add_index_test.rb @@ -1,6 +1,12 @@ require_relative "test_helper" class AddIndexTest < Minitest::Test + def test_add_index_without_enabled_tables + without_enabled_tables do + assert_safe AddIndex + end + end + def test_add_index if postgresql? assert_unsafe AddIndex, <<~EOF diff --git a/test/add_reference_test.rb b/test/add_reference_test.rb index 40634b77..0b73378e 100644 --- a/test/add_reference_test.rb +++ b/test/add_reference_test.rb @@ -1,6 +1,12 @@ require_relative "test_helper" class AddReferenceTest < Minitest::Test + def test_add_reference_without_enabled_tables + without_enabled_tables do + assert_safe AddReference + end + end + def test_add_reference skip unless postgresql? assert_unsafe AddReference diff --git a/test/change_column_null_test.rb b/test/change_column_null_test.rb index 61ddf8ea..cde4c0eb 100644 --- a/test/change_column_null_test.rb +++ b/test/change_column_null_test.rb @@ -1,6 +1,12 @@ require_relative "test_helper" class ChangeColumnNullTest < Minitest::Test + def test_change_column_null_without_enabled_tables + without_enabled_tables do + assert_safe ChangeColumnNull + end + end + def test_change_column_null if postgresql? || mysql? || mariadb? assert_unsafe ChangeColumnNull diff --git a/test/remove_column_test.rb b/test/remove_column_test.rb index 07d14525..def53031 100644 --- a/test/remove_column_test.rb +++ b/test/remove_column_test.rb @@ -1,6 +1,12 @@ require_relative "test_helper" class RemoveColumnTest < Minitest::Test + def test_remove_column_without_enabled_tables + without_enabled_tables do + assert_safe RemoveColumn + end + end + def test_remove_column assert_unsafe RemoveColumn end diff --git a/test/remove_index_test.rb b/test/remove_index_test.rb index d6903ea1..604c7005 100644 --- a/test/remove_index_test.rb +++ b/test/remove_index_test.rb @@ -1,6 +1,19 @@ require_relative "test_helper" class RemoveIndexTest < Minitest::Test + def test_remove_index_concurrently_without_enabled_tables + skip unless postgresql? + migrate AddIndexConcurrently + + without_enabled_tables do + StrongMigrations.enable_check(:remove_index) + assert_safe RemoveIndex + migrate RemoveIndexConcurrently + ensure + StrongMigrations.disable_check(:remove_index) + end + end + def test_remove_index_concurrently skip unless postgresql? migrate AddIndexConcurrently diff --git a/test/test_helper.rb b/test/test_helper.rb index e05039d8..252b2e15 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -99,11 +99,20 @@ def with_target_version(version) StrongMigrations.target_version = nil end + def without_enabled_tables + StrongMigrations.enabled_tables = %i[] + yield + ensure + StrongMigrations.enabled_tables = %i[users] + end + def check_constraints? ActiveRecord::VERSION::STRING >= "6.1" end end +StrongMigrations.enabled_tables = %i[users] + StrongMigrations.add_check do |method, args| if method == :add_column && args[1].to_s == "forbidden" stop! "Cannot add forbidden column"