2012-12-28 7 views
56

W jaki sposób możemy utworzyć instancję klasy z łańcucha nazw w Ruby-on-Rails?Jak utworzyć instancję klasy z ciągu znaków w Railsach?

Na przykład mamy jego nazwę w bazie danych w formacie "ClassName" lub "my_super_class_name".

Jak możemy z tego obiektu stworzyć obiekt?

Rozwiązanie:

Szukałem to sam, ale nie znaleziono, więc tutaj jest. Ruby-on-Rails API Method

name = "ClassName" 
instance = name.constantize.new 

To nie może być nawet sformatowane, nie możemy metoda ciąg użytkownik .classify

name = "my_super_class" 
instance = name.classify.constantize.new 

Oczywiście może to jest bardzo „sposób Rails”, ale to rozwiązuje to cel.

+4

Po prostu FYI, constantize to wygodna metoda ActiveSupport, która wykonuje polecenie "Object.const_get", a Classify to metoda ActiveSupport, która próbuje przekształcić ciąg znaków w standardowe formatowanie klas. To, co robisz, jest identyczne z odpowiedzią Evginey'a, z dodatkowymi kontrolami. Podczas gdy stała jest prawdopodobnie lepszym rozwiązaniem (ponieważ sprawdza stan zdrowia), pomaga zrozumieć narzędzia, z których korzystasz. – quandrum

+0

Dziękuję za to, szczerze mówiąc nie sprawdziłem, co robi w instrukcji obsługi. –

Odpowiedz

57
klass = Object.const_get "ClassName" 

o metodach klasy

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 
+0

Dzięki temu nie można uzyskać dostępu do metod klasowych. Powyższe rozwiązanie działa poprawnie z metodami klasy. –

+0

yes you actuality can –

+0

'Ładowanie środowiska programistycznego (Rails 3.2.9) irb (główne): 001: 0> name =" PartnerGateway " =>" PartnerGateway " irb (główne): 002: 0> klass = nazwa .constantize.nowy => # irb (main): 003: 0> klass .name => zero ' –

24

Inni mogą być również szukających alternatywy, które nie wyrzuca błąd, jeśli to się nie powiedzie, aby znaleźć klasę. safe_constantize to po prostu to.

class MyClass 
end 

"my_class".classify.safe_constantize.new # #<MyClass:0x007fec3a96b8a0> 
"omg_evil".classify.safe_constantize.new # nil 
2

Jestem zaskoczony, że nikt nie bierze pod uwagę bezpieczeństwa i hakowania w swoich odpowiedziach. Natrafienie na dowolny ciąg, który prawdopodobnie pojawił się nawet pośrednio po wprowadzeniu danych przez użytkownika, wymaga kłopotów i hakowania. Wszyscy powinni/powinny być białej listy, chyba że jesteś pewien, że łańcuch jest w pełni kontrolowane i monitorowane

def class_for(name) 
    { 
    "foo" => Foo, 
    "bar" => Bar, 
    }[name] || raise UnknownClass 
end 

class_for(name_wherever_this_came_from).create!(params_somehow) 

Jak znasz odpowiednich params arbitralnie bez białej listy byłoby trudne, ale masz pomysł.

0

można po prostu przekonwertować ciąg i zainicjować klasę z niego przez:

klass_name = "Module::ClassName" 
klass_name.constantize 

Aby zainicjować nowy obiekt:

klass_name.constantize.new 

Mam nadzieję, że okaże się pomocny. Dzięki!