Rake db:migrate not ignoring old migrations? - ruby-on-rails

Running through Michael Hartl's well known Rails tutorial, hit this snag.
I have this in a migration file, created by rails generate model etc:
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.string :email
t.timestamps
end
end
end
Later, I added this second migration file:
class AddIndexToUsersEmail < ActiveRecord::Migration
def change
add_index :users, :email, unique: true
end
end
To try and update the database to include the new one, I followed the instructions and ran rake db:migrate, but this gives me an error telling me I'm trying to create a table that already exists, which is to say I'm clearly missing something.
Am I...supposed to delete the first migration? That wouldn't make any sense. What to do?
(These are the only files under db/migrate)

if you realy want to see what migrations have been ran into the database, you can inspect your app database, there is a table called schema_migrations, in there you can see the unique id of each migration as a row for example is your migration is called: 20130402190449_add_flagand_table.rb, you should see the number 20130402190449 as a row of that table, hope i gave you some guidance

What you can do is rollback couple of migration and re-run.
You can rollback migration like this
#rake db:rollback STEP=2
and then run
#rake db:migrate
Hope it should work

My issues was my 2nd to last migration ran and it was trying to rerun that migration again after i added a new migration.
I ended up just commenting out the code inside the one it was trying to rerun, and then ran rake db:migrate then uncommented the migration code.
This way the schema does not break and it fixes whatever bug occurred.

Related

rake db:migrate is not creating user table

I have the following migrations
Problem is that rake db:migrate is not executing the first migration and no users table is created.
What could be the reason for this?
What could be the reason for this?
Main reason is probably that you've already ran the migration - or perhaps later migrations - and Rails therefore does not think it needs to run it.
A good way to see if this is the case is to open your db/schema.rb file:
You'll see the latest migration your schema is running. If this supersedes the one you're trying to invoke, it will not run.
--
Fixes
You could generate a new migration, and copy the code over:
$ rails g migration AddUsers2
You'd then add the following:
#db/migrate/_____.rb
class AddUsers2 < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.timestamps
end
end
end
Alternatively, you could wipe your DB and start again. This can be achieved using rake schema:load. THIS WILL WIPE ALL DATA AND START AGAIN

Rolling back a migration in Ruby on Rails

I am working on my first ruby on rails project, and have created a "Users" table for my app using a "rails generate scaffold users" command.
Now I am trying to undo this statement as I wish to try to rewrite the classes involved with that class and table in my database.
I saw that the scaffold statement created a "def change" class in a migration, and when I try to rollback that migration there is no function within the migration. I added a "def down" method with only the "drop_table :users" defined within it.
def down
drop_table :users
end
However, when I run "rake db:rollback", there is no response in the command prompt and the table is unchanged.
I am not quite sure how to undo this migration to rewrite the table schema. Can anyone offer assistance please?
The whole migration looks like the following:
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.string :password_digest
t.string :email
t.timestamps
end
end
def down
drop_table :users
end
end
EDIT:
Fixed this by running db:drop and db:rollback to clear my schema. I think there was an issue with me having the database open in another program. I closed it and that allowed the database to be rolled back.
rails generate scaffold users doesn't change your database, it only generate MVC code. You can simply undo it by destroy scaffold command
rails destroy scaffold users
If you run rake db:migrate command than you can rollback it by rake db:rollback command. At migration file, change method is enough for create or drop operation of tables. No down method is needed, down method is the complement method of up method.

Ruby on Rails: adding columns to existing database

