Reputation: 980
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
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:
rake db:schema:dump
001_create_database.rb
and pasted the schema from the db/schema.rb
fileFinally, 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
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