Как создать экземпляр класса из строкового имени в рубине?


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

Привет, @Wes, это было полезно, спасибо! Быстрый вопрос - будет ли это работать и для вложенных модулей? Например,clazz = 'Foo::Bar::Uber'
iaacp

@iaacp Да, он будет работать для любого количества вложенных уровней.
Вес


6

Попробуй это:

Kernel.const_get("MyClass").new

Затем, чтобы перебрать переменные экземпляра объекта:

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

Спасибо, так как мне действительно нужно прокручивать столбцы активной модели записи, это не сработает для меня, но будет полезно в моих "чистых" рубиновых приложениях :)
mhenrixon

1
Проверьте ActiveRecord # attributes () и / или 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"

В ruby ​​2.0 и, возможно, в более ранних версиях он Object.const_getбудет рекурсивно выполнять поиск в таких пространствах имен, как Foo::Bar. В приведенном выше примере пространство имен известно заранее и подчеркивается тот факт, что он const_getможет вызываться непосредственно в модулях, а не только в Object.


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