Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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`
Expand Down
3 changes: 3 additions & 0 deletions lib/generators/strong_migrations/templates/initializer.rb.tt
Original file line number Diff line number Diff line change
Expand Up @@ -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[]
7 changes: 4 additions & 3 deletions lib/strong_migrations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down
58 changes: 35 additions & 23 deletions lib/strong_migrations/checker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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

Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion lib/strong_migrations/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module StrongMigrations
VERSION = "0.7.8"
VERSION = "0.7.9"
end
6 changes: 6 additions & 0 deletions test/add_check_constraint_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions test/add_column_default_test.rb
Original file line number Diff line number Diff line change
@@ -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
Expand Down
6 changes: 6 additions & 0 deletions test/add_foreign_key_test.rb
Original file line number Diff line number Diff line change
@@ -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
Expand Down
6 changes: 6 additions & 0 deletions test/add_index_test.rb
Original file line number Diff line number Diff line change
@@ -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
Expand Down
6 changes: 6 additions & 0 deletions test/add_reference_test.rb
Original file line number Diff line number Diff line change
@@ -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
Expand Down
6 changes: 6 additions & 0 deletions test/change_column_null_test.rb
Original file line number Diff line number Diff line change
@@ -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
Expand Down
6 changes: 6 additions & 0 deletions test/remove_column_test.rb
Original file line number Diff line number Diff line change
@@ -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
Expand Down
13 changes: 13 additions & 0 deletions test/remove_index_test.rb
Original file line number Diff line number Diff line change
@@ -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
Expand Down
9 changes: 9 additions & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down