When Monkey Patching Goes Wrong
ShareThis
February 22nd 2010
One of Ruby’s coolest features is the ability to open up an existing class and modify its behaviours. There are times when this can go incredibly wrong however. Aslak Hellesoy reports a Rails bug which breaks the Ruby standard library, ERB, in turn breaking his wonderful BDD tool, cucumber.
Although many people have developed awesome new tools to do great things with Ruby we need to remember its great core features as well. As Aslak points out, the Rails team should have subclassed ERB for their purposes and used that throughout Rails core. It wont affect any developer using Rails because ERB is completely abstracted away and we work with templates.
This is not to say monkey patching is always bad. But the Rails team modified a core assumption of ERB: that output was not escaped. By modifying the public ERB API directly other applications were fatally affected.
So back to the subclass. Lets just take a simple example using ERB. The intetion of the Rails core was to, by default, escape possibly malicious, HTML/Javascript when using <%= %>. This is a change over from the previous version of Rails where you would need to write <%=h %>.
Again keeping it simple, say we want to pass our string of ERB “<%= my_string %>” to ERB.new. From ERB’s docs we would assume that if my_string contains any HTML tags they would be included in the output. However, the Rails monkey patch changes this assumption. This is a big no-no. Instead there should be some class like the following
class SafeERB < ERB
def initialize(string) # ERB.new takes more args
# but I'm just stubbing here
# code that parses ERB safely like <%=h %>
end
end
Not implementing safe html_escapee by default in this way is what caused this bug in a tool used by many developers. Obviously not acceptable. Of course, its isolated to cucumber’s use with actionpack (I think this is where view stuff is still done in Rails but I may be wrong) but this is still very important.
As programmers we are often given many hammers to pound the same nail. We need to remember some hammers are better suited for certain situations. Just as a framing hammer is better for nailing together a traditional suburban home and is not for building a log home, certain programming techinques & idioms are better suited for certain problems based on context.