Designer
Designer

Reputation: 1111

Best tactics to deal with failed migration using Ruby on Rails

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?

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

Upvotes: 1

Views: 1841

Answers (2)

Mshka
Mshka

Reputation: 1828

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

Upvotes: 4

DavidArndt
DavidArndt

Reputation: 446

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.

Upvotes: 3

Related Questions