Adrian Rotama
Adrian Rotama

Reputation: 311

Rails Mysql2::Error Table doesn't exist When create new migration

I wrote a migration with the following (create new table named sources):

class CreateSources < ActiveRecord::Migration
  def change
    create_table :sources do |t|
      t.string :name, null: false, default: ""

      t.timestamps null: false
    end
  end
end

And then I modified my existing model :

class Property < ActiveRecord::Base
  validates :source, allow_blank: true, inclusion: { in: 
  Source.all.map{ |source| source.name } }

I want to add validation to the property's source to only allow source from sources table.

And then when I run the migration, I got the following error:

ActiveRecord::StatementInvalid: Mysql2::Error: Table 'sources' doesn't exist: SELECT `sources`.* FROM `sources`

The problem is query of source table is occured when it hasn't been initialized yet.
Any tips on how I can get the migration to run?
This is run on production level. so I might can't drop all the migration and rearrange it.

Rails version 4.2.5
SQL version 5.7

Upvotes: 1

Views: 2021

Answers (2)

mu is too short
mu is too short

Reputation: 434665

Keep in mind that your Source.all.map{ |source| source.name } is going to be executed when the Property class is being loaded. The Source class might not be properly initialized at that point and there might not be a proper database connection set up. Also, you'll only access Source.all once so you'd have to restart your app if you added a new Source.

Instead, validate by hand:

class Property < ActiveRecord::Base
  validate :valid_source
private
  def valid_source
    return if(source.blank?)
    return if(Source.where(name: source).exists?)
    errors.add(:source, 'Unknown source') # Or whatever you want to say
  end
end

That way you're checking the sources table at the right time.

Also, I wouldn't expect the error you're seeing to occur in a migration. Perhaps you're using a model inside a migration, that is to be avoided.

As an aside, is there particular reason that you don't have belongs_to :source instead? Copying the name around like that is very error prone, using a reference (hopefully backed by a foreign key in the database) would be much safer.

Upvotes: 1

Nithin
Nithin

Reputation: 3699

Have you defined Source model? I hope so.

Here the problem looks like the loading of Property class takes priority before migration is run and hence the issue.

Upvotes: 0

Related Questions