discourse/spec/components/migration/table_dropper_spec.rb
Sam 6a3c8fe69c FEATURE: protect against accidental column or table drops
Often we need to amend our schema, it is tempting to use
drop_table, rename_column and drop_column to amned schema
trouble though is that existing code that is running in production
can depend on the existance of previous schema leading to application
breaking until new code base is deployed.

The commit enforces new rules to ensure we can never drop tables or
columns in migrations and instead use Migration::ColumnDropper and
Migration::TableDropper to defer drop the db objects
2018-03-21 15:43:32 +11:00

67 lines
2.0 KiB
Ruby

require 'rails_helper'
require_dependency 'migration/table_dropper'
describe Migration::TableDropper do
def table_exists?(table_name)
sql = <<-SQL
SELECT 1
FROM INFORMATION_SCHEMA.TABLES
WHERE table_schema = 'public' AND
table_name = '#{table_name}'
SQL
ActiveRecord::Base.exec_sql(sql).to_a.length > 0
end
describe '#delayed_drop' do
it "can drop a table after correct delay and when new table exists" do
ActiveRecord::Base.exec_sql "CREATE TABLE table_with_old_name (topic_id INTEGER)"
name = ActiveRecord::Base
.exec_sql("SELECT name FROM schema_migration_details LIMIT 1")
.getvalue(0, 0)
Topic.exec_sql("UPDATE schema_migration_details SET created_at = :created_at WHERE name = :name",
name: name, created_at: 15.minutes.ago)
dropped_proc_called = false
described_class.delayed_drop(
old_name: 'table_with_old_name',
new_name: 'table_with_new_name',
after_migration: name,
delay: 20.minutes,
on_drop: ->() { dropped_proc_called = true }
)
expect(table_exists?('table_with_old_name')).to eq(true)
expect(dropped_proc_called).to eq(false)
described_class.delayed_drop(
old_name: 'table_with_old_name',
new_name: 'table_with_new_name',
after_migration: name,
delay: 10.minutes,
on_drop: ->() { dropped_proc_called = true }
)
expect(table_exists?('table_with_old_name')).to eq(true)
expect(dropped_proc_called).to eq(false)
ActiveRecord::Base.exec_sql "CREATE TABLE table_with_new_name (topic_id INTEGER)"
described_class.delayed_drop(
old_name: 'table_with_old_name',
new_name: 'table_with_new_name',
after_migration: name,
delay: 10.minutes,
on_drop: ->() { dropped_proc_called = true }
)
expect(table_exists?('table_with_old_name')).to eq(false)
expect(dropped_proc_called).to eq(true)
end
end
end