Why I Hate Ruby (Or, at least, some common practices of its developers*)
Let me preface this post by saying, I don’t hate Ruby the language as a whole. It has an elegant syntax and I enjoy working with it (some of my best friends are Ruby developers!). What I do hate are some of the bad habits adopted by its development community.
I will begin with a story. This past week, I have been setting up elasticsearch as a full text search solution for attachments.me. Here’s the play-by-play.
Java
I got the Java development environment for elasticsearch up and running. This way, if need be, I can submit patches to the elasticsearch community. It’s using a tool called Gradle for dependency management and, for once, getting all the Java dependencies installed didn’t have me tearing my hair out.
Python
I installed pyes, a Python client for elasticsearch. This also went very smoothly.
Ruby
Now it was time to install a Ruby client. The library Tire was the most popular solution, so I went with this. All the unit tests passed, and it seemed like a safe move to add Tire to our Gemfile. The next day the code was deployed and it proceeded to crash our production environment.
Why? Because Tire relied on yajl-ruby which punched the to_json() method on classes with a method incompatible with ActiveSupport (which also punched the same method onto classes). It gets better, in irb I happened to be including the JSON gem, this library expected a to_json() serialization method incompatible with both yajl/json and ActiveSupport. The situation is so bat-shit-crazy that there’s even a multi_json library, to provide cross-compatibility between these gems (note that this gem does not fix the serialization incompatibility).
Is the problem that there are so many JSON libraries? Not really, although this is a bit crazy. The problem is that each of the JSON libraries is mucking with the class methods.
I’m a big JavaScript groupie. Like Ruby, JavaScript is a very malleable language. It might arguably be a bit too malleable. Early in its history, it got a reputation for its ability to turn into an unmaintainable mess. If there’s one rule that saved JavaScript, it’s this “thou shalt not touch the global scope.” Well written JavaScript libraries take this commandment to heart and, as a rule, tend to only introduce one variable into global scope.
Punching methods onto classes is cool, but it pollutes scope and can cause major issues like those I had with to_json(). I think that modifying things high up in the inheritance hierarchy, as a side-effect of a require statement is, in many ways, much worse than leaking things into the global scope in JavaScript — it causes bizarre hard to track down bugs, when two libraries are contending for the same method on a class.
Do I actually hate Ruby? no. Ruby developers just need to learn from languages like JavaScript and adopt conventions which pollute scope less. That way, novice Ruby developers can utilize the language while setting off less land mines.
— Ben (@benjamincoe)
* It has come to my attention that, as I do not actually hate the Ruby language as a whole, this article’s original title “Why I hate Ruby” was confusing for various individuals (many of whom did not realize what was happening in time, and erroneously read a sentence or two of the article). I have amended the title, and have lashed myself in penance.