4

Right now my approach is to list every table one at a time and call .delete_all on it. Which is repetitive:

Example:

#app/db/seeds.rb

Blog.delete_all
Person.delete_all
Post.delete_all
User.delete_all
Author.delete_all
Book.delete_all
# ... on and on for all the tables

And then of course run rake db:seed which would clear out all the records for those above tables.

Is there a command that does exactly what I want:

  • deletes all the records from all the tables without deleting the tables themselves?

Or, is there a way to iterate through all my tables and .delete_all on each table?

Nakilon
  • 34,866
  • 14
  • 107
  • 142
Neil
  • 4,578
  • 14
  • 70
  • 155
  • Check out [this](http://stackoverflow.com/questions/7755389/rake-task-to-truncate-all-tables-in-rails-3) question on truncating all tables in the database. – Piotr Kruczek Jul 02 '15 at 14:14

5 Answers5

7

Is there a command that does exactly what I want: deletes all the records from all the tables?

bundle exec rake db:reset

This is functionally equivalent to rake db:drop db:setup.

Don't want delete the tables?

#app/db/seeds.rb
[Blog, Person, Post, User, Author, Book].each do |table|
  ActiveRecord::Base.connection.execute("TRUNCATE #{table.table_name}")
end

SQL-TRUNCATE

Roman Kiselenko
  • 43,210
  • 9
  • 91
  • 103
  • 1
    This solution deletes the tables and then reloads them from the schema, and then also runs the `seeds.rb` file. I don't like that it unnecessarily deletes the tables, but it seems like the best option. An answer below does not delete the tables, but if the seed data adds new records it does not start the `id` back at `1` for each table. Instead it continues counting up where it left off. – Neil Jul 02 '15 at 15:17
  • 2
    @Neil If you're on Postgresql, `ActiveRecord::Base.connection.reset_pk_sequence!('table_name')` allows you to reset the `id` without deleting the table. – fylooi Jul 02 '15 at 16:14
5

As the OP has asked to delete all the record in all the tables, and not all the tables. So you can get all the tables by: ActiveRecord::Base.connection.tables, it will give you all you tables in the database.

puts ActiveRecord::Base.connection.tables                                       

ActiveRecord::Base.connection.tables.each do |table|                            
  next if table.match(/\Aschema_migrations\Z/)                                  
  klass = table.singularize.camelize.constantize                                
  klass.delete_all                                                              
end

Edit:

If you do want id to start again from 1, when you create a new instance after emptying the table, you have to destroy the table, and re-create it.

ActiveRecord::Migration.drop_table(:users)
ActiveRecord::Migration.create_table(:users)

And now if you create a new instance of model User, it will start generating ids right from 1. Please note that you need to send the name of the table in drop_table, and create_table functions, while the code that I've written above gives you the name of the class, in this case User. You can get the table name if you have the name of the model:

User.table_name # it will give you "users"
# in above code, you can do:
ActiveRecord::Migration.drop_table(klass.table_name) 
# string and symbol: both type of arguments work here!
Arslan Ali
  • 17,418
  • 8
  • 58
  • 76
  • Only issue is that the `id` does not start back at `1` for all the tables. Instead it continues counting off at the last id count. So If I had 50 records in the `blogs` table, and then I `rake db:seed` with the above command: If I create a new blog that blog's `id` will not be `1` but instead will be `51`. – Neil Jul 02 '15 at 15:10
  • 1
    @Neil I've updated my answer again. Start of `id` from `51` is expected behavior. `id` starts again from `1` only when you `destory`, and re-`create` a table, and that's what I've mentioned in my answer's edit. Please check it out. – Arslan Ali Jul 02 '15 at 18:16
4

If you really want to write ruby code to do this, try using ObjectSpace to get every instance of a Class, then select classes which inherit from ActiveRecord::Base

models = ObjectSpace.each_object(Class).select { |klass| klass < ActiveRecord::Base }
models.each{|m|m.delete_all}

However, the answers suggesting different rake tasks, instead of including this in seeds.rb are probably a better solution to your problem.

AJFaraday
  • 2,411
  • 1
  • 16
  • 39
1

If you force rails to load all your models you can then iterate over them

Rails.application.eager_load!

# This only gets direct subclasses, since we are just deleting
# No reason to get their subclasses
models = ActiveRecord::Base.subclasses

models.each(&:delete_all)
Joshua
  • 2,079
  • 20
  • 29
0

I added those lines to my seeds.rb file. With this code, you don't have to bother with referencing manually your models and/or with foreign key constraints (thanks to disable_referential_integrity).

Rails.application.eager_load!
ActiveRecord::Base.connection.disable_referential_integrity do
  ApplicationRecord.descendants.each do |model|
    model.delete_all
  end
end

NB : ApplicationRecord.descendants returns only true application models unlike ActiveRecord::Base.descendants (no more ApplicationRecord, schema_migrations and ar_internal_metadata).

devoh
  • 867
  • 9
  • 13