ruby converte il nome della classe in stringa nella classe effettiva


87

Come posso chiamare una classe da una stringa contenente il nome della classe al suo interno? (Immagino che potrei fare caso / quando, ma sembra brutto.)

Il motivo per cui lo chiedo è perché sto usando il acts_as_commentableplug-in, tra gli altri, e questi memorizzano commentable_type come colonna. Voglio essere in grado di chiamare qualsiasi particolare classe commentabile per fare una find(commentable_id)su di esso.

Grazie.

Risposte:


131

Penso che quello che vuoi sia constantize

Questo è un costrutto RoR. Non so se ce n'è uno per ruby ​​core


perfetto, è proprio quello che stavo cercando.
non smistato

40
Per un semplice Ruby, useresti Module.const_get. Il vantaggio di constantizeè che funziona anche con spazi dei nomi profondamente nidificati, quindi potresti fare 'Functional::Collections::LazyList'.constantizee ottenere la classe LazyList dal modulo Collections nel modulo Functional, mentre con const_get, dovresti fare qualcosa di simile 'Functional::Collections::LazyList'.split('::').reduce(Module, :const_get).
Chuck

45
"Object".constantize # => Object

Si prega di notare che .constantizeè un metodo Rails, non lo troverete in normale Ruby
Edgar Ortega

34

Data una stringa, prima chiama classify per creare un nome di classe (sempre una stringa), quindi chiama constantize per cercare di trovare e restituire la costante del nome di classe (nota che i nomi di classe sono costanti ).

some_string.classify.constantize

10
Dovresti usare camelize invece di classify poiché classify è per i nomi delle tabelle e non gestisce molto bene la pluralizzazione.
Peter Brown

1
Grazie! è fantastico!
duykhoa

2
La tua risposta è davvero preziosa, ma dovresti usare "titleize" per il nome della tabella che include uno spazio e rimuovere lo spazio bianco dalla stringa per rendere il nome completo della classe.
SSR

22

So che questa è una vecchia domanda, ma voglio solo lasciare questa nota, potrebbe essere utile per altri.

In plain Ruby, Module.const_get può trovare costanti annidate. Ad esempio, con la seguente struttura:

module MyModule
  module MySubmodule
    class MyModel
    end
  end
end

Puoi usarlo come segue:

Module.const_get("MyModule::MySubmodule::MyModel")
MyModule.const_get("MySubmodule")
MyModule::MySubmodule.const_get("MyModel")


6

Se si desidera convertire una stringa in un nome di classe effettivo per accedere al modello oa qualsiasi altra classe

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`
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.