STDERR vs $stderr - delegation bug

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
def duplicate io
setobj io
def unduplicate
setobj @io

output goes to stderr

ls non_existent_file

global stdout delegates all his calls to constant object STDOUT

$stdout = STDOUT

global stderr delegates all his calls to constant object STDERR

$stderr = 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
… open up 2 and use it

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