Rails 4 How to Ignore Pending Migrations

Rails 4 how to ignore pending migrations

Rails stores migration information in a table called schema_migrations.

You can add the version from your migration into that table to skip a specific migration.

The version is the number string which comes before the description in the file name.

[version]_Create_Awesome.rb

Rails: How to delete a pending migration

Sometimes, even dropping a local development database is not a good idea.
There are better ways to delete/destroy a specific migration in your Rails application.

You could use rails d migration command to destroy a particular migration:

rails d migration MigrationName

To undo the changes corresponding to a particular migration, you can use db:migrate:down method like this:

rake db:migrate:down VERSION=XXX

Sometimes, things could get more messy and in those situation another handy thing is to take a look at the schema_migrations table in your database which has all the migrations with their version saved in it.

You can delete a particular migration from this table like this:

delete from schema_migrations WHERE version = VERSION;

if you don't want that migration to be present anymore.

How temporarily disable needs_migration? check when testing migration?

Testing Rails migration is a bit of a pain so I would rather step back and think about if this needs to be in a Rails migration / tested in a Rails migration.

There are basically two different types of migrations

Schema migrations

Use mostly Rails built in functions. Unless you do some handcrafted SQL I wouldn't bother testing this and trust the framework here.

Data migrations

Data migrations are used to backfill or change data. As data is one of your most valuable assets and loosing or corrupting it is very painful I would definitely recommend to write tests for data migrations.

As mentioned, testing migrations is a bit of a pain so I would try to abstract the data migration code in it's own (service) class. Something like

class DataMigration::UpdateUsername
def self.run
new.run
end

def run
User.all do |batch|
user.update(name: user.name.capitalize)
end
end
end

You can now test the data migration like a normal class like this:

it 'does capitalize the name' do
user = create(:user, name: 'name')

DataMigration::UpdateUsername.run

expect(user.reload.name).to eq('NAME')
end

Now we can use this class in our Rails migration or e.g. just use it in a Rake task. Using it in a Rake task also has the advantages that we can pass in parameters, run several data migrations in parallel (e.g. you have a large data set) or even in a background job which you can't in a Rails migration.

Example

class DataMigration::UpdateUsername
def initialize(start_id:, finish_id:)
@start_id = start_id
@finish_id = finish_id
end

def run
User.find_in_batches(start: start_id, finish: finish_id) do |batch|
batch.each do |user|
user.update(name: user.name.capitalize)
end
end
end
end

Now we can create a custom task for this

namespace :db do
desc "Runs user data migration"
task :update_user, [:start, :finish] do |task, args|
DataMigration::UpdateUsername.new(start_id: args[:start], finish_id: args[:finish])
end
end

rake db:update_user[0, 10000]
rake db:update_user[10000, 20000]
# ...

Migrations are pending error while everything is up to date

The issue is your database reflects that migration is loaded but somehow the entry in schema_migrations either got deleted(accidentally or through migration rollback).

Steps to solve this issue:

  1. Identify the migration(migration number) from db/migrations where study_agreements relation was introduced. Let's say it is 1234

  2. Now manually create an entry in schema_migrations table in your DB. For example in MySQL you can do "INSERT INTO schema_migrations (version) values(1234)".

Another solution is: Run rake db:migrate after commenting the change or up method of your migration in which study_agreements relation was introduced.

How to skip rails migrations after creating database from dump

If you're restoring a database from a dump, the schema_migrations table should restore along with the rest of the tables.

This seems to indicate your schema_migrations table may not be getting backed up which would lead to the problem you have now.

The ideal solution would be to restore a backup that has all the tables in it correctly -- including schema_migrations.

Even if you decide to find a way around this in the short-term, in the long-term the correct solution is to modify your backup scripts to get all the tables you need, including schema_migrations.

In terms of what to do now, the ideal solution is probaby to backup just that one table (schema_migrations) from your database and import that data into the database you're trying to load now. Then your migrations should no longer be pending.

Doing that with a simple table dump and load script should be fine. The simple postgres gui PgAdmin ( http://www.pgadmin.org/ ) may also provide some basic tools for dumping then loading a single table.



Related Topics



Leave a reply



Submit