0

Is there a command/query I can run in the rails console to count all records of all models that are in the DB?

(Using Rails 5 and Postgres)

angst
  • 49
  • 6

3 Answers3

1

All active record models are descendants of ApplicationRecord, so you can do...

ApplicationRecord.descendants.map(&:count).inject(:+)

Note that outside production, classes tend to be loaded only when required, so if you're interested in getting the count fort a non-production environment (e.g. development) you would need to modify the configuation to ensure all records are loaded. In config/environment/development.rb set

config.eager_load = true

You can leave it as such but it will slow down your development server startup time. Personally I don't find it a problem but it depends on the size of your application.

Note that... as pointed out by max in the comments, if you do reload! in your console, your ApplicationRecord.descendants will be an empty array.

SteveTurczyn
  • 36,057
  • 6
  • 41
  • 53
  • There is a really big problem with this in development as `ApplicationRecord.descendants` is lazy loading and will only show classes that have been referenced. – max Jan 16 '20 at 18:51
  • @max good point. If op is concerned about production then of course not an issue. I'll edit my answer. – SteveTurczyn Jan 17 '20 at 13:53
  • There are still issues with just setting `config.eager_load = true` as `ApplicationRecord.descendants` relies on the class cache. For example if you run `reload!`. `ApplicationRecord.descendants` is suddenly empty again. – max Jan 17 '20 at 14:08
0

You can do this

ActiveRecord::Base.connection.tables.each do |table|
  next if table.classify.safe_constantize.nil?
  count = table.classify.safe_constantize.count
  puts "#{table} -> #{count}"
end
Gautam
  • 1,754
  • 1
  • 14
  • 22
0

This is not a one-liner but this handles non-conventional models where the table name does not match the class name. It uses ApplicationRecord.descents but handles the caveat that its lazy loading:

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true

  # ApplicationRecord.descendants is lazy loading so we must
  # force rails to load all the models
  def self.eager_load_descendants!
    Dir.glob(Rails.root.join('app', 'models', '**', '*.rb')).map do |pn|
      require_dependency pn
    end
  end

  def self.count_all_models
    eager_load_descendants!
    descendants.each_with_object({}) do |model, hash|
      hash[model.model_name.plural] = model.count
    end
  end
end

It returns a hash:

{"users"=>5, "rainbows"=>2, "ponies"=>0}

If you want a total sum you can just do:

irb(main):002:0> {"users"=>5, "rainbows"=>2, "ponies"=>0}.values.sum
=> 7
max
  • 96,212
  • 14
  • 104
  • 165
  • Also if you just want a row count of all the tables you can query [pg_stat_user_tables](https://stackoverflow.com/a/2611745/544825). – max Jan 16 '20 at 21:23