37

Ruby でシンボルまたは文字列を取り、それを同じ名前のクラスに変換する方法はありますか?

たとえば、次のようなクラスがある場合

class Bob
  def talk
     puts "Hi, I'm bob"
  end
end

そして、コードの別の場所にあるメソッドにシンボル :bob が渡されています。何らかの方法でそれをクラス Bob に変換できますか? 多分何かのような

b = :Bob.new
b.talk

または、これに似た何かを行う方法はありますか?

4

7 に答える 7

55

これを行うには多くの方法があります。コンテキストがないと、「最善の」方法を選択できなくなります。ここにいくつかの方法があります。

Kernel.const_get(:Bob)

eval(:Bob.to_s)

Kernel.const_get(:bob.to_s.capitalize)
于 2009-08-05T21:30:21.363 に答える
44

レール

Rails でのみ使用します。

文字列の場合:

"Module".constantize #=> Module
"Class".constantize #=> Class

記号付き:

:module.to_s.classify.constantize #=> Module
:open_struct.to_s.classify.constantize #=> OpenStruct

複数単語のシンボルを扱っている場合は#classify、チェーンに追加して、定数のすべての部分の大文字化を適切に処理する必要があります。

http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-constantize

于 2009-08-05T20:53:38.830 に答える
10

:foo_bar を FooBar に変換したい場合、私が見た解決策はどれも機能しません。それがあなたが探しているものなら:

:foo_bar.to_s.split("_").collect(&:capitalize).join.constantize
=> FooBar

それが誰かを助けることを願っています。

于 2010-11-27T05:03:29.567 に答える
5

NameSpace.const_get(classname)クラスオブジェクトを返します(classnameにクラスの名前が含まれていると仮定します-クラスではない定数の名前が含まれている場合、その定数の値を返します)。トップレベルの名前空間はオブジェクトなので、次のことができますObject.const_get(:Bob).new

于 2009-08-05T20:39:39.267 に答える
3
class Bob
end

def create(name)
  return eval("#{name}.new")
end

b = create(:Bob)
puts b.class
于 2009-08-05T20:42:57.900 に答える
2

モジュール/名前空間のサポートを含む同様のものを探しているときに思いついたものを次に示します。

['foo', 'bar'].inject {|r,e| "#{r.classify}::#{e.classify}"}.constantize

プロデュース

=> Foo::Bar

ただし、これにはRailsが必要であり、もちろん、配列に複数の要素がある場合にのみ機能します。

これはかなり単純に思えるので、何かが欠けていると確信しています。なぜこれが良いアプローチではないのか、誰かアドバイスしてくれませんか?

ありがとう!

于 2012-08-15T17:37:14.983 に答える