# What Not to Do (a cautionary tale)

**URL:** <https://www.ruby-forum.com/t/what-not-to-do-a-cautionary-tale/67790>\
**Category:** Ruby\
**Created:** [September 6, 2006, 8:16pm UTC](https://www.ruby-forum.com/t/what-not-to-do-a-cautionary-tale/67790 "2006-09-06T20:16:47Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![phrogz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/2acd7d/32.png) [@phrogz](https://www.ruby-forum.com/u/phrogz)\
**Post date:** [September 6, 2006, 8:16pm UTC](https://www.ruby-forum.com/t/what-not-to-do-a-cautionary-tale/67790/1 "2006-09-06T20:16:47Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![phrogz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/2acd7d/32.png) [@phrogz](https://www.ruby-forum.com/u/phrogz)\
**Post date:** [September 6, 2006, 8:40pm UTC](https://www.ruby-forum.com/t/what-not-to-do-a-cautionary-tale/67790/2 "2006-09-06T20:40:48Z")

</div>

On 9/6/06, Gavin K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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

🙂
