What should I do when my migration references a nonexistent class?

207 views Asked by At

My Migration references an nonexistent class:

class AddDataToUsers < ActiveRecord::Migration[4.2]
  def up
    UsersService.load_data
  end

  def down
    User.delete_all
  end
end

UsersService was deleted but I still have this old migration referencing it.

Devs are not able to run migrations from start now. How should I handle it to fix my migrations?

I have tried to change the old migration file to check if the UserService class is defined. I'm not sure if this is a good practice though.

2

There are 2 answers

3
Francesco Boffa On

As a best practice, you shouldn't be referencing models (or other classes!) in migrations. If you need to load / modify / delete data, you should be creating a rake task for it instead of a migration.

In your case, since the error has already been made, you have to remediate somehow. Since in this particular case it looks like you're loading data into a table that doesn't exist anymore, it should be safe to just delete this migration or comment the lines that reference the non-existing model.

Keep in mind that the "correct thing to do" will be different in different instances of the problem.

@spickermann is not wrong in that you can potentially delete old migrations that have run everywhere and rely on the db/schema.rb file. I however prefer to "squash" old migrations into a single file, getting the same speed benefit, but without breaking the Rails expectation of db:migrate to work from a scratch database.

0
spickermann On

Just delete old migrations once they ran on all your environments, like development, staging, and production. There is very little benefit in keeping old migration files.

To set up an empty database for your application, it is much faster to use rails db:schema:load than rails db:migrate. db:schema:load creates a database with all tables and columns configured like described in the schema.rb.

Or, you will need to import an up-to-date database dump into the new database anyway. In those cases, there is also no need to run migrations.

Therefore, I usually delete old migrations every couple of weeks. When you delete old migrations, then you typically do not run into the problem you described.

And this is actually recommended in the official Rails Guides, as max pointed out:

6.1 What are Schema Files for?

Migrations, mighty as they may be, are not the authoritative source for your database schema. Your database remains the authoritative source. By default, Rails generates db/schema.rb which attempts to capture the current state of your database schema.

It tends to be faster and less error prone to create a new instance of your application's database by loading the schema file via bin/rails db:schema:load than it is to replay the entire migration history. Old migrations may fail to apply correctly if those migrations use changing external dependencies or rely on application code which evolves separately from your migrations.

Schema files are also useful if you want a quick look at what attributes an Active Record object has. This information is not in the model's code and is frequently spread across several migrations, but the information is nicely summed up in the schema file.