aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases/migration_test.rb
diff options
context:
space:
mode:
authorschneems <richard.schneeman@gmail.com>2015-08-14 11:31:33 -0500
committerschneems <richard.schneeman@gmail.com>2016-01-07 18:01:05 -0600
commit900bfd94a9c3c45484d88aa69071b7a52c5b04b4 (patch)
tree9f28b1f0acf2f74143ec7806bd89081430f6f306 /activerecord/test/cases/migration_test.rb
parent89f776402dbaca581ef4bb342bb89db922124c7a (diff)
downloadrails-900bfd94a9c3c45484d88aa69071b7a52c5b04b4.tar.gz
rails-900bfd94a9c3c45484d88aa69071b7a52c5b04b4.tar.bz2
rails-900bfd94a9c3c45484d88aa69071b7a52c5b04b4.zip
Prevent destructive action on production database
This PR introduces a key/value type store to Active Record that can be used for storing internal values. It is an alternative implementation to #21237 cc @sgrif @matthewd. It is possible to run your tests against your production database by accident right now. While infrequently, but as an anecdotal data point, Heroku receives a non-trivial number of requests for a database restore due to this happening. In these cases the loss can be large. To prevent against running tests against production we can store the "environment" version that was used when migrating the database in a new internal table. Before executing tests we can see if the database is a listed in `protected_environments` and abort. There is a manual escape valve to force this check from happening with environment variable `DISABLE_DATABASE_ENVIRONMENT_CHECK=1`.
Diffstat (limited to 'activerecord/test/cases/migration_test.rb')
-rw-r--r--activerecord/test/cases/migration_test.rb44
1 files changed, 44 insertions, 0 deletions
diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb
index 19be357b6e..2f7859a7be 100644
--- a/activerecord/test/cases/migration_test.rb
+++ b/activerecord/test/cases/migration_test.rb
@@ -354,6 +354,50 @@ class MigrationTest < ActiveRecord::TestCase
Reminder.reset_table_name
end
+ def test_internal_metadata_table_name
+ original_internal_metadata_table_name = ActiveRecord::Base.internal_metadata_table_name
+
+ assert_equal "active_record_internal_metadatas", ActiveRecord::InternalMetadata.table_name
+ ActiveRecord::Base.table_name_prefix = "prefix_"
+ ActiveRecord::Base.table_name_suffix = "_suffix"
+ Reminder.reset_table_name
+ assert_equal "prefix_active_record_internal_metadatas_suffix", ActiveRecord::InternalMetadata.table_name
+ ActiveRecord::Base.internal_metadata_table_name = "changed"
+ Reminder.reset_table_name
+ assert_equal "prefix_changed_suffix", ActiveRecord::InternalMetadata.table_name
+ ActiveRecord::Base.table_name_prefix = ""
+ ActiveRecord::Base.table_name_suffix = ""
+ Reminder.reset_table_name
+ assert_equal "changed", ActiveRecord::InternalMetadata.table_name
+ ensure
+ ActiveRecord::Base.internal_metadata_table_name = original_internal_metadata_table_name
+ Reminder.reset_table_name
+ end
+
+ def test_internal_metadata_stores_environment
+ current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
+ migrations_path = MIGRATIONS_ROOT + "/valid"
+ old_path = ActiveRecord::Migrator.migrations_paths
+ ActiveRecord::Migrator.migrations_paths = migrations_path
+
+ assert_equal current_env, ActiveRecord::InternalMetadata.value_for("environment")
+
+ original_rails_env = ENV["RAILS_ENV"]
+ original_rack_env = ENV["RACK_ENV"]
+ ENV["RAILS_ENV"] = ENV["RACK_ENV"] = "foofoo"
+ new_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
+
+ refute_equal current_env, new_env
+
+ sleep 1 # mysql by default does not store fractional seconds in the database
+ ActiveRecord::Migrator.up(migrations_path)
+ assert_equal new_env, ActiveRecord::InternalMetadata.value_for("environment")
+ ensure
+ ActiveRecord::Migrator.migrations_paths = old_path
+ ENV["RAILS_ENV"] = original_rails_env
+ ENV["RACK_ENV"] = original_rack_env
+ end
+
def test_proper_table_name_on_migration
reminder_class = new_isolated_reminder_class
migration = ActiveRecord::Migration.new