2009-10-21 5 views
1

donné:Comment obtenir dynamiquement les modules imbriqués à partir d'un objet?

module A 
    class B 
    end 
end 

b = A::B.new 

nous voulons être en mesure d'obtenir l'imbrication du module comme un tableau. Cela peut être fait si la classe est connue à l'avance. par exemple:

module A 
    class B 
    def get_nesting 
     Module.nesting # => [A::B, A] 
    end 
    end 
end 

Mais, comment le faire pour un objet quelconque, afin que nous puissions faire quelque chose comme ceci:

module Nester 
    def get_nesting 
    Module.nesting 
    end 
end 

b.get_nesting 

Si nous essayons ci-dessus, nous obtenons un tableau vide.

Répondre

1

Vous cherchez quelque chose comme ça?

module D 
    A = 10 
    class E 
    module F 
    end 
    end 
end 

def all_nestings(top) 
    result = [] 
    workspace = [top] 
    while !workspace.empty? 
    item = workspace.shift 
    result << item 
    item.constants.each do |const| 
     const = item.const_get(const) 
     next unless const.class == Class || const.class == Module 
     workspace.push const 
    end 
    end 
    result 
end 

puts all_nestings(D).inspect # => [D, D::E, D::E::F] 
+0

Nice. Presque fonctionne ... comment cela fonctionnerait-il pour un objet où vous ne connaissiez pas les modules, etc? Serait-ce une question de dire: e = D :: E.new all_nestings (e.class) .inspect ? – suranyami

0

Je viens en cloque Class.hierarchy, qui commence à Object et retourne chaque étape de classe tout le chemin jusqu'à la classe en question.

class Class 
    def hierarchy 
    name.split('::').inject([Object]) {|hierarchy,name| 
     hierarchy << hierarchy.last.const_get(name) 
    } 
    end 
end 

Compte tenu de cette définition de la classe:

module A 
    module B 
    module C 
     class D 
     def self.hello 
      "hello world!" 
     end 
     end 
    end 
    end 
end 

Il retourne ceci:

A::B::C::D.hierarchy # => [Object, A, A::B, A::B::C, A::B::C::D] 

Remarque, ce sont les modules et les classes elles-mêmes, pas seulement des chaînes. Par exemple,

A::B::C::D.hierarchy.last.hello # => "hello world!" 

Un exemple avec une classe du monde réel:

require 'net/smtp' 
Net::SMTP.hierarchy # => [Object, Net, Net::SMTP] 
Questions connexes