web-dev-qa-db-ja.com

Rubyにクラスが既に存在するかどうかを確認する方法

Rubyにクラスが既に存在するかどうかを確認するにはどうすればよいですか?

私のコードは:

puts "enter the name of the Class to see if it exists"   
nameofclass=gets.chomp  
eval (" #{nameofclass}......  Not sure what to write here")

私は使用することを考えていました:

eval "#{nameofclass}ancestors.     ....."
61
Jimmy

Module.const_getを使用して、文字列が参照する定数を取得できます。定数を返します(通常、クラスは定数によって参照されます)。その後、定数がクラスであるかどうかを確認できます。

私はこれらの線に沿って何かをするでしょう:

def class_exists?(class_name)
  klass = Module.const_get(class_name)
  return klass.is_a?(Class)
rescue NameError
  return false
end

また、可能であれば、ユーザー入力を受け入れるときにevalの使用を常に避けます。私はこれがどんな深刻なアプリケーションにも使用されるとは思いませんが、セキュリティ上のリスクに注意する価値があります。

72
Olly

おそらくあなたは定義された状態でそれを行うことができますか?

例えば:

if defined?(MyClassName) == 'constant' && MyClassName.class == Class  
   puts "its a class" 
end

注:次のようなクラスチェックが必要です。

Hello = 1 
puts defined?(Hello) == 'constant' # returns true

元の質問に答えるには:

puts "enter the name of the Class to see if it exists"
nameofclass=gets.chomp
eval("defined?(#{nameofclass}) == 'constant' and #{nameofclass}.class == Class")
47
Sam Saffron

Module#const_defined?("SomeClass")を呼び出すことにより、特定のスコープ内で定数を探している場合、_Module.const_get_からNameErrorを救出する必要がなくなります。

これを呼び出す一般的なスコープはObjectです。例:Object.const_defined?("User")

Module 」を参照してください。

27
stcorbett
defined?(DatabaseCleaner) # => nil
require 'database_cleaner'
defined?(DatabaseCleaner) # => constant
11
Rob

クラス名は定数です。 defined?メソッドを使用して、定数が定義されているかどうかを確認できます。

defined?(String)    # => "constant"
defined?(Undefined) # => nil

興味があるなら defined? がどのように機能するかについてもっと読むことができます。

8
Tate Johnson

より簡潔なバージョンは次のとおりです。

def class_exists?(class_name)
  eval("defined?(#{class_name}) && #{class_name}.is_a?(Class)") == true
end

class_name = "Blorp"
class_exists?(class_name)
=> false

class_name = "String"
class_exists?(class_name)
=> true
6
Mike Bethany
Kernel.const_defined?("Fixnum") # => true
6
lfender6445

この問題に取り組むために私が時々することがあります。次のメソッドをStringクラスに次のように追加できます。

class String
    def to_class
        my_const = Kernel.const_get(self)
        my_const.is_a?(Class) ? my_const : nil
    rescue NameError 
        nil
    end

    def is_a_defined_class?
        true if self.to_class
    rescue NameError
        false
    end
end

次に:

'String'.to_class
=> String
'Unicorn'.to_class
=> nil
'puppy'.is_a_defined_class?
=> false
'Fixnum'.is_a_defined_class?
=> true
5
Afz902k

1行だけで、次のように記述します。

!!Module.const_get(nameofclass) rescue false

指定されたtrueが定義されたクラスに属する場合にのみnameofclassを返します。

2

これを使用して、実行時にクラスがロードされたかどうかを確認しました。

def class_exists?(class_name)
  ObjectSpace.each_object(Class) {|c| return true if c.to_s == class_name }
  false
end
1
Hugh

パッケージ化する場合は、 finishing_moves gemは class_exists? メソッド。

class_exists? :Symbol
# => true
class_exists? :Rails
# => true in a Rails app
class_exists? :NonexistentClass
# => false
0
Frank Koehl

クラスがロードされていない場合は、何らかのアクションを起こすと思います。

ファイルが必要な場合は、単にrequireの出力を確認してみませんか?

require 'already/loaded'  
=> false
0
stackdump

おそらく私のコードがサブモジュールのスコープ内にあるため、上記の答えはどれもうまくいきませんでした。

私はclass_exists?メソッドは、 「クラスが定義されているかどうかを確認するにはどうすればいいですか?」 に対する(= /// =)Fred Wilmoreの応答にあるコードを使用します。

def class_exists?(name)
   name.constantize.is_a?(Class) rescue false # rubocop:disable Style/RescueModifier
end

好奇心のための完全なコード:

module Some
  module Thing
    def self.build(object)
      name = "Some::Thing::#{object.class.name}"
      class_exists?(name) ? name.constantize.new(object) : Base.new(object)
    end

    def self.class_exists?(name)
      name.constantize.is_a?(Class) rescue false # rubocop:disable Style/RescueModifier
    end

    private_class_method :class_exists?
  end
end

引数として渡されたオブジェクトのクラスに応じてオブジェクトを構築するファクトリーとして使用します。

Some::Thing.build(something)
=> # A Some::Thing::Base object
Some::Thing.build(something_else)
=> # Another object, which inherits from Some::Thing::Base
0
Goulven