tags:

views:

1927

answers:

8

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.     ....."
+3  A: 

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")
Sam Saffron
+1  A: 

Class names are constants. You can use the defined? keyword 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.

Tate Johnson
This will not work for defined? 'String', though, which really was the question.
Banang
A: 

This is a very good blog post on this subject, explaining in detail how to solve your problem. This post also deals with the issue of namespaces, which is one you can't very well ignore.

Find it here

Best of luck!

Banang
+14  A: 

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.

Olly
A: 
defined?(DatabaseCleaner) # => nil
require 'database_cleaner'
defined?(DatabaseCleaner) # => constant
Rob
+1  A: 

The first answer, from Olly, is the right one.

All the other answers which have suggested to use "defined?(x)" have not considered that the original problem was: how can I test if a class given by name already exists?

So if we are given a class by name (i.e., a string), testing with defined? on the string will not be very useful.

Instead, we need to transform the "class name" into the class Ruby object; and to do that, we need Module.const_get; as the first answer indicated.

Raul Parolari
A: 

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")

http://ruby-doc.org/core/classes/Module.html#M001691

stcorbett
A: 

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
Hugh