ruby mengubah nama kelas dalam string menjadi kelas sebenarnya

88

Bagaimana cara memanggil kelas dari string yang berisi nama kelas di dalamnya? (Saya kira saya bisa melakukan kasus / kapan tetapi itu tampaknya jelek.)

Alasan saya bertanya adalah karena saya menggunakan acts_as_commentableplugin tersebut, dan ini menyimpan commentable_type sebagai kolom. Saya ingin dapat memanggil kelas tertentu yang dapat dikomentari untuk melakukannya find(commentable_id).

Terima kasih.

tidak disortir
sumber

Jawaban:

132

Saya pikir apa yang Anda inginkan adalah constantize

Itu adalah konstruksi RoR. Saya tidak tahu apakah ada satu untuk inti ruby

Jamie Wong
sumber
sempurna, itulah yang saya cari.
disortir
40
Untuk Ruby biasa, Anda akan menggunakan Module.const_get. Keuntungannya constantizeadalah ia bekerja bahkan dengan ruang nama yang sangat bersarang, sehingga Anda bisa melakukan 'Functional::Collections::LazyList'.constantizedan mendapatkan kelas LazyList dari modul Koleksi di modul Fungsional, sedangkan dengan const_get, Anda harus melakukan sesuatu seperti 'Functional::Collections::LazyList'.split('::').reduce(Module, :const_get).
Chuck
46
"Object".constantize # => Object
jtbandes
sumber
Harap dicatat bahwa .constantizeini adalah metode Rails, Anda tidak akan menemukannya di Ruby biasa
Edgar Ortega
35

Diberikan string, panggilan pertama classify untuk membuat nama kelas (masih string), kemudian panggil constantize untuk mencoba menemukan dan mengembalikan nama kelas konstan (perhatikan bahwa nama kelas adalah konstanta ).

some_string.classify.constantize
pengguna664833
sumber
10
Anda harus menggunakan camelize daripada classify karena classify adalah untuk nama tabel dan tidak menangani pluralisasi dengan baik.
Peter Brown
2
Jawaban Anda sangat berharga, tetapi Anda harus menggunakan "titleize" untuk nama tabel yang menyertakan spasi, dan hapus spasi dari string untuk membuat arti nama kelas lengkap.
SSR
22

Saya tahu ini adalah pertanyaan lama tetapi saya hanya ingin meninggalkan catatan ini, mungkin berguna untuk orang lain.

Di Ruby biasa, Module.const_getdapat menemukan konstanta bersarang. Misalnya, memiliki struktur berikut:

module MyModule
  module MySubmodule
    class MyModel
    end
  end
end

Anda dapat menggunakannya sebagai berikut:

Module.const_get("MyModule::MySubmodule::MyModel")
MyModule.const_get("MySubmodule")
MyModule::MySubmodule.const_get("MyModel")
Edgar Ortega
sumber
7

Ketika ActiveSupport tersedia (misalnya di Rails): String#constantizeatau String#safe_constantize, itulah"ClassName".constantize .

Di Ruby murni:, Module#const_getbiasanyaObject.const_get("ClassName") .

Dalam rubi baru-baru ini, keduanya bekerja dengan konstanta bersarang di modul, seperti di Object.const_get("Outer::Inner").

skalee
sumber
6

Jika Anda ingin mengubah string menjadi nama kelas sebenarnya untuk mengakses model atau kelas lainnya

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`
SSR
sumber