Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
Well crafted software takes care not to pollute the user's environment with things that might make it difficult or impossible for other software to function properly. As a very high level language, Ruby does not have as many of the basic system level co-existence issues that a systems programming language might. However, that does not mean it is immune to problems of environmental pollution: Ruby programs can and do cause co-existence problems at the system and application level.
One of the most significant sources of pain when it comes to co-existence problems is the problems that arise when two Ruby programs override the same bit of functionality via monkey-patching in a way that causes a conflict. This can lead to very confusing issues that are difficult to debug and track down.
As an example of this, a while ago I ran into a bug that was extremely confusing to track down. In the process of adding the writeexcel gem to my dependencies for a Rails project, I managed to end up with code failing in seemingly completely unrelated
to_json calls. I was getting an
ArgumentError about the number of arguments for
String#encode, which on the surface seemed like it should have nothing to do with adding the writeexcel dependency. This is the worst kind of bug, because it's not typically clear at all where to begin investigating the problem.
On further investigation I found that both writeexcel and Rails backported this method from Ruby 1.9 for use on Ruby 1.8, but that writeexcel did not copy the signature correctly. Because writeexcel's patch was getting loaded, when Rails checked to see if the method was present it found that it was and so did not install its own patch. As a result, somewhere deep in the JSON support the
String#encode method was being called with two arguments even though writeexcel's version only accepted one. While this problem was later fixed in writeexcel, it caused me to lose a big chunk of time on a wild goose chase and frustrated the hell out of me.
The irony of this situation is that the technique for doing backports used by writeexcel was directly copied from my own approach to backporting Ruby 1.9 methods in Prawn. I had previously advocated this technique, and so getting bit by this problem was a bit of an eye opener to the limitations of my approach. This goes to show that even "monkeypatching for good" is still a bad idea.
Turn the page if you're taking the linear tour, or feel free to jump around via the sidebar.