2009-07-27 3 views

ответ

42

, возможно, вы можете сделать это с установленным?

например:

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

Это лучший способ сделать это. Множество случаев в драгоценных камнях нужно делать так же, как это. определены? :: Rails – Brandt

+0

'defined? (MyClassName) == 'constant' && MyClassName.is_a? (Класс)' выглядит более интуитивно понятным. –

+0

Почему «определено? Object.const_get ("array" .capitalize) 'возвращает метод", а я запускаю 'defined? Array 'return" constant "? – kamal

7

Имена классов являются константами. Вы можете использовать метод defined?, чтобы определить, определена ли константа.

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

Вы можете прочитать больше о том, как defined? работает, если вы заинтересованы.

+2

Это не будет работать для определенных? «String», тем не менее, это был действительно вопрос. –

69

Вы можете использовать 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 при приеме пользовательского ввода; Я сомневаюсь, что это будет использоваться для любого серьезного применения, но стоит осознавать риски безопасности.

+0

Для меня было хорошо, если названная вещь была модулем. Используется 'klass.is_a? (Класс) || klass.is_a? (модуль) '. С этим методом работал квалифицированное имя пространства имен. Например, 'class_exists? ('Delayed :: Worker')' Очень приятно. –

11
defined?(DatabaseCleaner) # => nil 
require 'database_cleaner' 
defined?(DatabaseCleaner) # => constant 
23

Вы можете избежать того, чтобы спасти от NameError Module.const_get, если вы ищете постоянную в пределах определенного объема, вызвав Module#const_defined?("SomeClass").

Общей сферой для вызова является объект, например: Object.const_defined?("User").

См. "Module".

+9

это вернет true только в том случае, если класс был загружен. >> Object.const_defined? ("MyClass") # ложная >> MyClass # MyClass >> Object.const_defined? ("MyClass") # правда это, по крайней мере, в случае в консоли Rails, YMMV. – carpeliam

1

Я использовал это, чтобы увидеть, если класс был загружен во время выполнения:

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

Я использовал этот метод, потому что в моем сценарии я не знал, была ли константа ранее создана, и было важно, чтобы она сравнивалась только с объектами класса. Быть способным просто пройти в струне было идеально. Спасибо за то, что вы помогли мне разобраться, очень ценили. – Jurgen

6

Вот более сжато версия:

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 
3

Вот то, что я иногда делаю, чтобы решить эту самую проблему. Вы можете добавить следующие методы к классу струнных так:

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 

Тогда:

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

Это действительно классный способ обойти это, особенно если вы имеете дело с пользовательским вводом в виде строк (ex Rails). Спасибо за эту классную идею! – thegravian

0

Я предполагаю, что вы будете принимать какие-то действия, если не загружен класс.

Если вы хотите потребовать файл, почему бы просто не проверить вывод require?

require 'already/loaded' 
=> false 
1

только в одной строке, я хотел бы написать:

!!Module.const_get(nameofclass) rescue false 

, который будет возвращать true только если данное nameofclass принадлежит к определенному классу.

+0

Это вернет true для любой константы в Модуле (возможно, это все, что я не знаю), а не только для классов. 'Bla =" некоторая строка "; ! Module.const_get (: Bla) rescue false возвращает true. – nash

5
Kernel.const_defined?("Fixnum") # => true 
+1

Это будет возвращать только справедливо только если был загружен класс '' '$ рельсам Ĉ тест Загрузка тестовой среды (Rails 4.2.5.1) 2.2.1: 001> Kernel.const_defined ('ApiProvider') = > false 2.2.1: 002> ApiProvider => ApiProvider 2.2.1: 003> Kernel.const_defined? ('ApiProvider') => true '' ' –

0

Если вы хотите что-то упакованы, то finishing_moves драгоценный камень добавляет метод class_exists?.

class_exists? :Symbol 
# => true 
class_exists? :Rails 
# => true in a Rails app 
class_exists? :NonexistentClass 
# => false 
Смежные вопросы