Deconstructor to close file

I’m trying to write a logger class. I open the file in the initialize
method. Is there a destructor that I can override to close the file, or
can I just assume the file is closed automatically?

Am I going about this all wrong, and should instead just open and close
the file each time I write to it?

Thanks,
Ray

Errr… destructor for the non idiots

On 2/19/07, Raymond O’connor [email protected] wrote:

I’m trying to write a logger class. I open the file in the initialize
method. Is there a destructor that I can override to close the file, or
can I just assume the file is closed automatically?

Am I going about this all wrong, and should instead just open and close
the file each time I write to it?

There is no meaningful concept of a destructor in Ruby. There are
finalizers, but they’re not guaranteed to be called.

Rather than trying to write your own logger class, why don’t you look at
Log4R?

-austin

On 2/20/07, Raymond O’connor [email protected] wrote:

I’m trying to write a logger class. I open the file in the initialize
method. Is there a destructor that I can override to close the file, or
can I just assume the file is closed automatically?

Am I going about this all wrong, and should instead just open and close
the file each time I write to it?

Thanks,
Ray

  1. The files are closed automatically when you stop the program.
    You’ll need to close in special cases, e.g. you suspect that you’ll
    run out of free file handles, you want to make sure that file is
    properly closed asap (for the event of a powerfailure),…

  2. Normally with files (and many more) you either call close() or you
    can use the block form of File.open(). When the block finishes the
    file gets closed. But as you need the file in the class, I think you
    should provide you own close() method that will close the file, and
    let the responsibility to the user of your class.

  3. There are several ready-made logger packages available e.g. Logger
    and Log4r. You may want to try them before reinventing the wheel :wink:

  4. You may want to set File#sync=true to disable buffering on the
    file. The changes will be written to the file immediately, no matter
    how small. The default is to collect them and write them in larger
    chunks. This helps performance-wise, but you get the info with a
    little delay.

Thanks for everyone’s help! I may end up just using the standard
logger. Do you know if there is an easy way to add methods to the
standard logger class without having to do .extend everytime I create an
instance of it?

On Tue, Feb 20, 2007 at 08:48:07AM +0900, Raymond O’connor wrote:

I’m trying to write a logger class. I open the file in the initialize
method. Is there a destructor that I can override to close the file, or
can I just assume the file is closed automatically?

Am I going about this all wrong, and should instead just open and close
the file each time I write to it?

Ruby has no destructors (there are these things called finalizers, but
in general it’s best to pretend they don’t exist).

The usual idiom for a file (or any resource that needs to be released)
is:

File.open(path, read_or_write) do |file|

use file

end # The file will be closed

The way to implement something like that is to define a method like:

def open
resource = Resource.new
begin
yield( resource ) # pass the resource into the block
ensure # code in an ensure block always gets run, even if an exception
# is raised
resource.release
end
end

open { |res| res.use }

Unfortunately a logger doesn’t work well with this idiom.

You could provide an explicit teardown method for the logger and call it
when the program ends, or use the block based idiom:

Logger.new do |logger|
… whole program …
end

but that strikes me as awkward. The other option is the at_exit method.
It gets supplied a block to be run when the program exits, so in your
initalize you could do:

def initialize
@file = File.open(path, “w”)
at_exit { @file.close }
end

Finally, on a parting note, are you aware that ruby’s standard library
has a logger? Just require ‘logger’.

Classes are open in Ruby.

You can just extend the class, e.g.:

class Log4R
def asdf
p “blah”
end
end

On 20.02.2007 01:00, Austin Z. wrote:

There is no meaningful concept of a destructor in Ruby. There are
finalizers, but they’re not guaranteed to be called.

Are you sure about that? I know the statement to be true for Java but
in which situation (other than an interpreter crash) is a finalizer not
invoked?

Kind regards

robert

On 2/20/07, Robert K. [email protected] wrote:

On 20.02.2007 01:00, Austin Z. wrote:

There is no meaningful concept of a destructor in Ruby. There are
finalizers, but they’re not guaranteed to be called.
Are you sure about that? I know the statement to be true for Java but
in which situation (other than an interpreter crash) is a finalizer not
invoked?

I recall reading a few things over the last couple of years. On
program termination, I think they will be called, but things could
happen to keep an object around a lot longer than you think – which
means that it’s not something to trust.

-austin

On 19 feb, 21:21, Raymond O’connor [email protected] wrote:

Thanks for everyone’s help! I may end up just using the standard
logger. Do you know if there is an easy way to add methods to the
standard logger class without having to do .extend everytime I create an
instance of it?


Posted viahttp://www.ruby-forum.com/.

Besides what SonOfLift answered regarding open classes, another way to
extend a class in most OO languages is to create your own subclass
using inheritance, like:

class MyLogger < Log4R
# add any additional methods here
end

This is probably slightly safer than messing with the original class,
so it should be preferred when possible.

On 20.02.2007 14:12, Austin Z. wrote:

happen to keep an object around a lot longer than you think – which
means that it’s not something to trust.

Yeah, definitely do not trust on the ti

On 20.02.2007 14:12, Austin Z. wrote:

On 2/20/07, Robert K. [email protected] wrote:

On 20.02.2007 01:00, Austin Z. wrote:

There is no meaningful concept of a destructor in Ruby. There are
finalizers, but they’re not guaranteed to be called.
Are you sure about that? I know the statement to be true for Java but
in which situation (other than an interpreter crash) is a finalizer not
invoked?

I recall reading a few things over the last couple of years. On
program termination, I think they will be called,

Yes. Actually I found a regular way to prevent invocation:

robert@fussel ~
$ ruby -e ‘o=Object.new;ObjectSpace.define_finalizer(o) {p 222};exit 1’
222

robert@fussel ~
$ ruby -e ‘o=Object.new;ObjectSpace.define_finalizer(o) {p 222};exit! 1’

robert@fussel ~
$

So there is at least /one/ other way besides a process crash. I didn’t
think of exit! before. Good that we double checked. :slight_smile:

but things could
happen to keep an object around a lot longer than you think – which
means that it’s not something to trust.

Yeah, don’t trust the timing. And I definitively agree that there are
often better means than finalizers.

Kind regards

robert