Daniel Viglione
Daniel Viglione

Reputation: 9407

How does Rails know there are pending migrations if latest migration is the same?

Given I have the following versions in the schema_migrations table:

| 20180822231257 |
| 20180822234804 |
| 20180829011800 |
| 20180924212812 |

And given I checkout a specific branch of my project with the following migrations (below I omit the full file name for the db/migrate/*.rb files):

| 20180822231257 |
| 20180822234804 |

20180827225521
20180828172831

| 20180829011800 |

20180911233144
20180913172923

| 20180924212812 |

As you can see, the files without the pipes represent files in my db/migrate folder that are not in the schema_migrations file in the database.

Now when I try to run rails s, I get the following error:

Migrations are pending. To resolve this issue, run:
bin/rake db:migrate RAILS_ENV=development

When I looked at schema.rb, I noticed this line:

ActiveRecord::Schema.define(version: 20180924212812) do

So as you can see, schema.rb is pointing to the latest version.

However, schema.rb contains some code that is not in the database I have, such as a create_table statement for one of those migrations that are not in database:

  create_table "some_table", force: :cascade do |t|
    t.integer  "some_id",      limit: 4
    t.integer  "default_view", limit: 4
    t.datetime "created_at",             null: false
    t.datetime "updated_at",             null: false
  end

So despite that the latest migration version is the same, is Rails detecting that some older migrations are not present in the current schema_migrations table?

(Just as a side note, I think the reason both branches have the same latest commit is because I think someone cherry-picked the specific migration onto the other branch but not the other migrations).

Upvotes: 2

Views: 1745

Answers (2)

igor_rb
igor_rb

Reputation: 1891

here

def needs_migration?
  (migrations.collect(&:version) - get_all_versions).size > 0
end

def migrations
  migrations = migration_files.map do |file|
    version, name, scope = parse_migration_filename(file)
    raise IllegalMigrationNameError.new(file) unless version
    version = version.to_i
    name = name.camelize

    MigrationProxy.new(name, version, file, scope)
  end

  migrations.sort_by(&:version)
end
def migration_files
  paths = Array(migrations_paths)
  Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
end

you can see that rails got all files in db/migrate and subtract from them all versions from SchemaMigration table.

Upvotes: 2

Marcin Kołodziej
Marcin Kołodziej

Reputation: 5313

Rails creates a schema_migrations table where it inserts all migrations that have been successfully ran. If your environment is configured to check whether all migrations have been ran, it will compare all the migrations in your db/migrate directory with all the versions in schema_migrations table.

Contents of schema.rb are generated from your database, not migrations, so if you had some migrations create additional tables/columns and deleted these migrations, your schema will contain tables that will not be present if you run full rake db:migrate:reset.

Upvotes: 0

Related Questions