Boltz0r
Boltz0r

Reputation: 980

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

Upvotes: 2

Views: 2434

Answers (2)

Chelo
Chelo

Reputation: 76

I had the same problem but I can't use the solution above.

My database was created before than the ruby on rails app and it didn't have the schema_migrations table created, so when it ran this:

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

it returned false in the if statement thus, it never skip the create_database migration in my case.

I was looking for some way where I can run the migrations and avoid to create tables again and, at the same time, new coders can run it and create the tables.

After some search I found the table_exists? function, so:

  1. I created the schema migration using the rake db:schema:dump
  2. Then I created my first migration: 001_create_database.rb and pasted the schema from the db/schema.rb file
  3. Finally, I edited the migration adding and if statement before each create table:

    if !table_exists?("CarsTable")
        create_table "CarsTable" do |t|
            t.bigint   "Owner", null: false
            t.string   "Color", limit: 20, null: false
            t.string   "Make",  limit: 40, null: false
            t.string   "Model", limit: 20, null: false
            t.string   "Plate", limit: 10, null: false
         end
    end
    

I tested this in 2 ways, with a database previously created and populated (for production case and my own case) and without any database (for new coders) and it worked.

Upvotes: 2

Jay-Ar Polidario
Jay-Ar Polidario

Reputation: 6603

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.

Upvotes: 1

Related Questions