Home » Ruby » How to check if a class already exists in Ruby

How to check if a class already exists in Ruby

Posted by: admin November 30, 2017 Leave a comment

Questions:

How do I check if a class already exists in Ruby?

My code is:

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

I was thinking of using:

eval "#{nameofclass}ancestors.     ....."
Answers:

You can use Module.const_get to get the constant referred to by the string. It will return the constant (generally classes are referenced by constants). You can then check to see if the constant is a class.

I would do something along these lines:

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

Also, if possible I would always avoid using eval when accepting user input; I doubt this is going to be used for any serious application, but worth being aware of the security risks.

Questions:
Answers:

perhaps you can do it with defined?

eg:

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

Note: the Class check is required, for example:

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

To answer the original question:

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

Questions:
Answers:

You can avoid having to rescue the NameError from Module.const_get if you are looking the constant within a certain scope by calling Module#const_defined?("SomeClass").

A common scope to call this would be Object, eg: Object.const_defined?("User").

See: “Module“.

Questions:
Answers:
defined?(DatabaseCleaner) # => nil
require 'database_cleaner'
defined?(DatabaseCleaner) # => constant

Questions:
Answers:

Class names are constants. You can use the defined? method to see if a constant has been defined.

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

You can read more about how defined? works if you’re interested.

Questions:
Answers:

Here’s a more succinct version:

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

Questions:
Answers:
Kernel.const_defined?("Fixnum") # => true

Questions:
Answers:

Here’s something I sometimes do to tackle this very issue. You can add the following methods to the String class like so:

class String
    def to_class
        Kernel.const_get self
    rescue NameError 
        nil
    end

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

Then:

'String'.to_class
=> String
'unicorn'.to_class
=> nil
'puppy'.is_a_defined_class?
=> false
'Fixnum'.is_a_defined_class?
=> true

Questions:
Answers:

I used this to see if a class was loaded at runtime:

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

Questions:
Answers:

In just one line, I would write:

!!Module.const_get(nameofclass) rescue false

that will return trueonly if the given nameofclass belongs to a defined class.

Questions:
Answers:

I assume you’ll take some action if the class is not loaded.

If you mean to require a file, why not just check the output of require?

require 'already/loaded'  
=> false

Questions:
Answers:

If you want something packaged, the finishing_moves gem adds a class_exists? method.

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