Boltz0r Boltz0r - 2 months ago 14
MySQL Question

Rails app using existing database MySQL

I'm a RoR developer and I'm used to create my own databases using scaffold and such. However I was told to create a rails app to an existing populated database. I Searched and i found this:

1. write config/database.yml to reference your database.
2. Run "rake db:schema:dump" to generate db/schema.rb. Here's the
documentation:

$ rake -T db:schema:dump
...
rake db:schema:dump # Create a db/schema.rb file that can be
portably used against any DB supported by AR

3. Convert schema.rb into db/migrate/001_create_database.rb:

Class CreateMigration < ActiveRecord::Migration
def self.up
# insert schema.rb here
end

def self.down
# drop all the tables if you really need
# to support migration back to version 0
end
end


However I saw some comments saying that they lost their data and some saying that it worked. I can't take chances to lose the data from the database. Can someone please give me some more solid explanation? Or a better solution

Answer

Rails check all migration files in db/migrate/ and checks if they all are part of the "schema_migrations" table. Your code above will only work for fresh copy of your code (i.e. if I clone your Rails project), because migrations are run in the order of the filename. Since it is 00001_create_d... then it will be the first to be ran on my end, followed by other migration files you have.

You are right that you will then possibly lose data if you migrate, because the schema code you have will be ran after all of your migration files have already been migrated.

Now since it is only you and other developers working on the project, who cannot simply just do rake db:migrate, and that new cloners of your project will have no problems with your code above, then I could do the following below to force that 001_create_database.rb to be already part of your schema_migrations table, thereby skipping it, but not for new cloners (like myself).

IMPORTANT: backup your database first before doing below code

db/migrate/001_safeguard_create_database.rb

class SafeguardCreateDatabase < ActiveRecord::Migration
  def up
    # if current migration version already has a created database
    if ActiveRecord::Migrator.current_version > 2
      # force the next migration 002_create_database.rb to be skipped
      ActiveRecord::SchemaMigration.create(version: '2')
      # the version '2' above is the version of the file which is (002 becomes 2)
    end
  end
  def down
    raise ActiveRecord::IrreversibleMigration
  end
end

db/migrate/002_create_database.rb

class CreateDatabase < ActiveRecord::Migration
  def up
    # your schema.rb here
  end
  def down
    raise ActiveRecord::IrreversibleMigration
  end
end

After creating these two files, try rake db:migrate. It should only process 001_safeguard_create_database, and skip 002_create_database because it is assumed that your current DB is already set up with it. The 002_create_database then will only be ran for new project users who do not have a DB yet; and for these users, these first two migration files be be ran first, followed by all of your other migrations.

Comments