From: "Zed A. Shaw" <zedshaw / zedshaw.com>
>
> I then trolled through a few more projects and found that this
> is common practice.  The glue project does it.  Glue even goes
> so far as to re-open the Logger class *just so it can turn it
> into a singleton*.  Great Buddha the insanity is everywhere!

I was bitten recently by a change to the CGI module.  I don't
think I can get to quite the same level of moral outrage on this
one because by comparison what I ran afoul of seems more like what
one would expect to be a legitimate leveraging of the Power of Ruby,
even in a library context: no global classes or constants were
being opened or modified.  Something that I used to convert to a
String instance, was now still a String, but its singleton class had
been extended with additional features.  Including some accompanying
instance variables, which is the part that bit me.

My code was littered with  cgi['some_parameter'].to_s
because I'd long ago learned that CGI returned something as
a parameter value that acted like a String, but wasn't really.
I added the .to_s when fetching CGI parameters, because the values
I fetch eventually end up in objects which are serialized out to
a flat-file database with YAML.

A recent change to CGI that was--probably--for most intents and
purposes at least as good or better than the way it used to work
was apparently to make cgi['some_parameter'] now return a genuine
String - but one that had been extended with extra features.
Unfortunately, this had the effect of turning my .to_s calls into
no-op's.  This had the ultimately semi-harmless but alarming and
baffling result of my database files beginning to show signs of
very strange bloat: objects that used to appear as simple strings
in the YAML, were now complex dumps of objects that included the
string value, but also these ancillary CGI parameters that were
hitchhiking on these extended String objects CGI was now returning
as parameter values.

I think it took me at least an hour and a half to track down the
cause.  (Seemed like an eternity because I was working under a
deadline.)

To fix it, I did decide to open the String class with, well maybe
a small set of electric hedge trimmers.  But I'm only dealing with
my private application here.  If it were a library I were writing,
I'd go to prodigious lengths to try to not modify the global behavior
of Ruby.  My cheesy application-level fix:

class String
  # %%BWK -- this is a kludge to work around the CGI module extending
  #          String objects fetched from its parameters with some
  #          extra instance variables, which cause really verbose YAML
  #          to be output.
  #          I already was doing to_s on everything I fetched from
  #          the CGI parameters, thinking that was enough to give me
  #          a String without any extra baggage.  This kludge forces
  #          my assumption to be a true one.
  def to_s
    String.new(self)
  end
end

I'm not entirely sure what point I'm driving toward - because
really what CGI is doing seems to me in general like a pretty
reasonable use of Ruby. . . And yet it _bit_ me in a similar way to
what you reported about the Logger Maneuver.

I guess in general, Library Authors Take Note: Getting tricky in
your library can end up playing a trick on your users.


Regards,

Bill