---
title: "Why I Still Like Ruby (and a Few Things I Don’t Like)"
date: 2020-08-06T00:00:00+00:00
draft: false
canonical_url: https://www.viget.com/articles/why-i-still-like-ruby-and-a-few-things-i-dont-like/
featured: true
references:
- title: "The History of Ruby — SitePoint"
  url: https://www.sitepoint.com/history-ruby/
  date: 2023-11-16T14:54:03Z
  file: www-sitepoint-com-6vwmef.txt
- title: "When Should You NOT Use Rails?"
  url: https://codefol.io/posts/when-should-you-not-use-rails/
  date: 2023-11-04T17:36:55Z
  file: codefol-io-bskabg.txt
---

The Stack Overflow [2020 Developer
Survey](https://insights.stackoverflow.com/survey/2020#technology-most-loved-dreaded-and-wanted-languages-loved)
came out a couple months back, and while I don't put a ton of stock in
surveys like this, I was surprised to see Ruby seem to fare so poorly --
most notably its rank on the "most dreaded" list. Again, who cares
right, but it did make me take a step back and try to take an honest
assessment of Ruby's pros and cons, as someone who's been using Ruby
professionally for 13 years but loves playing around with other
languages and paradigms. First off, some things I really like.

### It's a great scripting language

Matz's original goal in creating Ruby was to build a truly
object-oriented scripting language[^1], and that's my
favorite use of the language: simple, reusable programs that automate
repetitive tasks. It has fantastic regex and unix support (check out
[`Open3`](https://docs.ruby-lang.org/en/2.0.0/Open3.html) as an
example). I might not always build Ruby apps, but I'll probably always
reach for it for scripting and glue code.

### A class is a little program

This one took me awhile to get my head around, and I'm not sure I'll do
a perfect job explaining it, but when a Ruby class gets loaded, it's
evaluated as a series of expressions from top-to-bottom, like a normal
program. This means you can, for example, define a class method and then
turn around and call it in the class' top-level source; in fact, this is
how things like `has_many` in Rails works -- you're just calling a class
method defined in the parent class. In other languages, you'd have to
reach for something like macros to accomplish this same functionality.

[Here's an alternate
explanation](https://mufid.github.io/blog/2016/ruby-class-evaluation/)
of what I'm getting at and [here's a cool
post](https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj)
that illustrates what sort of power this unlocks.

### The community is open source-focused

Ruby has a rich ecosystem of third-party code that Viget both benefits
from and contributes to, and with a few notable
exceptions[^2], it's all made available without the
expectation of direct profit. This means that you can pull a library
into your codebase and not have to worry about the funding status of the
company that built it (contrast with ventured-funded open-source like
[Gatsby](https://www.gatsbyjs.org/) and [Strapi](https://strapi.io/)).
Granted, with time, money, and a dedicated staff, the potential is there
to build better open source products than what small teams can do in
their free time, but in my experience, open source development and the
profit motive tend not to mix well.

### Bundler is good

It's simple, universal, and works well, and it makes it tough to get
into other languages that haven't figured this stuff out.

### It has a nice aesthetic

It's easy to make code that looks good (at least to my eye) and is easy
to understand. There's less temptation to spend a lot of time polishing
code the way I've experienced with some functional languages.

## And some things I don't like as much

Lest ye think I'm some diehard Ruby fan, I've got some gripes, as well.

### It's not universal

As I said, my favorite use of Ruby is as a scripting language, so it's
unfortunate that it doesn't come installed by default on most unix-y
systems, unlike Perl, Python, and Bash. If you want to share some Ruby
code with someone who isn't already a Ruby dev, you have to talk about,
like, asdf, rbenv, or Docker first.

### Functions aren't really first-class

You can write code in an FP style in Ruby, but there's a difference
between that and what you get in a truly functional language. I guess
the biggest difference is that a method and a lambda/block (I know
they're [a little
different](https://yehudakatz.com/2012/01/10/javascript-needs-blocks/)
don't @ me) are distinct things, and the block/yield syntax, while nice,
isn't as nice as just passing functions around. I wish I could just do:

```ruby
square = -> (x) { x * x }
[1, 2, 3].map(square)
```

Or even!

```ruby
[1, 2, 3].map(@object.square)
```

(Where `@object.square` gives me the handle to a function that then gets
passed each item in the array. I recognize this is incompatible with
optional parentheses but let me dream.)

### It is probably too flexible

Just like skiing, the most dangerous time to be a Ruby developer is the
"early intermediate" phase -- you've learned the syntax and language
features, and all of a sudden EVERYTHING is possible. Want to craft the
perfect DSL? Do it. Want to redefine what `+` does for your Integer
subclass? Do it. Want to open up a third-party library and inject a
custom header? You get my point.

As I've said, Ruby makes it easy to write nice-looking code, but it
takes restraint (and mistakes) to write maintanable code. I suppose the
same could be said about the programming discipline in general, but I
can see the appeal of simpler languages like Go.

### Type checking is cool and Ruby doesn't have it

The first languages I learned were C++ and Java, which formed my
opinions of explicit typing and compilation and made Ruby such a
revelation, but a lot has changed in the subsequent decade, and modern
typed languages are awesome. It'd be neat to be able to compile a
project and have some level of confidence about its correctness before
running the test suite. That said, I sure do appreciate the readability
of things like [RSpec](https://rspec.info/) that rely on the
dynamic/message-passing nature of Ruby. Hard to imagine writing
something as nice as this in, like, Haskell:

```ruby
it { is_expected.not_to allow_values("Landlord", "Tenant").for(:client_type) }
```

(As I was putting this post together, I became aware of a lot of
movement in the "typed Ruby" space, so we'll see where that goes. Check
out
[RBS](https://developer.squareup.com/blog/the-state-of-ruby-3-typing/)
and [Sorbet](https://sorbet.org/) for more info.)

------------------------------------------------------------------------

So those are my thoughts. In the end, it's probably best to know several
languages well in order to really be able to understand
strengths/weaknesses and pick the appropriate one for the task at hand.
If you're interested in other thoughts along these lines, you could
check out [this Reddit
thread](https://www.reddit.com/r/ruby/comments/hpta1o/i_am_tired_of_hearing_that_ruby_is_fine/)
(and [this
comment](https://www.reddit.com/r/ruby/comments/hpta1o/i_am_tired_of_hearing_that_ruby_is_fine/fxvfzgo/)
in particular) or [this blog
post](https://codefol.io/posts/when-should-you-not-use-rails/), but what
really matters is whether or not Ruby is suitable for your needs and
tastes, not what bloggers/commenters/survey-takers think.

[^1]: [*The History of Ruby*](https://www.sitepoint.com/history-ruby/)
[^2]: I.e. [Phusion Passenger](https://www.phusionpassenger.com/)
