2008-10-01 4 views
16

Ich habe eine benutzerdefinierte Rails Modell geschrieben. Dieses Modell wird von einem tatsächlichen Server und nicht von einer Datenbanktabelle unterstützt (erbt also nicht von ActiveRecord::Base). Um die angeforderten Informationen vom Server zu bekommen, öffne ich eine SSH-Verbindung dazu. Da Rails das Objekt nicht wiederverwenden, wird für jede empfangene Anforderung ein neues Objekt sowie eine neue SSH-Verbindung zum Server erstellt. Um die Serverbelastung zu reduzieren, möchte ich die SSH-Verbindung schließen, bevor das Modellobjekt eine Garbage-Collection erhält. Ich wundere mich, stellt Ruby einen Benachrichtigungsmechanismus zur Verfügung, um das Objekt zu informieren, dass es zerstört wird? Wenn ja, könnte ich diese Benachrichtigung verwenden, um zu wissen, wann die SSH-Verbindungen geschlossen werden müssen. Wenn nicht, muss ich es manuell machen, wenn ich weiß, dass ich mit dem Objekt fertig bin.Mitteilung der Objektzerstörung in Ruby

Wenn ich manuell darum kümmern muß, kann ich das Objekt explizit zerstören? Oder ist das Beste, was ich tun kann, ist object = nil?

Antwort

21

Wenn Sie kontrollieren müssen, was passiert, wenn ein Objekt zerstört wird, sollten Sie es explizit selbst zerstören - dies ist beabsichtigt. Du sollst ein Objekt auch nicht explizit zerstören können - das ist auch Absicht.

Mit anderen Worten, ein Objekt ist aus der Perspektive Ihres Programms niemals zerstört oder zerstörbar. Aus diesen Gründen sollten Sie das Problem überdenken (dies ist kein ungewöhnlicher Bedarf - Freigabe von Ressourcen, wenn das Objekt nicht mehr benötigt wird), sodass es in das Ruby-Paradigma passt.

Wenn Sie das Objekt auf "nil" setzen, erhalten Sie einen Hinweis auf den Garbage Collector, der jedoch nicht unbedingt sofort zerstört wird.

Wenn Sie jedoch die Garbage Collector damit umgehen müssen, dann lesen Sie weiter.

Es gibt keine direkte Unterstützung für einen Destruktor, aber Sie können einen finalizer function aufrufen, wenn dieser zerstört wird.

Nach http://pleac.sourceforge.net/pleac_ruby/classesetc.html kann es nicht Garbage gesammelt werden, wenn es einen Verweis auf das ursprüngliche Objekt enthält, also muss eine Klassenmethode und keine Instanzmethode sein.

class MyClass 
    def initialize 
     ObjectSpace.define_finalizer(self, 
            self.class.method(:finalize).to_proc) 
    end 
    def MyClass.finalize(id) 
     puts "Object #{id} dying at #{Time.new}" 
    end 
end 
0

Ich stellte eine Lösung here auf einem anderen Stackoverflow Threads, Rubin in einer Weise implementiert, die Python-Kontext-Manager ähnlich ist. Von der Client-Seite ist die Zerstörung implizit.