Skip to main content
2024-03-2511 min read
Web Development

Ruby: The Language That Peaked in 2007 and Nobody Told It

Ruby: The Language That Peaked in 2007 and Nobody Told It

Ah, Ruby. The language that promised to make programmers happy and ended up making them unemployed.

The DHH Kool-Aid Factory

It all started with one man: David Heinemeier Hansson, or as the Ruby community calls him, "Our Lord and Savior DHH."
DHH: "Look at this blog in 15 minutes!" The World: "HOLY SHIT" DHH: "Convention over configuration!" The World: "REVOLUTIONARY" DHH: "Also, fuck your types, tests are all you need!" The World: "Wait, what?"
And thus began Ruby's reign of terror, where "developer happiness" meant "fuck it, we'll fix it in production."
⚠️
Historical Note: Rails' "15-minute blog" demo was the "ChatGPT moment" of 2005. Everyone lost their minds watching DHH build a blog faster than it took to install Java. What we didn't realize was that we'd spend the next 20 years maintaining that 15-minute code.

The DHH Influence Propagation Model

💭 DHH Has Opinion
'Microservices are bullshit'

📝 Blog Post
'Why X is Actually Bad'
15,000 words

🐦 Tweet Storm
47 tweets
'Here's why you're wrong'

🏢 Basecamp Adopts
'We deleted all our X'

💎 Rails Core Meeting
'Should we deprecate X?'

📦 Rails 7.x
'X is now deprecated'
'Use Y instead'

📰 Hacker News
500 comments
Flamewar

👔 Your Boss
'I read that X is bad'
'We should use Y'

😭 You
'But our entire app uses X'
'6 months of refactoring'

The DHH Doctrine: Whatever DHH thinks today becomes Rails gospel tomorrow and your technical debt the day after. The man could tweet "Databases are overrated" and half the Ruby community would start using CSV files.

The Performance Joke

Ruby is slow. No, you don't understand. Ruby is S L O W.
Python: "I'm not the fastest language..." Ruby: "Hold my artisanal, small-batch, craft beer"
Ruby is so slow that by the time your web request finishes, your users have:
  • Made coffee
  • Questioned their life choices
  • Learned JavaScript
  • Built the same app in Node
  • Deployed it
  • Stolen all your customers
"But Ruby 3 is 3x faster!" they cry. Cool. 3 times a snail is still a snail.

Performance Comparison (Requests/Second)

3x faster!

Still slower than...

Go
50,000+ req/s
🚀

Ruby 2.x
3,000 req/s
🐌

Ruby 3.x
9,000 req/s
🐌🐌🐌

Python
8,000+ req/s
🚙

Rust
45,000+ req/s
🚀

Java
35,000+ req/s
✈️

Node.js
25,000+ req/s
🚗

PHP 8
15,000+ req/s
🚗

💡

Ruby Performance

Ruby's execution speed is legendarily slow due to its interpreted nature, global interpreter lock (GIL), and design phil...

conceptHover for more
🔄

Monkey Patching

Ruby's ability to modify classes and modules at runtime, including built-in classes. While powerful, it leads to unpredi...

patternHover for more

Everything Is Possible, Nothing Makes Sense

Ruby's philosophy: "There should be multiple ways to do everything, and they should all be slightly different!"
Want to iterate through an array?
ruby
1array.each { |x| puts x }
2array.each do |x| puts x end
3for x in array do puts x end
4array.map { |x| puts x }
5array.collect { |x| puts x } # same as map because fuck you
60.upto(array.length - 1) { |i| puts array[i] }
7array.length.times { |i| puts array[i] }
8while i < array.length do puts array[i]; i += 1 end
"Isn't it beautiful?" asks the Rubyist. "So expressive! So flexible!"
No. It's chaos. It's like a language designed by someone who couldn't make decisions so they included everyone's suggestions.

The Monkey Patching Pandemic

