Differences in subclasses function between Rails 2 and 3
Let's say I have somethi开发者_如何转开发ng like this
class Major < ActiveRecord::Base
def self.my_kids
self.subclasses.collect {|type| type.name}.sort
end
end
class MinorOne < Major
end
class MinorTwo < Major
end
In Rails 2.3 I could call Major.my_kids and get back an array of the subclass names, but in Rails 3.0.3 I get back an empty array, unless I load the subclasses first. This seems wrong to me, am I missing something or is this new to Rails 3?
There's no difference that I know of between Rails 2 and 3 concerning the use of the subclasses
method. You might have believed it was working previously because the subclasses were already loaded. As Rails load most files dynamically a parent class couldn't know about any class derived from it unless it is defined in the same file. The easiest way to ensure all models are loaded, you can simply call require
on all files in the app/models
directory:
Dir.glob(RAILS_ROOT + '/app/models/*.rb').each { |file| require file }
One other thing to note is that the subclasses
method doesn't work after issuing the reload!
command in the Rails console.
The reason why you're getting an empty array in Rails 3 is likely because Rails 3 uses autoloading.
If you open the Rails console and you reference the name of the subclasses, then run your 'subclasses' method on the parent class, you'll see it works. This is because Rails 3 only loads the classes into memory that you've referenced, when you reference them.
The way I ended up forcing my classes to load from a library I created under /lib was with the following code I added into the method that depends on those classes:
# load feature subclasses
my_classes_path = File.expand_path(File.dirname(__FILE__)) + "/my_classes"
if File.directory?(my_classes_path)
Dir.glob(my_classes_path + "/*.rb").each do |f|
load f
end
end
精彩评论