I'm getting an error:
SQLite3::SQLException: no such column: ideas.list_id:
SELECT "ideas".* FROM "ideas"
WHERE "ideas"."list_id" = 2
But I added
t.integer :list_id
to my db migration file:
class CreateIdeas < ActiveRecord::Migration
def change
create_table :ideas do |t|
t.string :name
t.text :description
t.string :picture
t.timestamps
end
add_foreign_key :ideas, :lists
end
end
which gave me this:
class CreateIdeas < ActiveRecord::Migration
def change
create_table :ideas do |t|
t.string :name
t.text :description
t.string :picture
t.integer :list_id
t.timestamps
end
add_foreign_key :ideas, :lists
end
end
and then I typed
rake db:migrate
Any idea why I would be getting an error saying there's no column? I'm still new to RoRs. Do I have to add a column some other way?
Thanks
As Speransky suggested, you should never modify old migration files. Rather you should create a new migration that adds the desired column. For instance, in this case you would run the following command in your app to create the new migration:
rails generate migration AddListIdColumnToIdeas list_id:integer
And Rails would generate the migration file automatically and the only thing left to do is run rake db:migrate.
If you insist on modifying the old migration file, you can add the column as you did and run the following:
rake db:drop
rake db:create
rake db:migrate
Which will destroy your current database, create a new one and run all the migrations (which will include your new column).
If you want to add a new column to an exist database, you should use rails generate migration. So you can try rails generate migration add_list_id_to_ideas list_id:integer and then use rake db:migrate to commit this change.
You should not add new rows to old migrations. Migration is a step of building database. And number of last executed migration is stored in schema, and it will not be run or redone if you use will use rake db:migrate. If you run the migration with creating the table before, then you should create new migration where you may use add_column method.
migration file name has the datetime encoded in its name so rails run this migration one and do not run it again unless you do a rollback
and here come the magic of migration to build you db with small steps so no need to update a migration after run rake db:migrate , you should make a new migration to do the change you want to your db schema
and remember to
remove the added line form the old migration file as it might raise errors if you decided to rollback this migration
Rails 4.0 easy way to add single or multiple column
https://gist.github.com/pyk/8569812
You can also do this ..
rails g migration add_column_to_users list_id:string
then rake db:migrate
also add :list_id attribute in your user controller ;
for more detail check out http://guides.rubyonrails.org/active_record_migrations.html
If you already have files in your migrate folder, you could just add column you want there(just type the code), delete development.sqlite or whatever represents your db file, and run rake db:migrate.
It will then create a new sqlite file with new column in table, and you can check it in schema.rb
So, basically, everything you did seems good, except you didn't delete your database file.
Doing this seems the easiest for me, all though you will lose all the files in your database. If you're just testing and developing Rails app, this works.
Can anyone comment if there is something wrong with this approach, besides what i wrote?
Edit: I actually found an answer about that here
Editing Existing Rails Migrations is a good idea?

Renaming original migration file in Rails after doing the rename_table_migration

I happened to create a Query model in Rails and recently found out that this is one of the reserved words now..
I renamed the table using a new migration file and renamed all the files that were created (name of new model - Plot)
Question: is it OK to rename the original migration file (20111228212521_create_queries.rb) to 20111228212521_create_plots.rb)
and everything inside the old file:
class CreateQueries < ActiveRecord::Migration
def change
create_table :queries do |t|
t.string :name
t.text :content
t.timestamps
end
end
end
to
class CreatePlots < ActiveRecord::Migration
def change
create_table :plots do |t|
t.string :name
t.text :content
t.timestamps
end
end
end
??
I just don't want too many migration files and also worried that there may be some errors when I switch to production..
You can change the migration file name, but you have to perform a few steps:
rake db:rollback to the point that queries table is rolled back.
Now change the name of migration file, also the contents.
Change the name of any Model that may use the table.
rake db:migrate
The short answer is to just make another migration file.
Migration files are meant to keep track of each and every change to the database. So, you're encouraged to make small one-off changes in a separate file. I can't speak for your situation, but in my situation, when I make a mistake like this, I simply create a new migration file and don't check the old migration file into source control. This way the errant changes are only on my local db and don't get into prod/dev/staging.
Aside from rolling back, and especially useful for when you need to rename a migration from early on in production you can now in Rails 4 create a new migration to rename it.
$rails generate migration RenamesFooBarr
and then in the method of the new migration add
rename_table :old_migration_name, :new_migration name
like this:
class RenamesFooBar < ActiveRecord::Migration
def change
rename_table :old_foo_bar_name, :new_foo_bar_name
end
end
This will effectively take care of all the indexes as well in the up and down since ActiveRecord recognizes the rename_table
source: http://api.rubyonrails.org/classes/ActiveRecord/Migration.html
Simply, do like this
Rollback the migration for that queries. i.e rake db:rollback
Change migration file, class name and the content of it.
Finally, Migrate the database. i.e rake db:migrate

