I have created a model named Categorie in my Rails App.
Due to a mistake, I needed to remove the model.
I ran
rails d model Categorie
Which removed my existing model.
I have forgotten to run rails g migration DropTable at that moment.
But then, I needed to re-create the Categorie model so i ran :
rails g model Categorie name:string
But when i want to run rake db:migrate i get the following error:
rake aborted!
StandardError: An error has occurred, all later migrations canceled:
Mysql2::Error: Table 'categories' already exists: CREATE TABLE `categories` ...
After that, I've tried to drop the table to redo all the process but it doesn't work, the table is still in schema.rb
I know it's not recommended to do it manually from the file that's why i'd like to know if someone would know something about it. I know it's an idiot mistake but now i don't know how to fix this.
Here is how i've tried to drop the table:
rails g migration DropCategories
def change
drop_table :categories
end
rake db:migrate
I think there is a problem with removing the table because here is the output when i migrate the database:
== 20170509123739 CreateCategories: migrating =================================
-- create_table(:categories)
rake aborted!
StandardError: An error has occurred, all later migrations canceled:
Mysql2::Error: Table 'categories' already exists: CREATE TABLE `categories` (`id` int(11) auto_increment PRIMARY KEY, `name` varchar(255), `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL) ENGINE=InnoDB
Rails seems to CREATE a table and not DELETE the one i want.
You can simply drop the table if it exists in your new migration:
def change
reversible do |dir|
dir.up do
drop_table :categories if table_exists? :categories # pre rails 5
drop_table :categories, if_exists: true # rails 5 and onwards
end
end
# put the rest of your migration here:
create_table :categories do |t|
t.string :name
t.timestamps
end
end
The reversible bit ensures that the custom table deletion code is only executed when running the migration normally, and is ignored whenever you do a rollback.
Follow these steps to fix the issue
in your migration file comment the code in 'change' method
def change
create_table :categories do |t|
#t.string :name
#t.timestamps
end
end
run rake db:migrate command
uncomment the code in 'change' method
def change
create_table :categories do |t|
t.string :name
t.timestamps
end
Now run rake db:migrate
Now your migrations get restored to normal and you can continue what you need
Hey I have a problem with my page here. I used a gem 'devise' to create a migration file for "users" I might have forgotten to rake db:migrate after that but I'm really not too sure what I did here to duplicate anything.
I ran the code rails g devise user I may have forgotten to db:migrate and then ran the code rails g devise:views
It's for a TeamTreeHouse project, and I'm sorry if I was too confusing with my question...anyway here is the error message.
== AddDeviseToUsers: migrating ===============================================
-- change_table(:users, :email)
rake aborted!
An error has occurred, this and all later migrations canceled:
SQLite3::SQLException: duplicate column name: email: ALTER TABLE "users" ADD "email" varchar(255) DEFAULT '' NOT NULL
Tasks: TOP => db:migrate
(See full trace by running task with --trace)
It seems you already have an "users" table
Try to run: rake db:reset to run your migrations after drop and recreate your database.
UPDATE
This command will clear all data you have stored (unless is present in your seeds.rb), be careful to use this if you have important data in your database.
his command will clear all data you have stored (unless is present in your seeds.rb), be careful to use this if you have important data in your database.
I have had ongoing trouble migrating a database in rails via rake db:migrate.
My migration currently looks like this:
class CreateArticles < ActiveRecord::Migration
def change
create_table :articles do |t|
t.string :title
t.text :subtitle
t.string :slug
t.text :body
t.integer :publish, limit: 1, default: 0
t.timestamps
end
end
end
However if ever I delete a column from this or even add or modify one the rake db:migrate command does nothing. The only way I can migrate it is sometimes running something like:
rake db:migrate VERSION=20080906120000
But even that is temperamental so most of the time I need to reset the db using
db:drop
db:create
then running the migration again as normal. basically db:migrate only ever works the first time after dropping and creating the db.
I've also tried rollback before running the migration.
This is far from ideal so I'd appreciate any help.
(I realise there are similar questions but all of their issues are solved after a db reset)
You need to run the migration down and then run it up again, which is done with the redo task. try this:
rake db:migrate:redo VERSION=20080906120000
EDIT: if you have data you want to keep in this table, it's better to make a new migration to remove the column or whatever you want to do, as the above will drop and recreate the table, wiping the data in the process.
So I accidentally named a column in my Item model "type" and I wrote a migration to rename it.
class RenameTypeToTagged < ActiveRecord::Migration
def up
rename_column :items, :type, :tagged
end
def down
end
end
When I restart the server, and rake db:migrate it still spits back "Can't mass-assign protected attributes: type". I've renamed the attr_accesible in the Item model by hand but it doesn't seem to resolve. any ideas? thanks
i don't know if it can help, but you have the possibility to rollback to a previous version of the migration. you can after redo a new migration file with the right field name.
to rollback to a previous migration, if your migration file with the error is named :
20130629033812_create_items.rb
you just have to type
rake db:migrate:down VERSION=20130629033812
How do you roll back a failed rails migration? I would expect that rake db:rollback would undo the failed migration, but no, it rolls back the previous migration (the failed migration minus one). And rake db:migrate:down VERSION=myfailedmigration doesn't work either. I've ran into this a few times and it's very frustrating. Here's a simple test I made to duplicate the problem:
class SimpleTest < ActiveRecord::Migration
def self.up
add_column :assets, :test, :integer
# the following syntax error will cause the migration to fail
add_column :asset, :test2, :integer
end
def self.down
remove_column :assets, :test
remove_column :assets, :test2
end
end
result:
== SimpleTest: migrating =====================================================
-- add_column(:assets, :test, :integer)
-> 0.0932s
-- add_column(:asset, :error)
rake aborted!
An error has occurred, all later migrations canceled:
wrong number of arguments (2 for 3)
ok, lets roll it back:
$ rake db:rollback
== AddLevelsToRoles: reverting ===============================================
-- remove_column(:roles, :level)
-> 0.0778s
== AddLevelsToRoles: reverted (0.0779s) ======================================
huh? that was my last migration before SimpleTest, not the failed migration. (And oh, it would be nice if the migration output included the version number.)
So lets try running the down for the failed migration SimpleTest:
$ rake db:migrate:down VERSION=20090326173033
$
Nothing happens, and no output either. But maybe it ran the migration anyway? So lets fix the syntax error in the SimpleTest migration, and try to run it again.
$ rake db:migrate:up VERSION=20090326173033
== SimpleTest: migrating =====================================================
-- add_column(:assets, :test, :integer)
rake aborted!
Mysql::Error: Duplicate column name 'test': ALTER TABLE `assets` ADD `test` int(11)
Nope. Obviously the migrate:down didn't work. It's not failing, it's just not executing.
No way to get rid of that duplicate table other than manually going into the database and removing it, and then running the test. There's got to be a better way than that.
Unfortunately, you must manually clean up failed migrations for MySQL. MySQL does not support transactional database definition changes.
Rails 2.2 includes transactional migrations for PostgreSQL. Rails 2.3 includes transactional migrations for SQLite.
This doesn't really help you for your problem right now, but if you have a choice of database on future projects, I recommend using one with support for transactional DDL because it makes migrations much more pleasant.
Update - this is still true in 2017, on Rails 4.2.7 and MySQL 5.7, reported by Alejandro Babio in another answer here.
OK, folks, here's how you actually do it. I don't know what the above answers are talking about.
Figure out which part of the up migration worked. Comment those out.
Also comment out/remove the part of the migration that broke.
Run the migration again. Now it will complete the non-broken parts of the migration, skipping the parts that have already been done.
Uncomment the bits of the migration you commented out in step 1.
You can migrate down and back up again if you want to verify that you've got it right now.
To go to a specified version just use:
rake db:migrate VERSION=(the version you want to go to)
But if a migration fails part way, you'll have to clean it up first. One way would be:
edit the down method of the migration to just undo the part of the up that worked
migrate back to the prior state (where you started)
fix the migration (including undoing your changes to the down)
try again
I agree that you should use PostgreSQL when possible. However, when you are stuck with MySQL, you can avoid most of these problems by trying your migration on your test database first:
rake db:migrate RAILS_ENV=test
You can revert to the previous state and try again with
rake db:schema:load RAILS_ENV=test
At 2015 with Rails 4.2.1 and MySQL 5.7, a failed migration can't be fixed with standard rake actions that Rails provide, as it was at 2009.
MySql does not support rollback of DDL statments (at MySQL 5.7 Manual). And Rails can not do anything with that.
Also, we can check how Rails is doing the job: A migration is wrapped in a transaction depending on how connection adapter respond to :supports_ddl_transactions?. After a search of this action at rails source (v 4.2.1), I found that only Sqlite3 and PostgreSql supports transactions, and by default it is not supported.
Edit
Thus the current answer to the original question: A failed MySQL migration must be manually fixed.
The easy way to do this is to wrap all of your actions in a transaction:
class WhateverMigration < ActiveRecord::Migration
def self.up
ActiveRecord::Base.transaction do
...
end
end
def self.down
ActiveRecord::Base.transaction do
...
end
end
end
As Luke Francl noted, "MySql['s MyISAM tables don't] support transactions" -- which is why you might consider avoiding MySQL in general or at least MyISAM in particular.
If you're using MySQL's InnoDB, then the above will work just fine. Any errors in either up or down will back out.
BE AWARE some types of actions cannot be reverted via transactions. Generally, table changes (dropping a table, removing or adding columns, etc.) cannot be rolled back.
Run just the down migration from the console:
http://gilesbowkett.blogspot.com/2007/07/how-to-use-migrations-from-console.html (click through to his pastie)
I had a typo (in "add_column"):
def self.up
add_column :medias, :title, :text
add_colunm :medias, :enctype, :text
end
def self.down
remove_column :medias, :title
remove_column :medias, :enctype
end
and then your problem (cannot undo partly failed migration). after some failed googling i ran this:
def self.up
remove_column :medias, :title
add_column :medias, :title, :text
add_column :medias, :enctype, :text
end
def self.down
remove_column :medias, :title
remove_column :medias, :enctype
end
as you can see i just added the correction line by hand, and then removed it again, before i checked it in.
Alejandro Babio's answer above provides the best current answer.
One additional detail I want to add:
When the myfailedmigration migration fails, it is not considered as applied, and this can be verified by running rake db:migrate:status, which would show output similar to the following:
$ rake db:migrate:status
database: sample_app_dev
Status Migration ID Migration Name
--------------------------------------------------
up 20130206203115 Create users
...
...
down 20150501173156 Test migration
The residual effect of add_column :assets, :test, :integer being executed on the failed migration will have to be reversed at the database level with a alter table assets drop column test; query.