Ad

Rails 5.0.0.beta1, Two Database Setup Creates Additional Active_record_internal_metadatas Tables

I'm trying to implement a two database setup in rails 5.0.0.beta1. Everything seems to be working quite fine but I've run into something odd. The models connect to the specified databases, associations work, migrations (after some tweaks) work fine too. After I run the migrations an additional table, called active_record_internal_metadatas, appears in both databases. When I tested this setup on rails 4.2.5 there were no such thing. Can somebody shed some light on the issue?

The settings for a double database setup:

  • database.yml

    default: &default
    adapter: mysql2
    encoding: utf8
    pool: 5
    username: root
    password:
    socket: /tmp/mysql.sock
    
    development:
      <<: *default
      database: app_name_development_first
    
    development_second:
      <<: *default
      database: app_name_development_second
    
  • second_db_connection.rb - a model which handles the connection to the second database. All models that are supposed to be in the second database have to inherit from this model.

    class SecondDbConnection < ActiveRecord::Base
        establish_connection "#{Rails.env}_second".to_sym
        self.abstract_class = true
    end
    
  • application_controller.rb - caching connections for the second database

    class ApplicationController < ActionController::API
      around_filter :cache_other_db_connections
    
      private
        def cache_other_db_connections
          SecondDbConnection.connection.cache { yield }
        end
    end
    
  • db.rake - overwritten migration tasks

    namespace :db do
      task :migrate do
        Rake::Task['db:migrate_first'].invoke
        Rake::Task['db:migrate_second'].invoke
      end
    
      task :migrate_first do
        ActiveRecord::Base.establish_connection ("#{Rails.env}".to_sym)
        ActiveRecord::Migrator.migrate('db/db_first/migrate/')
        ActiveRecord::Base.connection.close
      end
    
      task :migrate_second do
        ActiveRecord::Base.establish_connection ("#{Rails.env}_second".to_sym)
        ActiveRecord::Migrator.migrate('db/db_second/migrate/')
        ActiveRecord::Base.connection.close
      end
    end
    
Ad

Answer

It seems to be a Rails 5 feature. Here is an quotation from this pull request commit introducing it:

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.

Ad
source: stackoverflow.com
Ad