Wie können wir eine Klasse aus ihrer Namenszeichenfolge in Ruby-on-Rails instanziieren?
Zum Beispiel haben wir den Namen in der Datenbank in einem Format wie "ClassName" oder "my_super_class_name".
Wie können wir daraus ein Objekt erstellen?
Lösung:
Habe selbst danach gesucht, aber nicht gefunden, also hier ist es. Ruby-on-Rails-API-Methode
name = "ClassName"
instance = name.constantize.new
Es kann sogar nicht formatiert werden, wir können die Zeichenfolgenmethode .classify verwenden
name = "my_super_class"
instance = name.classify.constantize.new
Natürlich ist dies vielleicht nicht sehr "Rails Way", aber es löst seinen Zweck.
ruby-on-rails
ruby-on-rails-3
string
class
instantiation
Vjatseslav Gedrovits
quelle
quelle
Object.const_get
und Classify ist eine ActiveSupport-Methode, die versucht, eine Zeichenfolge in eine Standardklassenformatierung umzuwandeln. Was Sie tun, ist identisch mit Evgineys Antwort, mit einigen zusätzlichen Überprüfungen. Während das Konstantisieren wahrscheinlich eine bessere Lösung ist (weil es Sanity Checks durchführt), hilft es, die von Ihnen verwendeten Tools zu verstehen.Antworten:
klass = Object.const_get "ClassName"
über Klassenmethoden
class KlassExample def self.klass_method puts "Hello World from Class method" end end klass = Object.const_get "KlassExample" klass.klass_method irb(main):061:0> klass.klass_method Hello World from Class method
quelle
Loading development environment (Rails 3.2.9) irb(main):001:0> name = "PartnerGateway" => "PartnerGateway" irb(main):002:0> klass = name.constantize.new => #<PartnerGateway id: nil, name: nil, partner_id: nil, gateway: nil, changed_by_id: nil, deleted_at: nil, created_at: nil, updated_at: nil> irb(main):003:0> klass.name => nil
irb(main):005:0> klass2 = Object.const_get name => PartnerGateway(id: integer, name: string, partner_id: integer, gateway: string, changed_by_id: integer, deleted_at: datetime, created_at: datetime, updated_at: datetime) irb(main):006:0> klass2.name => "PartnerGateway" irb(main):008:0> klass2.id NoMethodError: undefined method
id 'für # <Klasse: 0xac3e4c0> `Andere suchen möglicherweise auch nach einer Alternative, die keinen Fehler auslöst, wenn die Klasse nicht gefunden wird.
safe_constantize
ist genau das.class MyClass end "my_class".classify.safe_constantize.new # #<MyClass:0x007fec3a96b8a0> "omg_evil".classify.safe_constantize.new # nil
quelle
Sie können einfach eine Zeichenfolge konvertieren und eine Klasse daraus initialisieren, indem Sie:
klass_name = "Module::ClassName" klass_name.constantize
So initialisieren Sie ein neues Objekt:
Ich hoffe, dass sich dies als hilfreich herausstellt. Vielen Dank!
quelle
Ich bin überrascht, dass niemand in seinen Antworten über Sicherheit und Hacking nachdenkt. Die Instanziierung einer beliebigen Zeichenfolge, die wahrscheinlich sogar indirekt aus Benutzereingaben stammt, erfordert Probleme und Hacking. Wir alle sollten / müssen auf der Whitelist stehen, es sei denn, wir sind sicher, dass die Zeichenfolge vollständig kontrolliert und überwacht wird
def class_for(name) { "foo" => Foo, "bar" => Bar, }[name] || raise UnknownClass end class_for(name_wherever_this_came_from).create!(params_somehow)
Wie Sie die entsprechenden Parameter willkürlich kennen würden, ohne eine Whitelist zu haben, wäre eine Herausforderung, aber Sie haben die Idee.
quelle