Rails DB Migration - How To Drop a Table?

I added a table that I thought I was going to need, but now no longer plan on using it. How should I remove that table?
I've already run migrations, so the table is in my database. I figure rails generate migration should be able to handle this, but I haven't figured out how yet.
I've tried:
rails generate migration drop_tablename
but that just generated an empty migration.
What is the "official" way to drop a table in Rails?
You won't always be able to simply generate the migration to already have the code you want. You can create an empty migration and then populate it with the code you need.
You can find information about how to accomplish different tasks in a migration here:
http://api.rubyonrails.org/classes/ActiveRecord/Migration.html
More specifically, you can see how to drop a table using the following approach:
drop_table :table_name
Write your migration manually. E.g. run rails g migration DropUsers.
As for the code of the migration I'm just gonna quote Maxwell Holder's post Rails Migration Checklist
BAD - running rake db:migrate and then rake db:rollback will fail
class DropUsers < ActiveRecord::Migration
def change
drop_table :users
end
end
GOOD - reveals intent that migration should not be reversible
class DropUsers < ActiveRecord::Migration
def up
drop_table :users
end
def down
fail ActiveRecord::IrreversibleMigration
end
end
BETTER - is actually reversible
class DropUsers < ActiveRecord::Migration
def change
drop_table :users do |t|
t.string :email, null: false
t.timestamps null: false
end
end
end
First generate an empty migration with any name you'd like. It's important to do it this way since it creates the appropriate date.
rails generate migration DropProductsTable
This will generate a .rb file in /db/migrate/ like 20111015185025_drop_products_table.rb
Now edit that file to look like this:
class DropProductsTable < ActiveRecord::Migration
def up
drop_table :products
end
def down
raise ActiveRecord::IrreversibleMigration
end
end
The only thing I added was drop_table :products and raise ActiveRecord::IrreversibleMigration.
Then run rake db:migrate and it'll drop the table for you.
Warning: Do this at your own risk, as #z-atef and #nzifnab correctly point out, Rails will not be aware of these changes, your migration sequence fill fail and your schema will be different from your coworkers'. This is meant as a resource for locally tinkering with development only.
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(:table_name)
And done, worked for me!
You need to to create a new migration file using following command
rails generate migration drop_table_xyz
and write drop_table code in newly generated migration file (db/migration/xxxxxxx_drop_table_xyz) like
drop_table :tablename
Or if you wanted to drop table without migration, simply open rails console by
$ rails c
and execute following command
ActiveRecord::Base.connection.execute("drop table table_name")
or you can use more simplified command
ActiveRecord::Migration.drop_table(:table_name)
rails g migration drop_users
edit the migration
class DropUsers < ActiveRecord::Migration
def change
drop_table :users do |t|
t.string :name
t.timestamps
end
end
end
rake db:migrate
The simple and official way would be this:
rails g migration drop_tablename
Now go to your db/migrate and look for your file which contains the drop_tablename as the filename and edit it to this.
def change
drop_table :table_name
end
Then you need to run
rake db:migrate
on your console.
I wasn't able to make it work with migration script so I went ahead with this solution. Enter rails console using the terminal:
rails c
Type
ActiveRecord::Migration.drop_table(:tablename)
It works well for me. This will remove the previous table. Don't forget to run
rails db:migrate
I think, to be completely "official", you would need to create a new migration, and put drop_table in self.up. The self.down method should then contain all the code to recreate the table in full. Presumably that code could just be taken from schema.rb at the time you create the migration.
It seems a little odd, to put in code to create a table you know you aren't going to need anymore, but that would keep all the migration code complete and "official", right?
I just did this for a table I needed to drop, but honestly didn't test the "down" and not sure why I would.
you can simply drop a table from rails console.
first open the console
$ rails c
then paste this command in console
ActiveRecord::Migration.drop_table(:table_name)
replace table_name with the table you want to delete.
you can also drop table directly from the terminal. just enter in the root directory of your application and run this command
$ rails runner "Util::Table.clobber 'table_name'"
You can roll back a migration the way it is in the guide:
http://guides.rubyonrails.org/active_record_migrations.html#reverting-previous-migrations
Generate a migration:
rails generate migration revert_create_tablename
Write the migration:
require_relative '20121212123456_create_tablename'
class RevertCreateTablename < ActiveRecord::Migration[5.0]
def change
revert CreateTablename
end
end
This way you can also rollback and can use to revert any migration
Alternative to raising exception or attempting to recreate a now empty table - while still enabling migration rollback, redo etc -
def change
drop_table(:users, force: true) if ActiveRecord::Base.connection.tables.include?('users')
end
You can't simply run drop_table :table_name, instead you can create an empty migration by running:
rails g migration DropInstalls
You can then add this into that empty migration:
class DropInstalls < ActiveRecord::Migration
def change
drop_table :installs
end
end
Then run rails db:migrate in the command line which should remove the Installs table
The solution was found here
Open you rails console
ActiveRecord::Base.connection.execute("drop table table_name")
ActiveRecord::Base.connection.drop_table :table_name
if anybody is looking for how to do it in SQL.
type rails dbconsole from terminal
enter password
In console do
USE db_name;
DROP TABLE table_name;
exit
Please dont forget to remove the migration file and table structure from schema
I needed to delete our migration scripts along with the tables themselves ...
class Util::Table < ActiveRecord::Migration
def self.clobber(table_name)
# drop the table
if ActiveRecord::Base.connection.table_exists? table_name
puts "\n== " + table_name.upcase.cyan + " ! "
<< Time.now.strftime("%H:%M:%S").yellow
drop_table table_name
end
# locate any existing migrations for a table and delete them
base_folder = File.join(Rails.root.to_s, 'db', 'migrate')
Dir[File.join(base_folder, '**', '*.rb')].each do |file|
if file =~ /create_#{table_name}.rb/
puts "== deleting migration: " + file.cyan + " ! "
<< Time.now.strftime("%H:%M:%S").yellow
FileUtils.rm_rf(file)
break
end
end
end
def self.clobber_all
# delete every table in the db, along with every corresponding migration
ActiveRecord::Base.connection.tables.each {|t| clobber t}
end
end
from terminal window run:
$ rails runner "Util::Table.clobber 'your_table_name'"
or
$ rails runner "Util::Table.clobber_all"
Helpful documentation
In migration you can drop table by:
drop_table(table_name, **options)
options:
:force
Set to :cascade to drop dependent objects as well. Defaults to false
:if_exists
Set to true to only drop the table if it exists. Defaults to false
Example:
Create migration for drop table, for example we are want to drop User table
rails g migration DropUsers
Running via Spring preloader in process 13189
invoke active_record
create db/migrate/20211110174028_drop_users.rb
Edit migration file, in our case it is db/migrate/20211110174028_drop_users.rb
class DropUsers < ActiveRecord::Migration[6.1]
def change
drop_table :users, if_exist: true
end
end
Run migration for dropping User table
rails db:migrate
== 20211110174028 DropUsers: migrating ===============================
-- drop_table(:users, {:if_exist=>true})
-> 0.4607s
the best way you can do is
rails g migration Drop_table_Users
then do the following
rake db:migrate
Run
rake db:migrate:down VERSION=<version>
Where <version> is the version number of your migration file you want to revert.
Example:-
rake db:migrate:down VERSION=3846656238
Drop Table/Migration
run:-
$ rails generate migration DropTablename
exp:- $ rails generate migration DropProducts
if you want to drop a specific table you can do
$ rails db:migrate:up VERSION=[Here you can insert timestamp of table]
otherwise if you want to drop all your database you can do
$rails db:drop
Run this command:-
rails g migration drop_table_name
then:
rake db:migrate
or if you are using MySql database then:
login with database
show databases;
show tables;
drop table_name;
If you want to delete the table from the schema perform below operation --
rails db:rollback

Resources