アプリケーションの中にあるModelのレコードを数を調べたかったので、それをプログラムから動的に行う方法を考えてみた。
ActiveRecord::Baseのサブクラスを取ってくればいいはずだ!ということで、ActiveRecord::Base.subclasses
を使うことにした。確認にはrails console
を使った。
% rails c
ActiveRLoading development environment (Rails 4.1.0)
Frame number: 0/5
[1] pry(main)> ActiveRecord::Base.subclasses
=> [User (call 'User.connection' to establish a connection)]
[2] pry(main)>
User
というModelが取れたことはわかる。でも実はこのアプリケーションには他にもモデルがあるはずなのに、この方法では取れてこないようだ。
Railsのdevelopment環境ではデフォルトでModelがキャッシュされないようになっている(当たり前だよね、毎回新しく読みなおすようになっていないと変更が即座に反映されないから)。そのためか、最初に呼び出すまでObjectSpaceに存在しないらしく、subclasses
メソッドでも取れてこないようだ。
というわけで、強制的にロードしてやる!
Dir.glob(File.join(Rails.root, "app", "models", "**", "*.rb")).each {|f| require f}
ActiveRecord::Base.subclasses
# => [User (...), Hoge, Piyo] という感じで得られる
レコード数を調べるとしたらコレでOK。
Dir.glob(File.join(Rails.root, "app", "models", "**", "*.rb")).each {|f| require f}
ActiveRecord::Base.subclasses.map(&:count).inject(&:+)
# => 1024 などなど
production環境では予めModelもロードされているので2行目のコードだけで調べられるはず。