mirror of https://github.com/rails/rails
Performance: faster Object.subclasses_of
This commit is contained in:
parent
06b6f435cb
commit
6c970d79a0
|
@ -3,17 +3,18 @@ class Object
|
|||
Class.remove_class(*subclasses_of(*superclasses))
|
||||
end
|
||||
|
||||
# Exclude this class unless it's a subclass of our supers and is defined.
|
||||
# We check defined? in case we find a removed class that has yet to be
|
||||
# garbage collected. This also fails for anonymous classes -- please
|
||||
# submit a patch if you have a workaround.
|
||||
def subclasses_of(*superclasses) #:nodoc:
|
||||
subclasses = []
|
||||
|
||||
# Exclude this class unless it's a subclass of our supers and is defined.
|
||||
# We check defined? in case we find a removed class that has yet to be
|
||||
# garbage collected. This also fails for anonymous classes -- please
|
||||
# submit a patch if you have a workaround.
|
||||
ObjectSpace.each_object(Class) do |k|
|
||||
if superclasses.any? { |superclass| k < superclass } &&
|
||||
(k.name.blank? || eval("defined?(::#{k}) && ::#{k}.object_id == k.object_id"))
|
||||
subclasses << k
|
||||
superclasses.each do |sup|
|
||||
ObjectSpace.each_object(class << sup; self; end) do |k|
|
||||
if k != sup && (k.name.blank? || eval("defined?(::#{k}) && ::#{k}.object_id == k.object_id"))
|
||||
subclasses << k
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -38,9 +38,9 @@ class ClassTest < Test::Unit::TestCase
|
|||
@parent = eval("class D; end; D")
|
||||
@sub = eval("class E < D; end; E")
|
||||
@subofsub = eval("class F < E; end; F")
|
||||
assert @parent.subclasses.all? { |i| [@sub.to_s, @subofsub.to_s].include?(i) }
|
||||
assert_equal 2, @parent.subclasses.size
|
||||
assert_equal [@subofsub.to_s], @sub.subclasses
|
||||
assert_equal [], @subofsub.subclasses
|
||||
assert_equal [@sub.to_s, @subofsub.to_s].sort, @parent.subclasses.sort
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue