What Not to Do (a cautionary tale)

Discussion in 'Ruby' started by Gavin Kistner, Sep 6, 2006.

  1. I wrote a little code generation system for my company. It's a small
    script that reads in an XML file and an ERB template, feeds the XML file
    to the template, and writes out the result to a file.
    =20
    To help those in the company who don't know XPath, I extended REXML with
    a couple convenience methods that let you search for elements by name
    and/or attributes.
    =20
    class REXML::Element
    # Find all descendant nodes with a specified tag name and/or
    attributes
    def find( tag_name=3D'*', attributes_to_match=3D{} )
    self.each_element(
    ".//#{REXML::Element.xpathfor(tag_name,attributes_to_match)}" ){}
    end

    # Find all child nodes with a specified tag name and/or attributes
    def kids( tag_name=3D'*', attributes_to_match=3D{} )
    self.each_element(
    "./#{REXML::Element.xpathfor(tag_name,attributes_to_match)}" ){}
    end

    ...
    end

    This worked very nicely. Template writers could simply do something
    like:
    In this file I see the following classes: <%=3D
    root.find( 'class' ).map{ |el| el.attributes[ 'name' ] }.join( ', '
    )
    %>

    All was fine under 1.8.4.

    I just upgraded to 1.8.5 and all templates using #find broke. After a
    bit of sleuthing, it looks like REXML changed the Document#root method
    in a way that caused it to call Elements#[], and that method uses
    @element.find, mixed in from Enumerable. My Element#find was overriding
    Enumerable#find, and all hell broke loose as a result.

    Moral of the story (pick one or more):
    [ ] Don't extend someone else's class with common method names
    [ ] Don't upgrade your Ruby environment unless you need to
    Gavin Kistner, Sep 6, 2006
    #1
    1. Advertising

  2. Gavin Kistner

    Guest

    On 9/6/06, Gavin Kistner <> wrote:
    > I just upgraded to 1.8.5 and all templates using #find broke. After a
    > bit of sleuthing, it looks like REXML changed the Document#root method
    > in a way that caused it to call Elements#[], and that method uses
    > @element.find, mixed in from Enumerable. My Element#find was overriding
    > Enumerable#find, and all hell broke loose as a result.
    >
    > Moral of the story (pick one or more):
    > [ ] Don't extend someone else's class with common method names
    > [ ] Don't upgrade your Ruby environment unless you need to


    [ ] Keep a set of tests and make sure they still pass after a system update

    :)
    , Sep 6, 2006
    #2
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    10
    Views:
    547
    Otis Mukinfus
    Apr 15, 2006
  2. Replies:
    10
    Views:
    1,184
  3. Simon Mullis

    A cautionary tale...

    Simon Mullis, Sep 28, 2007, in forum: Ruby
    Replies:
    5
    Views:
    102
    Robert Dober
    Sep 28, 2007
  4. Peter Otten

    Re: A cautionary tale

    Peter Otten, Dec 4, 2013, in forum: Python
    Replies:
    0
    Views:
    89
    Peter Otten
    Dec 4, 2013
  5. Steven D'Aprano

    Re: A cautionary tale

    Steven D'Aprano, Dec 5, 2013, in forum: Python
    Replies:
    1
    Views:
    81
    Frank Millman
    Dec 5, 2013
Loading...

Share This Page