2016-10-31 19 views
5

このようなクラスがあります。名前空間を持たないクラス名だけを取得する方法

module Foo 
    class Bar 
    end 
end 

そして、私はFooなしBarのクラス名を取得したいです。

bar = Foo::Bar.new 
bar.class.to_s.match('::(.+)$'){ $1 } 

私はこのコードでクラス名を得ることができましたが、これを得るには最良の方法だとは思いません。

名前空間を持たないクラスの名前を取得するより良い方法はありますか?

+1

_Sidenote_:あなたの正規表現は 'Fooの::バー:: Baz'と2とより多くのネスティングレベルを持つ任意のクラスに間違った結果を生成します。 – mudasobwa

答えて

6

これを行う正規の方法は、Object#classModule#nameを呼び出すことです。たとえば:あなたはクラスがFooに含まれているかわからない場合、あなたは次のことを行う可能性があります

module Foo 
    class Bar 
    end 
    class Tar 
    end 
    module Goo 
    class Bar 
    end 
    end 
end 

bar.class.name.split('::').last 
#=> "Bar" 
2

私は、これはあまりにも正常に動作と考えている:

module Foo 
    class Bar 
    end 
end 

bar = Foo::Bar.new 

print bar.class.to_s.split('::').last 

これは

Bar 

につながる私もそれが正規表現の評価よりも少し速いだろうと考えていますが、私はありませんこれについては確かに私はベンチマークを行っていない。

1

たちは、次のモジュールFooがあるとし

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] 

ObjectSpace::each_objectを参照してください。

あなたは配列aであなたが望むことができます。あなたがしたい場合

b = a.select { |k| k.to_s.end_with?("Bar") } 
    #=> [Foo::Goo::Bar, Foo::Bar] 

は「フー::」除外(なぜ私が想像することはできませんが)名前の部分は、それは単純な文字列です:おそらく、あなたが名前"Bar"で終わるclasesにこれを狭めたいです操作:なしオブジェクトBarまたはGoo::Barがないことを

b.map { |k| k.to_s["Foo::".size..-1] } 
    #=> ["Goo::Bar", "Bar"] 

または

b.map { |k| k.to_s[/(?<=\AFoo::).*/] 
    #=> ["Goo::Bar", "Bar"] } 

注意。

関連する問題