all of the previous solutions seem to make the following assumptions -
$stderr and $stdout are global objects which all of ruby send messages
bound to ‘stderr’ and ‘stdout’ to, and that the constants STDERR and
STDOUT also point to these same objects. that being the case (?), can
someone tell me why the following DOES NOT WORK?
···
======================================================================
#!/usr/bin/env ruby
require ‘delegate’
simplest possible example
of a redirectable IO class
class DupableIO < SimpleDelegator
def initialize io
@io = io
super(@io)
end
def duplicate io
setobj io
end
def unduplicate
setobj @io
end
end
output goes to stderr
ls non_existent_file
global stdout delegates all his calls to constant object STDOUT
$stdout = DupableIO.new STDOUT
global stderr delegates all his calls to constant object STDERR
$stderr = DupableIO.new STDERR
a normal io (File) object
$log = open ‘logfile’, ‘w’
output STILL goes to stderr (correct)
ls non_existent_file
now tell stderr and stdout to delegate
their calls to the log object
$stderr.duplicate $log
$stdout.duplicate $log
output goes to logfile (correct)
$stderr.puts ‘foo’
======================================================================
in particular it would seem that, somewhere, some test is made of
$stderr and $stdout BEFORE actually using them - something along the
lines of
if $stderr.type == IO
… use it
else
… open up 2 and use it
end
how else to explain the above behavior. it’s really unfortunate
because i think this type of solution is in the ‘ruby spirit’ : what
we require is an IO object which can, temporarily, make calls on
another IO object. this IS the delegate pattern to a ‘T’ - it would
be nice to be able to use it.
- ara howard