Question

Cela fonctionne:

>> class Foo 
>>   def xyz()
>>     Foo.subclasses
>>   end
>> end
=> nil
>> class Bar < Foo
>> end
=> nil
>> class Quux < Bar
>> end
=> nil
>> Foo.new.xyz()
=> ["Quux", "Bar"]

Mais cela ne fonctionne pas. User est une classe dans mon 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

Mais cela ne!

>> Foo.subclasses
=> ["Quux", "Bar"]

Qu'est-ce qui se passe ici? Comment puis-je énumérer les sous-classes de User?

Était-ce utile?

La solution

est sous-classes surchargées et communiquées protégées dans base.rb. Voir 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 (ligne 1855 définit des sous-classes de méthodes, ligne 1757, il est protégé).

Vous pouvez faire la même chose pour l'utilisateur que vous avez fait pour Foo:. Ajouter une méthode xyz ()

Autres conseils

Vous n'avez pas besoin redéclarer (comme dans la réponse de Tim ) ou fournir une méthode d'assistance (comme dans réponse Rutger). Vous avez juste besoin de changer l'autorisation de la méthode (qui, étant une méthode de classe, nécessite quelques manigances):

class User < ActiveRecord::Base

  class <<self
    public :subclasses
  end

end

Juste pour contourner les droits d'accès et ne pas changer quoi que ce soit, pensez à utiliser la méthode #send qui a accès à des méthodes privées.

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top