Listar subclasses não funciona no script/console rubi?
-
19-09-2019 - |
Pergunta
Isso funciona:
>> class Foo
>> def xyz()
>> Foo.subclasses
>> end
>> end
=> nil
>> class Bar < Foo
>> end
=> nil
>> class Quux < Bar
>> end
=> nil
>> Foo.new.xyz()
=> ["Quux", "Bar"]
Mas isso não. User
é uma aula no meu aplicativo.
>> 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
Mas isso faz!
>> Foo.subclasses
=> ["Quux", "Bar"]
O que está acontecendo aqui? Como eu listaria as subclasses de User
?
Solução
As subclasses são substituídas e feitas protegidas em base.rb. Ver 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 (A linha 1855 define subclasses de método, a linha 1757 o torna protegido).
Você pode fazer o mesmo para o usuário que fez para Foo: Adicione um método xyz ().
Outras dicas
Você não precisa redeclare (como em Resposta de Tim) ou fornecer um método auxiliar (como em Resposta de Rutger). Você só precisa alterar a permissão do método (que, sendo um método de classe, requer algumas travessuras):
class User < ActiveRecord::Base
class <<self
public :subclasses
end
end
Apenas para contornar os direitos de acesso e não alterar nada, considere usar o método #send que tem acesso a métodos privados.
User.send(:subclasses)
tables = ActiveRecord::Base.connection.tables {|t| t.classify.constantize rescue nil}.compact
subclasses = tables.map do |table|
table.singularize.classify.constantize
end