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).
Чак


35

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

some_string.classify.constantize

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`
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.