61

I have this testingdatabase which, by now, is stuffed with junk. Now I've done a few Table.destroy_all commands in the rails console which deletes all records and dependencies which is awesome. However; I'd like to truncate everything so the ID's etc. start at 1 again. Is there any way in Rails 3?

CaptainCarl
  • 3,411
  • 6
  • 38
  • 71

12 Answers12

161

The accepted answer only works if you need to recreate the whole database.
To drop a single table (with the callbacks) and to get the IDs to start from 1:

Model.destroy_all # Only necessary if you want to trigger callbacks.
ActiveRecord::Base.connection.execute("TRUNCATE #{table_name} RESTART IDENTITY")

If you are using Sqlite, it does not support truncate so do the following:

Model.destroy_all # Only necessary if you want to trigger callbacks.
ActiveRecord::Base.connection.execute("Delete from #{table_name}")
ActiveRecord::Base.connection.execute("DELETE FROM SQLITE_SEQUENCE WHERE name='#{table_name}'")
lulalala
  • 17,572
  • 15
  • 110
  • 169
Ravi Sankar Raju
  • 2,850
  • 3
  • 18
  • 16
  • 2
    Your answer is correct when one table should be truncated (And i thank you for that) I've chosen Yam Marcovic answer as the accepted answer because i did ask for "everything" to be truncated. – CaptainCarl Nov 01 '12 at 09:28
  • 4
    Thanks for the vote. The whole db requirement was not clear from the question ! Just for the information, rake db:drop will drop the database. If the requirement is to just truncate all tables, u can run ActiveRecord::Base.connection.tables.collect{|table_name| ActiveRecord::Base.connection.execute("TRUNCATE #{table_name}")}. Although it might not take care of the callbacks, i guess it is not necessary as we are truncating all the tables. – Ravi Sankar Raju Nov 01 '12 at 10:06
  • destroy_all will call destroy on each record, which is quite different than truncating the table. From Docs: # Destroys the records matching +conditions+ by instantiating each # record and calling its +destroy+ method. Each object's callbacks are # executed (including :dependent association options and # +before_destroy+/+after_destroy+ Observer methods). Returns the # collection of objects that were destroyed; each will be frozen, to # reflect that no changes should be made (since they can't be # persisted). – justingordon Sep 03 '13 at 02:22
  • 4
    In Postgres, the 2nd command doesn't actually reset the auto increment value for the ID column. For that, you need to "TRUNCATE table_name RESTART IDENTITY"). See http://stackoverflow.com/a/7610991/271454 – Doug Johnston Oct 27 '14 at 18:11
  • 5
    Just to clarify: For MySQL/MariaDB: `ActiveRecord::Base.connection.execute("TRUNCATE #{table_name}")` For PostgreSQL: `ActiveRecord::Base.connection.execute("TRUNCATE #{table_name} RESTART IDENTITY")` – Sergio Gonzalez Sep 14 '17 at 19:30
  • To quote the table name: `c = ActiveRecord::Base.connection; c.execute("TRUNCATE #{c.quote_table_name(Model.table_name)}")`. Add `RESTART IDENTITY`/`CASCADE` whenever necessary. – x-yuri Jun 07 '21 at 07:18
30
Model.connection.truncate(Model.table_name)
18

This worked for me - ActiveRecord::Base.connection.execute("TRUNCATE table_name")

Ramkumar K R
  • 195
  • 5
  • 13
Mr.Quack
  • 331
  • 2
  • 5
8

Rails 6.0+ add new method: truncate_tables

ActiveRecord::Base.connection.truncate_tables([:table1_name, :table2_name])

https://stackoverflow.com/a/68618256/7438710

YaEvan
  • 660
  • 9
  • 12
  • I think it is `ActiveRecord::Base.connection.truncate_tables(*[:table1_name, :table2_name])` or `ActiveRecord::Base.connection.truncate_tables(:table1_name, :table2_name)` – new2cpp Oct 11 '22 at 06:32
2

Simply rebuild the database on the next test run (this will happen automatically after dropping it).

rake db:drop RAILS_ENV=test

Yam Marcovic
  • 7,953
  • 1
  • 28
  • 38
2

You could also do rake db:rollback STEP=3 RAILS_ENV=test

where 3 represents the number of migrations that you have in db/migrate. In example: If I have in

db/migrate
20140121065542_create_users.rb
20140121065710_create_profiles.rb
20140121065757_create_articles.rb
20140121065900_create_comments.rb
20140121065929_create_categories.rb

So I have 5 migrations in total to remove. If I do rake db:rollback STEP=5 RAILS_ENV=test all the tables will be drop from my TEST database and if I remove RAILS_ENV=test than all the ENVIRONNMENT (production, test, development) tables will be delete and it cleans also db/shema.rb file from it's migration datas.

Papouche Guinslyzinho
  • 5,277
  • 14
  • 58
  • 101
2

rake db:reset will perform rake db:drop db:setup. In other words, drop the database and setup the database again.

Source

Eva
  • 4,397
  • 5
  • 43
  • 65
2

Assuming you're using MySQL or Postgre and not SQlite3 (which doesn't support TRUNCATE), you could do the following:

MyModel.connection_pool.with_connection { |c| c.truncate(MyModel.table_name) }

Note that this would not invoke ActiveRecord callbacks.

jsears
  • 4,511
  • 2
  • 31
  • 36
0

I used below code to truncate all tables

ActiveRecord::Base.establish_connection
ActiveRecord::Base.connection.tables.each do |table|
  next if table == 'schema_migrations'

  case ActiveRecord::Base.connection.adapter_name.downcase.to_sym
    when :mysql2 , :postgresql
      ActiveRecord::Base.connection.execute("TRUNCATE #{table}")
      ActiveRecord::Base.connection.execute("TRUNCATE #{table} RESTART IDENTITY")
    when :sqlite
      ActiveRecord::Base.connection.execute("DELETE FROM #{table}")
  end
end
Dave
  • 4,376
  • 3
  • 24
  • 37
0

You can use ModelName.delete_all in rails console.

0

Rails 6 added the rake task db:truncate_all. See docs

You can invoke it from the rails console with:

ActiveRecord::Tasks::DatabaseTasks.truncate_all
Neil Atkinson
  • 724
  • 6
  • 10
-5

(A bit late to the party, I know)

Asking to do this in the console:

2.1.2 :001 > Post.all.each do |post|
2.1.2 :002 >   post.destroy!
2.1.2 :003 > end

Works as well...

This essentially loops through all of the posts and destroys them. It does not change your auto increment value though...

Same logic should work for Rails 3 as well (though I am using Rails 4)

  • 5
    1. Don't use `each`, use `find_each`. It makes sure you willn't get a billion of records in one query 2. Don't use the loop, if you need to just delete the records from DB (without running any callbacks). Just do `Post.delete_all` – Kukunin Mar 13 '15 at 21:11
  • original post was about how to reset auto-indexing to zero (truncate) database table using rails. this answer only deletes records – Anton Semenichenko Mar 22 '18 at 10:24
  • 1. This could take hours to be done as you are deleting record by record. 2. This will no reset any sequences in SQL, 3. all.each will load all Posts to memory... so if you have mln of records it can cill your app performance – Argonus Jun 21 '18 at 12:38