问题
This works:
>> class Foo
>> def xyz()
>> Foo.subclasses
>> end
>> end
=> nil
>> class Bar < Foo
>> end
=> nil
>> class Quux < Bar
>> end
=> nil
>> Foo.new.xyz()
=> ["Quux", "Bar"]
But this doesn't. User
is a class in my application.
>> User.subclasses
NoMethodError: protected method `subclasses' called for #<Class:0x20b5188>
from [...]/vendor/rails/activerecord/lib/active_record/base.rb:1546:in `method_missing'
from (irb):13
But this does!
>> Foo.subclasses
=> ["Quux", "Bar"]
What's going on here? How would I list the subclasses of User
?
回答1:
subclasses is overridden and made protected in base.rb. See http://www.google.com/codesearch/p?hl=en&sa=N&cd=1&ct=rc#m8Vht-lU3vE/vendor/rails/activerecord/lib/active_record/base.rb&q=active_record/base.rb (line 1855 defines method subclasses, line 1757 makes it protected).
You could do the same for User as you did for Foo: add a xyz() method.
回答2:
You don't need to redeclare (as in Tim's answer) or provide a helper method (as in Rutger's answer). You just need to change the permission of the method (which, being a class method, requires some shenanigans):
class User < ActiveRecord::Base
class <<self
public :subclasses
end
end
回答3:
Just to work around the access rights and not change anything, consider using the #send method that has access to private methods.
User.send(:subclasses)
回答4:
tables = ActiveRecord::Base.connection.tables {|t| t.classify.constantize rescue nil}.compact
subclasses = tables.map do |table|
table.singularize.classify.constantize
end
来源:https://stackoverflow.com/questions/1195531/listing-subclasses-doesnt-work-in-ruby-script-console