Ruby konvertiert den Klassennamen in einer Zeichenfolge in eine tatsächliche Klasse

86

Wie rufe ich eine Klasse aus einer Zeichenfolge auf, die diesen Klassennamen enthält? (Ich denke, ich könnte Fall / wann tun, aber das scheint hässlich.)

Der Grund, den ich frage, ist, dass ich acts_as_commentableunter anderem das Plugin verwende und diese den commentable_type als Spalte speichern. Ich möchte in der Lage sein, jede bestimmte kommentierbare Klasse aufzurufen, um eine find(commentable_id)Aktion durchzuführen.

Vielen Dank.

unsortiert
quelle

Antworten:

129

Ich denke was du willst ist constantize

Das ist ein RoR-Konstrukt. Ich weiß nicht, ob es einen für Ruby Core gibt

Jamie Wong
quelle
Perfekt, genau das habe ich gesucht.
unsortiert
40
Für einfaches Ruby würden Sie verwenden Module.const_get. Der Vorteil constantizeist , dass es auch bei tief verschachtelten Namensräumen funktioniert, so dass Sie tun könnten 'Functional::Collections::LazyList'.constantizeund die Klasse LazyList von den Modulsammlungen im Modul Funktions, während mit bekommen const_get, würden Sie so etwas wie zu tun haben 'Functional::Collections::LazyList'.split('::').reduce(Module, :const_get).
Chuck
44
"Object".constantize # => Object
jtbandes
quelle
Bitte beachten Sie, dass dies .constantizeeine Rails-Methode ist, die Sie in Ruby
Edgar Ortega am
33

Eine Zeichenfolge, erste Anruf gegeben Klassifizieren einen Klassennamen (noch ein String), dann rufen erstellen constantize zu versuchen , den Klassennamen Konstante (beachten Sie, dass zu finden und das Rückklassennamen Konstanten sind ).

some_string.classify.constantize
user664833
quelle
10
Sie sollten camelize anstelle von classify verwenden, da classify für Tabellennamen gilt und die Pluralisierung nicht sehr gut handhabt.
Peter Brown
1
Vielen Dank! das ist großartig!
Duykhoa
2
Ihre Antwort ist wirklich wertvoll, aber Sie sollten "titleize" für den Tabellennamen verwenden, der nach Leerzeichen enthält, und Leerzeichen aus der Zeichenfolge entfernen, um einen vollständigen Klassennamen zu erhalten.
SSR
22

Ich weiß, dass dies eine alte Frage ist, aber ich möchte nur diese Notiz hinterlassen, sie kann für andere hilfreich sein.

Module.const_getKann im einfachen Ruby verschachtelte Konstanten finden. Zum Beispiel mit folgender Struktur:

module MyModule
  module MySubmodule
    class MyModel
    end
  end
end

Sie können es wie folgt verwenden:

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

Wenn Active verfügbar ist (zB in Rails): String#constantizeoder String#safe_constantize, das heißt "ClassName".constantize.

In reinem Ruby: Module#const_getnormalerweise Object.const_get("ClassName").

In den letzten Rubinen arbeiten beide mit Konstanten, die in Modulen wie in verschachtelt sind Object.const_get("Outer::Inner").

Skalee
quelle
6

Wenn Sie eine Zeichenfolge in einen tatsächlichen Klassennamen konvertieren möchten, um auf das Modell oder eine andere Klasse zuzugreifen

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
quelle