这有效:
>> class Foo
>> def xyz()
>> Foo.subclasses
>> end
>> end
=> nil
>> class Bar < Foo
>> end
=> nil
>> class Quux < Bar
>> end
=> nil
>> Foo.new.xyz()
=> ["Quux", "Bar"]
但事实并非如此。 User
是我应用程序中的一个类。
>> 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
但是这样做了!
>> Foo.subclasses
=> ["Quux", "Bar"]
这里发生了什么?我如何列出User
的子类?
答案 0 :(得分:2)
子类被重写并在base.rb中受到保护。请参阅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(第1855行定义方法子类,第1757行使其受保护)。
您可以为用户执行与Foo相同的操作:添加xyz()方法。
答案 1 :(得分:1)
您无需重新声明(如在Tim's answer中)或提供辅助方法(如Rutger's answer中所述)。您只需要更改方法的权限(作为类方法,需要一些恶作剧):
class User < ActiveRecord::Base
class <<self
public :subclasses
end
end
答案 2 :(得分:1)
只是为了解决访问权限而不改变任何内容,请考虑使用可以访问私有方法的#send方法。
User.send(:subclasses)
答案 3 :(得分:0)
tables = ActiveRecord::Base.connection.tables {|t| t.classify.constantize rescue nil}.compact
subclasses = tables.map do |table|
table.singularize.classify.constantize
end