[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

What Not to Do (a cautionary tale

Gavin Kistner

9/6/2006 6:14:00 PM

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.

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.

class REXML::Element
# Find all descendant nodes with a specified tag name and/or
attributes
def find( tag_name='*', attributes_to_match={} )
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='*', attributes_to_match={} )
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: <%=
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



1 Answer

brabuhr

9/6/2006 6:40:00 PM

0

On 9/6/06, Gavin Kistner <gavin.kistner@anark.com> 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

:-)