Hi,
I have this class:
class MoldItem < ActiveRecord::Base self.abstract_class = true end
And then I have a (currenly unspecified) number of classes such as these:
class StringMoldItem < MoldItem end class LinkMoldItem < MoldItem end
I would like to add a class method to MoldItem that will return all of its subclasses. In the above example, this method would return the Array [StringMoldItem, LinkMoldItem].
I have been able to write this method in several ways that are successful using script/console. But as soon as I try to use the method within my browser (i.e. calling it in a controller) I get unexpected results.
Option 1: def self.subklasses(direct = false) #ensure files are loaded by rails Dir.glob(RAILS_ROOT + '/app/models/*.rb').each { |file| require file }
classes = if direct ObjectSpace.each_object(Class) do |c| next unless c.superclass == self classes << c end else ObjectSpace.each_object(Class) do |c| next unless c.ancestors.include?(self) and (c != self) classes << c end end classes end
Option 2: def self.subklasses Dir.glob(RAILS_ROOT + '/app/models/*.rb').each { |file| require file } @@subclasses[MoldItem] end
Option 3:
def self.inherited other super if defined? super ensure ( @subclasses ||= ).push(other).uniq! end
def self.subklasses Dir.glob(RAILS_ROOT + '/app/models/*.rb').each { |file| require file } @subclasses ||= @subclasses.inject( ) do |list, subclass| list.push(subclass, *subclass.subklasses) end end
Results: when I run MoldItem.subklasses using script/console, I get the correct result for all three options. When I run it from a controller (by visiting a page of my website), the first request after starting mongrel works. However, every subsequent request will return or nil (depending on the option).
I think the problem is a conflict between this line: Dir.glob(RAILS_ROOT + '/app/models/*.rb').each { |file| require file } (which is meant to ensure that the subclasses such as StringMoldItem and LinkMoldItem exist) and rails' fancy way of requiring source files (would that be ActiveSupport::Dependencies#load_missing_constant?).
Do you have any suggestions for how I can dynamically return a list of the subclasses of MoldItem?