Josh Moore Josh Moore - 4 months ago 15
Ruby Question

Notification of object destruction in Ruby

I have written a custom Rails model. This model is backed by an actually server not by a database table (so it does not inherit from

ActiveRecord::Base
). In order to get the requested information from the server I open a SSH connection to it. Because rails does not reuse object a new object, as well as a new SSH connection to the server, will be created for ever request that is received. To reduce server stress I want to close the SSH connection before the model object gets garbage collected. I am wondering does ruby provide a notification mechanism to inform the object that it will be destroyed? If so I could use this notification to know when to close the SSH connections. If not I will need to do it manual when I know I am finished with the object.

If I need to manually take care of this, can I explicitly destroy the object? Or is the best i can do is
object = nil
?

Answer

If you need to control what happens when an object is destroyed, you really should be explicitly destroying it yourself - this is by design. You're not supposed to be able to destroy an object explicitly either - this is also by design.

In other words, from the perspective of your program, an object is never destroyed or destroyable. For these reasons you should re-think the problem (this is not an uncommon need - release of resources when the object is no longer needed) so it fits into the Ruby paradigm.

Setting the object to nil gives a hint to the garbage collector, but does not necessarily immediately destroy it.

However, if you must have the garbage collector handle it, then read on.

There is no direct support for a destructor, but you can have it call a finalizer function when it is destroyed.

According to http://pleac.sourceforge.net/pleac_ruby/classesetc.html it may not be garbage collected if it contains a reference to the original object, so must be a class method and not an instance method.

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