web-dev-qa-db-ja.com

Rubyシンボルからクラスへ

Rubyで、記号または文字列を取得して同じ名前のクラスに変換する方法はありますか?

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

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

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

b = :Bob.new
b.talk

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

34
intargc

これを行うには多くの方法があります。あなたの文脈の欠如は、「最良の」方法を選ぶことを不可能にします。ここにいくつかの方法があります。

Kernel.const_get(:Bob)

eval(:Bob.to_s)

Kernel.const_get(:bob.to_s.capitalize)
53
August Lilleaas

Rails

Railsのみ。で使用

文字列を使用する場合:

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

記号付き:

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

multi-Word記号を扱っている場合は、チェーンに#classifyを追加して、の大文字の使用を適切に処理する必要があります。定数のすべての部分。

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

40
Dan Frade

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

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

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

10
Lance Olsen

NameSpace.const_get(classname)はクラスオブジェクトを返します(classnameにクラスの名前が含まれていると仮定します-クラスではない定数の名前が含まれている場合、その定数の値を返します)。最上位の名前空間はObjectであるため、Object.const_get(:Bob).newを実行できます。

5
sepp2k
class Bob
end

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

b = create(:Bob)
puts b.class
3
Tim Hoolihan

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

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

を生成します

=> Foo::Bar

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

これはかなり単純に見えるので、私は何かを見逃していると確信しています、なぜこれが良いアプローチではないのか誰かがアドバイスしたいと思いますか?

ありがとう!

2
Joe

私の場合、以下の両方の例が機能しましたが、名前空間を忘れる必要もありません。

  Object.const_get("ModuleName::#{class_model_name}")

または

  Kernel.const_get("ModuleName::#{class_model_name}").
0
FredyK