55

I have a model & a table which I no longer need in my App, I could leave them there but I would like to remove them to keep things tidy.

I'm trying to figure out the best way to remove them with out messing around with my migrations & db/schema.rb files & any side effect it could have on my production environment, my app is on Heroku. I'm using PostgreSQL on both my local machine & heroku.

So far I've found two ways to do this but am not sure which is the best method/ rails way?

Method 1

I thought about just going in to my database & dropping the table & then destroying the model.

rails db
DROP TABLE table_name
\q
rails destroy model model_name

If I do this what will happen to the migrations I have for this model/table? I have two migrations for this model, a timestamp_create_modelname & a add_attribute_to_table name.

Also will this method update the db/schema.rb file?

When I push the App to Heroku I suspect the Model will be removed but the table will remain in place, is there a heroku command to drop a table.

Method Two

Another way I read about was to generate a new migration to drop the table & then destroy the model.

rails generate migration drop_tablename

& then update the below file:

db/migrate/timestamp_drop_tablename (updated in response to Dan Wich's answer below)

class DropTablename < ActiveRecord::Migration
  def up
    drop_table :tablename
  end

  def down
    create_table :tablename do |t|
      t.string :table_column
      t.references :anothertable

      t.timestamps        
    end
    add_index :tablenames, :anothertable_id
  end
end

& then in the terminal:

rake db:migrate
rails destroy model model_name
rake db:migrate
git add .
git commit -m "removed table/model_name"
git push heroku master
heroku run rake db:migrate
heroku restart

This seems to be the best method but what happens to the older migration files? Will they remain & update db/schema every time I run rake db:migrate only to be overridden by db/migrate/timestamp_drop_tablename?

I'm happy to experiment with the second method but would like someone with someone with experience to weigh in & tell me the rails ways for doing this.

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Holly
  • 7,462
  • 23
  • 86
  • 140

2 Answers2

33

The second method is the ideal way to handle this: your migration files are meant to represent how your database has changed over time. The older migration files will remain in your project (in case, hypothetically, you wanted to roll back to an older version), but Rails will not run them when you rake db:migrate because it knows they've already been run (based on data in the database's schema_migrations table).

Your schema.rb will just be updated once to reflect that your database no longer contains that table.

One minor tweak to your code: your migration file should drop the table in the up method, and ideally recreate it in the down method. The "up" signifies that your migration drops the table to move forward in time, and if the migration is rolled back, the down method will be run.

Dan Wich
  • 4,923
  • 1
  • 26
  • 22
  • Thanks for the explanation Dan, I'm going to try this when I get home. I updated the code in my question for the migration file as sugested, do you mind looking over it, is this what I should be putting in the `def down` method? – Holly Mar 27 '13 at 10:20
  • Yep, exactly right. That way if something goes wrong, you can `rake db:rollback` and end up with the same database structure as before. – Dan Wich Mar 27 '13 at 21:45
  • i am trying to destroy a model in Rails 4.2.4. once I run rails destroy model, i can't run rake db:migrate. i keep seeing a NameError: uninitialized constant User. what did i miss? – srrvnn Jan 20 '16 at 06:08
13

I know this is an old thread. More often than not, you want to remove not only the model, but routes, controller and views associated with that model as well. To do that, run these

rails g migration DropYourModel
rails destroy scaffold YourModelName

Edit your migration file to drop_table and then run

rake db:migrate

If the model happens to be defined in a namespace, e.g., admins, replace the first command with

rails destroy scaffold admins/YourModelName
Elad Amsalem
  • 1,490
  • 1
  • 12
  • 14
MichaelZ
  • 1,890
  • 2
  • 13
  • 8
  • Agreed, this is the correct way to handle it in rails 4. But you probably want to generate migration first, as it seems second command don't automatically add drop table if model was deleted. – Fedcomp Jul 01 '15 at 09:56
  • 1
    Be careful with `destroy scaffold` because it will remove the migration file that set up the table originally, this will break any migrations that operate on that table later, so if the project was being set up from scratch the migrations wont work. – Toby 1 Kenobi Mar 02 '17 at 06:41