Deconstructor to close file

R

Raymond O'connor

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
 
A

Austin Ziegler

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
 
J

Jan Svitok

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 ;-)

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

Logan Capaldo

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

Raymond O'connor

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?
 
S

SonOfLilit

Classes are open in Ruby.

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

class Log4R
def asdf
p "blah"
end
end
 
G

gga

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?

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

Robert Klemme

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
 
A

Austin Ziegler

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
 
R

Robert Klemme

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.

Yeah, definitely do not trust on the ti
 
R

Robert Klemme

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. :)
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top