0

I cloned an old project of mine (live on production) from GitHub to my new MacBook running macOS v11 (Big Sur). I wanted to work on new features and updates, but I keep getting some migration errors.

As far as I know, we should not delete any migration file. So what is the best practice to fix these errors?

  • Should I delete, edit the migration files that causes issue?
  • Should I delete the relevant gems along with migration files and install fresh?
  • Any other suggestion?

Command (as root):

bin/rails db:migrate RAILS_ENV=development

Output:

    ** Invoke db:migrate (first_time)
    ** Invoke environment (first_time)
    ** Execute environment
    ** Invoke db:load_config (first_time)
    ** Execute db:load_config
    ** Execute db:migrate
    == 20171118122416 AddTaggingsCounterCacheToTags: migrating ====================
    -- add_column(:tags, :taggings_count, :integer, {:default=>0})
       -> 0.0521s
    rails aborted!
    StandardError: An error has occurred, this and all later migrations canceled:

    uninitialized constant AddTaggingsCounterCacheToTags::ActsAsTaggableOn
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Designer
  • 1,061
  • 1
  • 12
  • 26
  • 1
    For the specific error you have, do the migration file name and class name match correctly? See https://stackoverflow.com/a/413273/5001190 – DavidArndt Apr 10 '21 at 15:52
  • There's nothing wrong with deleting migrations when they've been applied everywhere, `db/schema.rb` (or `db/structure.sql`) should have everything you need. If this is an old project and `schema.rb` is right, you can delete all the migrations and start fresh from `schema.rb`. – mu is too short Apr 10 '21 at 17:08

2 Answers2

3

No, you should not delete migrations, as per Ruby on Rails' own suggestion you're probably better off running bin/rails db:schema:load when creating a new DB on an old project with already existing migrations

From schema.rb:

This file is the source Rails uses to define your schema when running bin/rails db:schema:load. When creating a new database, bin/rails db:schema:load tends to be faster and is potentially less error prone than running all of your migrations from scratch. Old migrations may fail to apply correctly if those migrations use external dependencies or application code.

Note that Ruby on Rails db:setup does db:create, db:schema:load, and db:seed which is useful when setting up a project

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mshka
  • 1,798
  • 1
  • 10
  • 19
  • There's nothing wrong with deleting old migrations (that have been applied everywhere). But yes, starting fresh with `schema.rb` is the right thing to do. – mu is too short Apr 10 '21 at 17:10
  • Ah wow! I didn't know about bin/rails db:schema:load. It worked! I'm not crystal clear why and how though. I need to do more reading about what exactly it does. Thank you! – Designer Apr 10 '21 at 20:00
2

In general, just use db:schema:load

Normally the best solution is to run bin/rails db:schema:load, as @Mshka says.

But for some potential inspiration, here is a case study in which an old migration file had been deleted (a no-no) and I restored it such that I could run db:migrate once again...

Case study: restoration of deleted migration

In this example, a colleague had deleted an old migration for no apparent reason (probably an accident), so db:migrate no longer worked on an empty database in development. After tracking down the deleted migration file from an old commit, however, simply re-adding that migration file presented a new problem: migrations were now failing in production, since the column added by the migration already existed in production. The solution that worked out well in my case was to modify that old migration from

class AddContigFileidToSubmissions < ActiveRecord::Migration[4.2]
  def change
    add_column :submissions, :contig_fileid, :string
  end
end

to

class AddContigFileidToSubmissions < ActiveRecord::Migration[4.2]
  def self.up
    if !column_exists?(:submissions, :contig_fileid)
      add_column :submissions, :contig_fileid, :string
    end
  end

  def self.down
    remove_column :submissions, :contig_fileid
  end
end

That allowed db:migrate to work again on an empty database in development (where the column was now properly added), and for migrations to continue to work when deploying to production (where Rails would find that the column already existed in the database, and make no change).

So if you discover that a previous commit incorrectly damaged an old migration, perhaps fixing the damage could be a convenient solution. But use your judgment.

DavidArndt
  • 406
  • 2
  • 6
  • Thanks for sharing the example David! It is gold! I remember going through a similar thing a while ago. – Designer Apr 10 '21 at 20:14