Ruby lets you modify ANYTHING at runtime. ANYTHING.
ruby
1class String
2 def length
3 "wouldn't you like to know"
4 end
5end
6
7# Congratulations! You've just broken every library in your project
But Ruby developers don't see this as a bug, they see it as a FEATURE.
"We can add methods to core classes!" they exclaim, as if that's not the programming equivalent of performing surgery on yourself while drunk.
🚨
Real Production Horror: I once debugged an issue where nil was monkey-patched to return true in certain contexts. The developer who wrote it had left the company. The comment said "temporary fix." The commit was from 2011.
I've seen production codebases where:
  • Numbers have been taught to speak
  • Strings learned to fly
  • Arrays became self-aware
  • nil was redefined to equal true (I wish I was joking)

The Rails Trap

"Ruby is great!" "Oh cool, what do you build with it?" "Rails apps!" "What else?" "..." "..." "...Rails APIs?"
Ruby is essentially Rails' life support system. It's like if the entire Python ecosystem was just Django. Actually, it's worse, because at least Python has data science. Ruby has... Sinatra? (Rails but sadder)
85%5%5%3%2%Ruby Ecosystem DependenciesRails and Rails-relatedSinatraTesting tools (for Rails)DevOps toolsOther

The Gem Ecosystem: Abandon Hope All Ye Who Bundle Install

RubyGems: Where good ideas go to die and security vulnerabilities go to thrive.
Want to add authentication to your app? Here are 47 gems:
  • All last updated in 2013
  • All with slightly different APIs
  • All monkey-patching core classes
  • All conflicting with each other
  • All with dependencies on specific Ruby versions that don't exist anymore
Running bundle install is like Russian roulette:
  • Will it work?
  • Will it download 400MB of dependencies?
  • Will it require a specific version of Ruby that you don't have?
  • Will it compile native extensions for 47 minutes?
  • Will it conflict with your other gems?
  • Will it summon Cthulhu?
The answer to all: Yes.

Version Manager Hell

Ruby developers don't use Ruby. They use:
  • RVM (Ruby Version Manager)
  • rbenv (because RVM was too magical)
  • chruby (because rbenv was too complex)
  • asdf (because why have a Ruby-specific solution?)
  • Docker (because fuck it, containerize the pain)
Every Ruby project starts with:
"Okay, first install rbenv..."
"I use RVM"
"No, rbenv is better"
"Actually, chruby..."
[fistfight ensues]
Meanwhile, your .ruby-version file says 2.3.1, but you need 2.3.1-p112, but actually that has a security vulnerability so you need 2.3.8, but that breaks your gems, so actually...

RVM

rbenv

chruby

asdf

Docker

New Ruby Project

Version Manager?

RVM
(Ruby Version Manager)
~/.rvm magic

rbenv
(Less magic)
Shims everywhere

chruby
(Even less magic)
Simple but limited

asdf
(Polyglot)
For everything

Docker
(Give up)
Containerize the pain

Conflicts with rbenv

Conflicts with RVM

Too simple for some

Another tool to learn

Now debug Docker too

Team Arguments
🥊

Use whatever
the senior dev likes

The "Everything Is An Object" Lie

Ruby: "Everything is an object!" Me: "What about blocks?" Ruby: "Well..." Me: "And methods?" Ruby: "Okay, so..." Me: "And operators?" Ruby: "LOOK, MOST THINGS ARE OBJECTS, OKAY?"
It's like Ruby wanted to be Smalltalk but gave up halfway through and decided to wing it.

The Testing Cult

Ruby developers don't write code. They write tests. Mountains of tests. Tests for their tests. Tests to test the test tests.
RSpec, MiniTest, Cucumber... Each with their own DSL that looks nothing like Ruby:
ruby
1describe "the thing" do
2 context "when stuff happens" do
3 let(:thing) { FactoryBot.create(:thing) }
4 before { stub_const("CONSTANT", "value") }
5
6 it "does the stuff" do
7 expect(thing).to receive(:method).with(anything).and_return(42)
8 thing.do_stuff
9 expect(thing).to be_valid
10 expect(thing).not_to be_invalid
11 expect(thing).to have_received(:method).twice
12 end
13 end
14end
"Look how readable!" they say about this DSL acid trip. "It's like English!"
English? What English are you speaking where "expect thing to have received method twice" is a normal sentence?

