2012-03-08 2 views
2

に名前でクラスを取得します私はので、私は、データベースからクラス名(ClassOneまたはClassTwoのいずれか)を取得していますし、私はそのクラスにルビー

do_somethingを呼び出したい二つのクラス

class ClassOne 
    def do_something 
     [...] 
    end 
end 

class ClassTwo 
    def do_something 
     [...] 
    end 
end 

を持っています

class_name = "ClassOne" 

を持っていると私はCLASS_NAMEがある場合ClassOne.do_somethingまたはClassTwo.do_somethingを呼び出したいことは、 "ClassTwo" に等しいです。私があれば、簡単な条件を使用してそれを行うことはできません

、私は多くのクラスがあり、クラスが呼び出す前に存在しているかどうかをチェックしています。..

はそれを行うためにそこに方法は何ですか? Railsのために

Kernel.const_get('ClassOne').do_something 

:バニラRuby用

答えて

6

'ClassOne'.constantize.do_something 
+0

私は '' Class:0x9c9026c>( '' NoMethodError) 'に対して' '未定義のメソッド 'do_something'を取得しています。 – applechief

+1

クラスメソッドとして使用するには、 'def self.do_something'する必要があります。 – sgtFloyd

+2

またはクラスをそのまま残して、 'Kernel.const_get( 'ClassOne')を呼び出します。new.do_something' /' 'ClassOne'.constantize.new.do_something' –

2

利用できる場合は、activesupportのからconstantizeを使用してクラスに任意の文字列を変換することができますが、ユーザーが送信することができれば、これは例外を引き起こす可能性があります問題の文字列

case (with_class) 
when 'ClassOne', 'ClassTwo' 
    with_class.constantize.do_something 
else 
    raise "Um, what are you doing?" 
end 

同じことがハッシュや配列が有効なクラスを定義し、それに応じて[]またはinclude?のいずれかでテストで達成することができます:case使用する方が安全かもしれません。

+1

ユーザーがあなたのクラスをすべて発見できる潜在的なセキュリティ問題文字列を生成できる場合は、定数の値を明らかにする。 –

+0

文字列はユーザ​​ー生成されません。将来私は新しいクラスを追加しているかもしれませんし、新しいクラスが利用可能になるたびにこのコードのこの部分を更新したくありません。 – applechief

+0

同じRubyプロセス内でクラスを変数として渡すことができるので、必要はありませんそれらを文字列として保持する。 'using_class = condition? 'のようなことはかなり一般的です。 ClassA:ClassB'を呼び出し、その変数自体があたかもクラスそのものであるかのように操作します。ダックタイピングはこれを可能にします。 – tadman

-1

eval("#{classname}.do_something")

注:def self.do_somethingにコードを変更する必要があり、そうでなければ、これらはインスタンスメソッドです。これはあなたの意図であるように見えます。

+0

いいえ、してください。 'eval'は、あなたがこのようなことをするためにちょっとしたことをするのではありません。これは単に他の方法がない場合に最適です。 – tadman