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

···

--
Posted via http://www.ruby-forum.com/.

Errr... destructor for the non idiots

···

--
Posted via http://www.ruby-forum.com/.

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/19/07, Raymond O'connor <nappin713@yahoo.com> 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?

--
Austin Ziegler * halostatue@gmail.com * http://www.halostatue.ca/
               * austin@halostatue.ca * You are in a maze of twisty little passages, all alike. // halo • statue
               * austin@zieglers.ca

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.

···

On 2/20/07, Raymond O'connor <nappin713@yahoo.com> 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

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'.

···

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

Thanks,
Ray

--
Posted via http://www.ruby-forum.com/\.

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 via http://www.ruby-forum.com/.

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 20.02.2007 01:00, Austin Ziegler wrote:

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

Classes are open in Ruby.

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

class Log4R
  def asdf
    p "blah"
  end
end

···

On 2/20/07, Raymond O'connor <nappin713@yahoo.com> 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 via http://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 19 feb, 21:21, Raymond O'connor <nappin...@yahoo.com> 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/.

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 2/20/07, Robert Klemme <shortcutter@googlemail.com> wrote:

On 20.02.2007 01:00, Austin Ziegler 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?

--
Austin Ziegler * halostatue@gmail.com * http://www.halostatue.ca/
               * austin@halostatue.ca * You are in a maze of twisty little passages, all alike. // halo • statue
               * austin@zieglers.ca

Yeah, definitely do not trust on the ti

···

On 20.02.2007 14:12, Austin Ziegler wrote:

On 2/20/07, Robert Klemme <shortcutter@googlemail.com> wrote:

On 20.02.2007 01:00, Austin Ziegler 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.

> 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

···

On 20.02.2007 14:12, Austin Ziegler wrote:

On 2/20/07, Robert Klemme <shortcutter@googlemail.com> wrote:

On 20.02.2007 01:00, Austin Ziegler wrote: