I feel like this must be a question that has been answered in the past but I could not find anything with Google.
According to the Rails guides:
There is no need (and it is error prone) to deploy a new instance of an app by replaying the entire migration history. It is much simpler and faster to just load into the database a description of the current schema.
However, when you load the database via the schema file there would be no data in the schema_migrations table and therefore any migrations that are added to the project in the future cannot be run without first running the entire migration history.
Am I missing something here? If I create a new instance of the Rails DB from a schema file how can I run any future migrations against it?
It is preferred to set up a new database with a schema load rather than running old migrations, and it should be expected that the schema_migrations table is updated correctly when running a rake db:schema:load. When you run rake db:schema:load the schema_migrations table should be populated based on the value of the version key-pair passed to the ::define method in the db/schema.rb file.
For example:
ActiveRecord::Schema.define(version: 20161208214643) do
end
should update the schema_migrations table up to the migration listed in version. The version value should be populated in the db/schema.rb file automatically after running a rake db:schema:dump or rake db:migrate (which invokes db:schema:dump). This allows for any future migrations to be run normally, as should be expected.
The inserts into the schema_migrations table are handled by the assume_migrated_upto_version method, as seen in the following files:
https://github.com/rails/rails/blob/5-0-stable/activerecord/lib/active_record/schema.rb#L52
https://github.com/rails/rails/blob/5-0-stable/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb#L1021
Related
I got some problems about my database.
I've generated a model Comment once, but this Comment migration not what I wanted, so I drop it, and succeeded to drop. Now I try to re-generate it, and keep running rails db:migrate, but something went wrong.
It shows :
"PG::DuplicateTable: ERROR: relation "comments" already exists",
I've checked my schema.rb, did not have this comment table.
My database using "psql", and Rails version is "Rails 6.0.2.2". I've been searched related problem, but seems like not what I faced.
according your description, I have also encountered this, this is what I tried and solved:
psql
rails db
\d:
drop table tablename;
hope to solve your problem
If the data is not important you could just start fresh by dropping the current database and create a new one
rake db:drop
rake db:create
rake db:migrate
If you are sure that those migrations already have been run before, then you can go and modify the schema migrations table directly where rails stores all migrations that have been run already.
First log into your postgres and choose the correct database
sudo -u postgres psql
\c db_name
then to view the current migrations in the schema table
select * from schema_migrations;
that will show you the current migrations that rails considers as done.
Then check you migrations folder, get the version of all the migration files you want to skip running, the file name starts with the version
for example
20200401212538_add_country_name.rb
the first numeric 20200401212538 part is the version
then insert them into the migrations table
insert into schema_migrations VALUES ('version_of_migration');
Or you could also delete migrations so you could re-run them if you want to.
After that running rake db:migrate should work just fine without trying to recreate the tables.
Another solutions you might consider is that in your migrations you check first if table exists or not before trying to create it.
I've dropped my table successfully from the database from the console, using
ActiveRecord::Migration.drop_table(:foo),
But for some reason the table data still shows in the schema file.
I would like a method to do this without having to manually remove the data, (Doesn't give a proper rails feeling to it.)
The schema file located in db/schema.rb was most likely generated the very last time you ran rake db:migrate. This is because rake db:migrate migrates your db through all of the migrations in your db/migrate folder, and then it calls the db:schema:dump task, which generates the schema file based on the current state of the database.
For your situation, after you have run ActiveRecord::Migration.drop_table(:foo) in the rails console, the current state of your database (now, no longer having the table foo) is not in sync with the schema.rb file that was generated when you last migrated.
What you want to do at this point is re-dump the schema based on the current state of the database, and you do this by running rake db:schema:dump. This will take the current state of your database (without the table foo) and generate your db/schema.rb file.
For more information on the schema file and its relationship to migrations, I would recommend looking at the Rails Guide on Active Record Migrations: Schema Dumping and You.
While the answers provided here work properly, I wanted something a bit more 'straightforward', I found it here: link
First enter rails console:
$rails console
Then just type:
ActiveRecord::Migration.drop_table(:foo)
Where :foo is the table name. And done, worked for me!
2 months ago, one of my migration files has been removed. The thing is when I rake db:migrate my database in localhost the migration is missing. I can Not create a new migration because the production database was migrated with the missing file. So everytime I import the production database in local and I run a migration it says:
Field already exists....
I saw some comment which says I should modify the schema_migrations table with the corresponding version of the migration file.
Do you have any deeper explanation about this issue.
Thanks
the schema_migrations table holds all the version numbers of all the migrations that have been run, or that the system thinks have been run at least. When you do rake db:migrate, rails looks at all the files in db/migrate, and ignores the ones whose numerical prefix is in schema_migrations.
So, if you have a migration that has actually already been run, but the system thinks it hasn't, you just need to add its version number into schema_migrations.
Open the relevant database console, and type
insert into schema_migrations (version) values("<the number from the start of the migration file>");
obviously, replace the part in < > with the proper number.
Then, db:migrate will no longer try and run that migration.
I'm trying to make a new rails project with an existing database.
I create the projects, configure the database.yml and can successfully do a db:schema:dump
This is all based on what I read on this site
http://blog.joelberghoff.com/2013/02/06/ruby-on-rails-tutorial-creating-a-rails-instance-from-an-existing-mysql-db/
And a few others.
After I do the dump, I copied the schema.rb into db/migrate and renamed to 001_createdatabase.rb as indicated in his tutorial.
Everything seems fine. However I cannot run the site as it tells me i have migrations pending. and the db:migrate:status indicates its that 001_createdatabase.rb that I created.
So based on that:
Was creating that 001_createdatabase migration from the schema.rb the right thing to do?
If it was how do I get rails to understand that it doesn't need to run that one as its already done?
Where does rails check to see if it has pending migrations. Obviously it must check the db/migrate folder and compare it to what?
Thanks
It would seem that in order to get credit for having run the migration, you need to actually run the migration. The migration, 001_createdatabase.rb, represents the migration that will take you from having an empty database -- no tables, no data -- to having your first version of the database. When you run rake db:migrate, rails checks to see if every file in the db/migrate directory has been run by looking for the numerical part of the migration file name in the schema_migrations table.
In your case, you've not run the migration, there is no entry in the schema_migrations table, so rails thinks, rightly, there is a migration to run.
To fix the issue, you can put the record that the migration has been run into schema_migrations or actually run the migration. You may need to create the schema_migrations table, rails will create it as needed.
If you want to run the migration, either drop your database (or create a new one -- you can drop the old one when this works), and point your rails application to the new database. run rake db:create and rake db:migrate. When it completes, you should have a new copy of your database, but one that has been created by the rails migration process. The schema_migrations table should have a record with 1 in the version column.
Does rake db:migrate only add new migrations, or does it drop all migrations/changes and build everything new?
I think rake is throwing an error because it is trying to access a table attribute in migration 040 that was deleted in migration 042. somehow my DB and rake are out of synch and I want to fix them.
for you experts out there - is it common for rake to get out of synch with migrations? how can I avoid this (no, I do not hand-edit my schema or rake files).
When you use rails migrations, a table called schema_migrations is automatically created, which keeps track of what migrations have been applied, by storing the version number of each migration (this is the number that prefaces the migration name in the file name, ie db/migrate/_20090617111204__migration.rb). When you run rake db:migrate to migrate up, only migrations which have not been run previously (ie. their version is not contained in the table) will be run (for this reason, changing a migration that's already been executed will have no effect when running db:migrate). When migrating down, all versions found in schema_migrations that are greater than the version you are rolling back to will be undone.
Everytime you create a migration using scripts (like script/generate model ...) a new migration is added to the correct directory ready to be synched with the real database.
Actually rake db:migrate just checks which missing migrations still need to be applied to the database without caring about the previouse ones.
Of course if you modify the database using other ways is common to obtain out-of-synch things because as you said you can find yourself applying a migration to something that is changed underneath.
A migration means that you move from the current version to a newer version (as is said in the first answer). Using rake db:migrate you can apply any new changes to your schema. But if you want to rollback to a previous migration you can use rake db:rollback to nullify your new changes if they are incorrectly defined. Caution: by doing so your data will be lost.