The Syntax Sugar Diabetes

Ruby has so much syntax sugar, reading it gives you diabetes:
ruby
1class Person
2 attr_accessor :name
3
4 def initialize(name)
5 @name = name
6 end
7
8 def say_hello
9 puts "Hello, #{@name}!" unless @name.nil? || @name.empty?
10 end
11end
"Look how clean!" they say. But then you realize:
  • @ means instance variable
  • @@ means class variable
  • $ means global variable
  • : means symbol (which is like a string but not)
  • => used to mean hash rocket but now : does too
  • &:method means convert symbol to proc
  • ||= means assign if nil or false (not just nil!)
It's like learning to read by first learning hieroglyphics.
The Symbol Disaster: Ruby has both strings and symbols. They're almost the same but not quite. New developers spend months accidentally creating memory leaks because symbols aren't garbage collected. "It's for performance!" they say about the language that loses drag races to glaciers.

The Community's Death Rattle

RubyConf 2010: "We're taking over the world!" RubyConf 2015: "JavaScript isn't that bad..." RubyConf 2020: "At least we're not PHP!" RubyConf 2023: "Anyone still here? Hello?"
The Ruby community is like a high school reunion where everyone peaked senior year. They're still talking about the glory days when Rails was hot and startups were built on MacBooks running TextMate.
Now? The juniors learn JavaScript. The seniors moved to Go. The architects went to Rust. The data people went to Python. Who's left? The people maintaining 15-year-old Rails monoliths and crying into their craft beer.

The Metaprogramming Madness

Ruby's metaprogramming is like giving a toddler a chainsaw. Sure, they COULD create beautiful ice sculptures. But they're probably going to lose a limb.
ruby
1define_method :dynamic_method do |arg|
2 self.class.send(:define_method, arg) do
3 self.instance_variable_set("@#{arg}", yield)
4 end
5end
"Isn't it powerful?" they ask, as:
  • Their IDE gives up trying to understand what's happening
  • Their debugger commits suicide
  • New developers open the codebase and immediately update their LinkedIn

The 2.7 to 3.0 Betrayal

Ruby 3.0: "We're 3x faster and have types!"
Reality:
  • 3x faster: Only on benchmarks nobody runs
  • Types: Optional type annotations that nobody uses
  • Breaking changes: Just enough to make upgrading painful
  • Actual improvement: Marginally better at being slow
It's like putting a spoiler on a golf cart and calling it a race car.

The Real Tragedy

The saddest part? Ruby introduced genuinely good ideas:
  • Convention over configuration
  • Developer ergonomics matter
  • Testing as a first-class citizen
  • Expressive, readable code
But it sacrificed everything else on the altar of "developer happiness":
  • Performance? "Hardware is cheap!"
  • Maintainability? "Just read the tests!"
  • Static analysis? "That's what production is for!"
  • Debugging? "puts debugging is an art form!"

In Conclusion

Ruby is a language designed for developer happiness that somehow makes everyone involved miserable:
  • The developers maintaining legacy Rails apps
  • The ops people dealing with Ruby's memory leaks
  • The new hires trying to understand metaprogrammed spaghetti
  • The companies trying to hire Ruby developers in 2023
  • The investors who bet on Ruby startups
Ruby promised to be different. To be better. To make programming joyful. Instead, it became a cautionary tale about what happens when you prioritize developer ego over user experience, clever code over maintainable code, and syntax sugar over performance.
⚠️
The Ultimate Irony: Modern PHP is faster, has better tooling, more jobs, and a larger community than Ruby. Let that sink in. PHP. The language we all agreed to hate. Is now objectively better than Ruby in every measurable way.
But hey, at least it's not COBOL.
(Actually, COBOL developers make $200k+ maintaining critical financial systems. Ruby developers make $65k maintaining some startup's "Uber for dogs" platform that's perpetually 6 months from shutting down.)
47 minutes later, my Rails app is still booting. But hey, at least I'm experiencing peak developer happiness while I wait.