6

This question is similar / related to another stack overflow question about Looking up all the descendants of a class in Ruby. A wonderful question full of the information that I was looking for - except that when I drop down into a rails console:

irb(main):001:0> ActiveSupport::DescendantsTracker.descendants(Object)
=>[]
irb(main):002:0> ObjectSpace.each_object(Class).select { |klass| klass < Object }
=> [IRB::Notifier::AbstractNotifier, IRB::Notifier::ErrUnrecognizedLevel, ...]

So, why isn't ActiveSupport::DescendantsTracker returning the descendants of Object? What are the differences in the implementation? The documentation for DescendantsTracker suggests that:

This module provides an internal implementation to track descendants which is faster than iterating through ObjectSpace.

Faster? Ok, it's gotta be faster to return nothing versus something (right?), but it's supposed to return the descendants of the supplied class.

Community
  • 1
  • 1
erroric
  • 991
  • 1
  • 11
  • 22

2 Answers2

3

ActiveSupport::DescendantsTracker.descendants(Object) will be returning blank in your console because the development console doesn't compile your application, it hasn't yet loaded all of the classes and therefore doesn't know about them to output them!

Take a look at this question: RoR: MyModel.descendants returns [] in a view after the first call?

Community
  • 1
  • 1
Matt
  • 13,948
  • 6
  • 44
  • 68
  • I've read the related post and I still don't get it. How do i test this functionality? I've tried setting `config.cache_classes = true` in config\development.rb to no effect... – erroric May 28 '13 at 15:48
  • 1
    Did you try the initializer in the unaccepted answer? `Dir[Rails.root + 'app/models/*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }` – Matt May 28 '13 at 15:49
  • Why do i need to load my application's models to view the descendants of Object? Shouldn't rails already know about them? If i reference the class name in the console, does rails not then load that object? – erroric May 29 '13 at 16:38
  • Sorry... my last comment did not answer the question in your previous comment. I did try it and it did not work - i changed the path to use the location of my class files of the module i would like to get the descendants for. I had to update the line to `Dir[Rails.root + 'lib/modules//*.rb'].map { |f| "::#{File.basename(f, '.*').camelize}".constantize }`. This gives me the expected classes, but still an empty result set when using `ActiveSupport::DescendantsTracker.descendants` while `ObjectSpace` method gives me the expected results. – erroric May 29 '13 at 16:55
  • Over a year later and I come across this again... and the initializer from the comment works. – erroric Sep 12 '14 at 20:24
3

You need to eager load the classes, as stated in: https://github.com/rails/rails/issues/3364

ActionDispatch::Reloader.to_prepare do
  Rails.application.eager_load!
end
sequielo
  • 1,541
  • 1
  • 18
  • 27
  • Interesting... reading through the rails issue - gives an interesting back story to the problem. I believe that using `ActionDispatch::Reloader...` is for rails server in dev mode, but the solution for the console appears to simply be calling `Rails.application.eager_load!`. I'll give both a try. – erroric Oct 07 '13 at 15:54