ruby преобразовать имя класса из строки в фактический класс

87

Как мне вызвать класс из строки, содержащей это имя класса внутри него? (Думаю, я мог бы сделать случай / когда, но это кажется уродливым.)

Причина, по которой я спрашиваю, заключается в том, что я использую acts_as_commentable, среди прочего, плагин, и они хранят commentable_type в виде столбца. Я хочу иметь возможность вызывать любой конкретный комментируемый класс, чтобы сделать с find(commentable_id)ним что-то.

Спасибо.

несортированный
источник

Ответы:

131

Я думаю, что ты хочешь constantize

Это конструкция RoR. Я не знаю, есть ли один для рубинового ядра

Джейми Вонг
источник
идеально, это именно то, что я искал.
несортированный
40
Для простого Ruby вы должны использовать Module.const_get. Преимущество constantizeзаключается в том, что он работает даже с глубоко вложенными пространствами имен, поэтому вы можете сделать 'Functional::Collections::LazyList'.constantizeи получить класс LazyList из модуля Collections в модуле Functional, тогда как с помощью const_getвам нужно будет сделать что-то вроде 'Functional::Collections::LazyList'.split('::').reduce(Module, :const_get).
Чак
45
"Object".constantize # => Object
jtbandes
источник
Обратите внимание, что .constantizeэто метод Rails, вы не найдете его в простом Ruby
Эдгар Ортега,
35

Для данной строки сначала вызовите classify, чтобы создать имя класса (все еще строку), затем вызовите constantize, чтобы попытаться найти и вернуть константу имени класса (обратите внимание, что имена классов являются константами ).

some_string.classify.constantize
user664833
источник
10
Вы должны использовать camelize вместо classify, поскольку classify предназначен для имен таблиц и не очень хорошо обрабатывает множественное число.
Питер Браун
1
Благодарность! замечательно!
duykhoa
2
Ваш ответ действительно ценен, но вы должны использовать "titleize" для имени таблицы, которое включает пробел, и удалить пробел из строки, чтобы сделать полное имя класса значением.
SSR
22

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

В простом Ruby Module.const_getможно найти вложенные константы. Например, имеющий следующую структуру:

module MyModule
  module MySubmodule
    class MyModel
    end
  end
end

Вы можете использовать его следующим образом:

Module.const_get("MyModule::MySubmodule::MyModel")
MyModule.const_get("MySubmodule")
MyModule::MySubmodule.const_get("MyModel")
Эдгар Ортега
источник
7

Когда ActiveSupport доступен (например, в Rails): String#constantizeили String#safe_constantize, что есть "ClassName".constantize.

В чистом Ruby: Module#const_getобычно Object.const_get("ClassName").

В последних версиях Ruby оба работают с константами, вложенными в модули, например в Object.const_get("Outer::Inner").

скали
источник
6

Если вы хотите преобразовать строку в актуальное имя класса для доступа к модели или любому другому классу

str = "group class"

> str.camelize.constantize 'or'
> str.classify.constantize 'or'
> str.titleize.constantize

Example :
  def call_me(str)
    str.titleize.gsub(" ","").constantize.all
  end

Call method : call_me("group class")

Result:
  GroupClass Load (0.7ms) SELECT `group_classes`.* FROM `group_classes`
ССР
источник