アプリケーションの中にあるModelのレコードを数を調べたかったので、それをプログラムから動的に行う方法を考えてみた。

ActiveRecord::Baseのサブクラスを取ってくればいいはずだ!ということで、ActiveRecord::Base.subclassesを使うことにした。確認にはrails consoleを使った。

1% rails c
2ActiveRLoading development environment (Rails 4.1.0)
3
4Frame number: 0/5
5[1] pry(main)> ActiveRecord::Base.subclasses
6=> [User (call 'User.connection' to establish a connection)]
7[2] pry(main)>

UserというModelが取れたことはわかる。でも実はこのアプリケーションには他にもモデルがあるはずなのに、この方法では取れてこないようだ。

Railsのdevelopment環境ではデフォルトでModelがキャッシュされないようになっている(当たり前だよね、毎回新しく読みなおすようになっていないと変更が即座に反映されないから)。そのためか、最初に呼び出すまでObjectSpaceに存在しないらしく、subclassesメソッドでも取れてこないようだ。

というわけで、強制的にロードしてやる!

1Dir.glob(File.join(Rails.root, "app", "models", "**", "*.rb")).each {|f| require f}
2ActiveRecord::Base.subclasses
3# => [User (...), Hoge, Piyo] という感じで得られる

レコード数を調べるとしたらコレでOK。

1Dir.glob(File.join(Rails.root, "app", "models", "**", "*.rb")).each {|f| require f}
2ActiveRecord::Base.subclasses.map(&:count).inject(&:+)
3# => 1024 などなど

production環境では予めModelもロードされているので2行目のコードだけで調べられるはず。