diff --git a/lib/strong_migrations.rb b/lib/strong_migrations.rb index 68c5d7df..7b1bc275 100644 --- a/lib/strong_migrations.rb +++ b/lib/strong_migrations.rb @@ -8,11 +8,12 @@ module StrongMigrations class << self - attr_accessor :auto_analyze, :start_after, :checks, :error_messages + attr_accessor :auto_analyze, :start_after, :checks, :error_messages, :ignored end self.auto_analyze = false self.start_after = 0 self.checks = [] + self.ignored = [] self.error_messages = { add_column_default: "Adding a column with a non-null default causes the entire table to be rewritten. @@ -39,6 +40,15 @@ def change end end", + add_column_default_null: + "Adding a column with a null default causes the entire table to be rewritten. +Instead, add the column without a default value. +class %{migration_name} < ActiveRecord::Migration%{migration_suffix} + def change + %{command} + end +end", + add_column_json: "There's no equality operator for the json column type, which causes issues for SELECT DISTINCT queries. Use jsonb instead.", diff --git a/lib/strong_migrations/migration.rb b/lib/strong_migrations/migration.rb index cc7b8639..97be0334 100644 --- a/lib/strong_migrations/migration.rb +++ b/lib/strong_migrations/migration.rb @@ -14,7 +14,7 @@ def migrate(direction) end def method_missing(method, *args, &block) - unless @safe || ENV["SAFETY_ASSURED"] || is_a?(ActiveRecord::Schema) || @direction == :down || version_safe? + unless @safe || ENV["SAFETY_ASSURED"] || is_a?(ActiveRecord::Schema) || @direction == :down || version_safe? || name_safe? ar5 = ActiveRecord::VERSION::MAJOR >= 5 case method @@ -64,7 +64,10 @@ def method_missing(method, *args, &block) options ||= {} default = options[:default] - if !default.nil? && !(postgresql? && postgresql_version >= 110000) + if options.key?(:default) && default.nil? && postgresql? + raise_error :add_column_default_null, + command: command_str("add_column", [table, column, type, options.except(:default)]) + elsif default && postgresql? raise_error :add_column_default, add_command: command_str("add_column", [table, column, type, options.except(:default)]), change_command: command_str("change_column_default", [table, column, default]), @@ -149,6 +152,10 @@ def version_safe? version && version <= StrongMigrations.start_after end + def name_safe? + version.nil? && name && StrongMigrations.ignored.include?(name) + end + def raise_error(message_key, header: nil, **vars) message = StrongMigrations.error_messages[message_key] || "Missing message" diff --git a/test/strong_migrations_test.rb b/test/strong_migrations_test.rb index 84ca2beb..6c6d2e24 100644 --- a/test/strong_migrations_test.rb +++ b/test/strong_migrations_test.rb @@ -46,6 +46,12 @@ def change end end +class AddColumnDefaultNull < TestMigration + def change + add_column :users, :nice, :boolean, default: nil + end +end + class AddColumnDefaultSafe < TestMigration def change add_column :users, :nice, :boolean @@ -251,6 +257,10 @@ def test_add_column_default assert_unsafe AddColumnDefault end + def test_add_column_default_null + assert_unsafe AddColumnDefaultNull + end + def test_add_column_default_safe assert_safe AddColumnDefaultSafe end