Як створити екземпляр класу з імені рядка в рубіні?


121

У мене є ім'я класу, і я хочу створити екземпляр цього класу, щоб я міг переглядати кожен атрибут rails, який присутній у схемі цього класу.

Як би я пішов робити це?

  1. У мене є ім'я як рядок класу, який я хочу перевірити
  2. Напевно, мені потрібно створити екземпляр класу, щоб я міг
  3. Перегляньте його атрибути та роздрукуйте їх.

1
Це чудове питання. Дякуємо, що запитали і врятували мене від використанняeval
Девід Вест,

Відповіді:


219

У рейках ви можете просто зробити:

clazz = 'ExampleClass'.constantize

У чистому рубіні:

clazz = Object.const_get('ExampleClass')

з модулями:

module Foo
  class Bar
  end
end

ви б використали

> clazz = 'Foo::Bar'.split('::').inject(Object) {|o,c| o.const_get c}
  => Foo::Bar 
> clazz.new
  => #<Foo::Bar:0x0000010110a4f8> 

4
Зауважте, що Object.const_get('Foo::Bar')не буде працювати, поки constantizeбуде.
Марк-Андре Лафортун

Дякую, прокинувся, щоб запитати про це через проблему адміністратора :: Користувач :) Побий мене.
mhenrixon

Привіт @ Вітаю, це було корисно, дякую! Швидке запитання - чи може це працювати і для вкладених модулів? Наприклад,clazz = 'Foo::Bar::Uber'
iaacp

@iaacp Так, він працюватиме на стільки ж вкладених рівнів, скільки у вас.
Уес


6

Спробуйте це:

Kernel.const_get("MyClass").new

Потім провести цикл через змінні екземпляри об'єкта:

obj.instance_variables.each do |v|
  # do something
end

Дякую, оскільки мені справді доводиться перебирати стовпчики активної моделі запису, для мене це не спрацює, але це стане в нагоді в моїх «чистих» програмах на
рубінах

1
Ознайомтеся з атрибутами ActiveRecord # () та / або ActiveRecord # attribute_names ().
mbreining


5
module One
  module Two
    class Three
      def say_hi
        puts "say hi"
      end
    end
  end
end

one = Object.const_get "One"

puts one.class # => Module

three = One::Two.const_get "Three"

puts three.class # => Class

three.new.say_hi # => "say hi"

У рубін 2.0 і, можливо , більш ранніх версіях, Object.const_getбуде рекурсивно виконати пошук на через простір імен , як Foo::Bar. Наведений вище приклад - коли простір імен відомий заздалегідь і підкреслює той факт, що const_getможна викликати модулі безпосередньо на відміну від виключно на Object.


До цього слід додати пояснення. На даний момент це лише блок коду.
Джош Крозьє
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.