Bagaimana cara membuat instance kelas dari nama string di ruby?

121

Saya memiliki nama kelas dan saya ingin membuat turunan dari kelas itu sehingga saya dapat mengulang melalui setiap atribut rails yang ada dalam skema kelas itu.

Bagaimana saya akan melakukan itu?

  1. Saya memiliki nama sebagai string kelas yang ingin saya periksa
  2. Saya rasa saya perlu membuat instance kelas agar saya bisa
  3. Ulangi atributnya dan cetaklah.
mhenrixon.dll
sumber
1
Ini pertanyaan yang bagus. Terima kasih telah menanyakannya dan menyelamatkan saya dari penggunaaneval
David West

Jawaban:

219

Di rel, Anda bisa melakukan:

clazz = 'ExampleClass'.constantize

Dalam ruby ​​murni:

clazz = Object.const_get('ExampleClass')

dengan modul:

module Foo
  class Bar
  end
end

Anda akan menggunakan

> clazz = 'Foo::Bar'.split('::').inject(Object) {|o,c| o.const_get c}
  => Foo::Bar 
> clazz.new
  => #<Foo::Bar:0x0000010110a4f8> 
Wes
sumber
4
Perhatikan bahwa Object.const_get('Foo::Bar')tidak akan berhasil, sementara constantizeakan.
Marc-André Lafortune
Terima kasih, bangun untuk bertanya tentang itu karena masalah Admin :: Pengguna :) Pukul saya untuk itu.
mhenrixon
Hai @Wes, ini sangat membantu, terima kasih! Pertanyaan singkat - apakah ini juga akan berfungsi untuk modul bersarang? Misalnya,clazz = 'Foo::Bar::Uber'
iaacp
@iaacp Ya, ini akan bekerja untuk sebanyak mungkin level yang Anda miliki.
Wes
15

Sangat sederhana di Rails: gunakan String#constantize

class_name = "MyClass"
instance = class_name.constantize.new
edgerunner
sumber
6
Untuk Rails bukan Ruby :(
ethicalhack3r
Salin implementasi ActiveSupport tanpa malu- malu jika Anda belum menggunakan Rails
edgerunner
6

Coba ini:

Kernel.const_get("MyClass").new

Kemudian untuk mengulang melalui variabel instance objek:

obj.instance_variables.each do |v|
  # do something
end
mbreining
sumber
Terima kasih, karena saya benar-benar harus mengulang melalui kolom model rekaman aktif, ini tidak akan berfungsi untuk saya, tetapi akan berguna dalam aplikasi ruby ​​"murni" saya :)
mhenrixon
1
Lihat ActiveRecord # atribut () dan / atau 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"

Di ruby ​​2.0 dan, mungkin rilis sebelumnya, Object.const_getakan secara rekursif melakukan pencarian di namespace seperti Foo::Bar. Contoh di atas adalah ketika namespace diketahui sebelumnya dan menyoroti fakta yang const_getdapat dipanggil pada modul secara langsung dan bukan secara eksklusif Object.

A-Dubb
sumber
Anda harus menambahkan penjelasan untuk ini. Sampai sekarang, itu hanya satu blok kode.
Josh Crozier