Skip to content
Permalink
Browse files

Refactor migration to move migrations paths to connection

Rails has some support for multiple databases but it can be hard to
handle migrations with those. The easiest way to implement multiple
databases is to contain migrations into their own folder ("db/migrate"
for the primary db and "db/seconddb_migrate" for the second db). Without
this you would need to write code that allowed you to switch connections
in migrations. I can tell you from experience that is not a fun way to
implement multiple databases.

This refactoring is a pre-requisite for implementing other features
related to parallel testing and improved handling for multiple
databases.

The refactoring here moves the class methods from the `Migrator` class
into it's own new class `MigrationContext`. The goal was to move the
`migrations_paths` method off of the `Migrator` class and onto the
connection. This allows users to do the following in their
`database.yml`:

```
development:
  adapter: mysql2
  username: root
  password:

development_seconddb:
  adapter: mysql2
  username: root
  password:
  migrations_paths: "db/second_db_migrate"
```

Migrations for the `seconddb` can now be store in the
`db/second_db_migrate` directory. Migrations for the primary database
are stored in `db/migrate`".

The refactoring here drastically reduces the internal API for migrations
since we don't need to pass `migrations_paths` around to every single
method. Additionally this change does not require any Rails applications
to make changes unless they want to use the new public API. All of the
class methods from the `Migrator` class were `nodoc`'d except for the
`migrations_paths` and `migrations_path` getter/setters respectively.
  • Loading branch information...
eileencodes committed Jan 10, 2018
1 parent 198e3e3 commit a2827ec9811b5012e8e366011fd44c8eb53fc714
@@ -1049,8 +1049,8 @@ def assume_migrated_upto_version(version, migrations_paths)
sm_table = quote_table_name(ActiveRecord::SchemaMigration.table_name)

migrated = ActiveRecord::SchemaMigration.all_versions.map(&:to_i)
versions = ActiveRecord::Migrator.migration_files(migrations_paths).map do |file|
ActiveRecord::Migrator.parse_migration_filename(file).first.to_i
versions = migration_context.migration_files.map do |file|
migration_context.parse_migration_filename(file).first.to_i
end

unless migrated.include?(version)
@@ -119,6 +119,14 @@ def initialize(connection, logger = nil, config = {}) # :nodoc:
end
end

def migrations_paths
@config[:migrations_paths] || Migrator.migrations_paths
end

def migration_context
MigrationContext.new(migrations_paths)
end

class Version
include Comparable

@@ -28,7 +28,7 @@ def encode_with(coder)
coder["columns_hash"] = @columns_hash
coder["primary_keys"] = @primary_keys
coder["data_sources"] = @data_sources
coder["version"] = ActiveRecord::Migrator.current_version
coder["version"] = connection.migration_context.current_version
end

def init_with(coder)
@@ -100,7 +100,7 @@ def clear_data_source_cache!(name)

def marshal_dump
# if we get current version during initialization, it happens stack over flow.
@version = ActiveRecord::Migrator.current_version
@version = connection.migration_context.current_version
[@version, @columns, @columns_hash, @primary_keys, @data_sources]
end

Oops, something went wrong.

0 comments on commit a2827ec

Please sign in to comment.
You can’t perform that action at this time.