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


34

Враховуючи рядок, спочатку викличте класифікацію, щоб створити ім’я класу (все ще рядок), потім викличте constantize, щоб спробувати знайти і повернути константу імені класу (зверніть увагу, що імена класів є константами ).

some_string.classify.constantize

10
Вам слід використовувати camelize замість класифікації, оскільки класифікація призначена для імен таблиць і не справляється з плюралізацією дуже добре.
Пітер Браун

1
Дякую! це чудово!
duykhoa

2
Ваша відповідь справді цінна, але ви повинні використовувати "titleize" для назви таблиці, яка включає пробіл, і видалити пробіл із рядка, щоб зробити повне ім'я класу.
РСР

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

В останніх рубінах обидва працюють з константами, вкладеними в модулі, як 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.