Il y a une classe comme celle-ci.
module Foo
class Bar
end
end
Et je veux obtenir le nom de classe Bar
sans Foo
.
bar = Foo::Bar.new
bar.class.to_s.match('::(.+)$'){ $1 }
Je pourrais obtenir le nom de la classe avec ce code, mais je ne pense pas que ce soit le meilleur moyen de l'obtenir.
Existe-t-il un meilleur moyen d'obtenir le nom de la classe sans espace de nom?
La manière canonique de faire cela est d'appeler Object # class et Module # nom . Par exemple:
bar.class.name.split('::').last
#=> "Bar"
Si vous utilisez Rails, vous pouvez réellement utiliser la méthode demodulize
sur la classe String . http://apidock.com/Rails/String/demodulize
bar.class.name.demodulize
Je crois que cela fonctionnerait bien aussi:
module Foo
class Bar
end
end
bar = Foo::Bar.new
print bar.class.to_s.split('::').last
Cela se traduirait par
Bar
Je pense aussi que ce serait un peu plus rapide que l'évaluation des expressions régulières, mais je ne suis pas sûr à ce sujet et je n'ai pas effectué de test de référence.
Supposons que nous ayons le module suivant Foo
:
module Foo
class Bar
end
class Tar
end
module Goo
class Bar
end
end
end
Si vous ne savez pas quelles classes sont contenues dans Foo
, procédez comme suit:
a = ObjectSpace.each_object(Class).with_object([]) { |k,a|
a << k if k.to_s.start_with?("Foo::") }
#=> [Foo::Tar, Foo::Goo::Bar, Foo::Bar]
Voir ObjectSpace :: each_object .
Vous pouvez ensuite faire ce que vous souhaitez avec le tableau a
. Peut-être voudrez-vous limiter cela aux classes dont le nom se termine par "Bar"
:
b = a.select { |k| k.to_s.end_with?("Bar") }
#=> [Foo::Goo::Bar, Foo::Bar]
Si vous voulez la partie des noms qui exclut "Foo ::" (bien que je ne puisse pas imaginer pourquoi), c'est une simple manipulation de chaîne:
b.map { |k| k.to_s["Foo::".size..-1] }
#=> ["Goo::Bar", "Bar"]
ou
b.map { |k| k.to_s[/(?<=\AFoo::).*/]
#=> ["Goo::Bar", "Bar"] }
Notez qu'il n'y a pas d'objet Bar
ou Goo::Bar
.