web-dev-qa-db-fra.com

Comment obtenir uniquement le nom de la classe sans espace de nom

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?

18
ironsand

La manière canonique de faire cela est d'appeler Object # class et Module # nom . Par exemple:

bar.class.name.split('::').last
#=> "Bar"
10
Todd A. Jacobs

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
34
Uelb

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.

3
Ed de Almeida

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.

1
Cary Swoveland