An experience report of writing and publishing a Ruby gem
A couple nights ago I was overcome with the urge to publish a Ruby gem. I have been writing Ruby for over 5 years and realized that it was time to give Ruby development outside of Stripe's Ruby infra a shot.
The package is
which I've wanted to build on and off for about three years now.
It's worth its own article and context, so that's all I'll say
about the gem itself here.
I wanted to put a strong foot forward when publishing the gem. I do a lot of advocacy for writing high-quality Ruby code, mostly internal to Stripe, but also in public. Check out Ruby style guide and Effective Sorbet for most of the advice.
However, I haven't shared a whole Ruby library in public before. While I didn't expect to do a perfect job with the new stuff, I did want to get some things right.
strict typing as the minimum.
Plus the stuff I would do in any design:
I learned much more about the Ruby language's built-in
tooling. It's cool to see
gem all coming as a unit. Never really knew
they flocked together. Getting Ruby to a newer version got
all these things to a newer version too.
I'm a big fan of Clojure. In that ecosystem the mantra is
everything is data. You often write configuration files as
Clojure data structures. It was cool to see Ruby doing a
similar thing, even if it forgot the data part.
Rakefile are all Ruby code. I've definitely
touched Stripe Gemfiles before but working with the RubyGem
registry made it so much clearer how everything was fitting
The Sorbet VSCode extension can be slow at Stripe scale. On a few hundred billion lines less of Ruby it was amazing.
minitest style of tests were nice. Having
really only written RSpec-like tests,
minitest feels a lot less magical and much
smaller. Definitely reminded me of Go tests.
I wanted to follow Effective Sorbet precisely but there was one thing that I could not do because I felt it was not appropriate for an open-source project.
Despite recommending them heavily, I didn't use
T::Struct. I had used
T::Struct initially but switched to plain old Ruby
The reasoning: too many methods and too many
bad methods, e.g.
from_hash, etc. I can't
feel comfortable shipping a gem with that much baggage of
Stripes write friction logs. A friction log is basically a stream of conscious document that details everything and anything that went wrong or felt off about doing something. As a platform team lead, I get friction logs from folks across the company all the time. Those logs feed into what we choose to prioritize. It's a good system.
Here's a distillation of my frictions:
By far I wasted the most time trying to get Ruby set up on my Macbook. Stripe-issued laptops solve this problem so I hadn't felt the pain before.
Apple ships an old version of Ruby (~v2.6) but all the tooling I worked with expected Ruby 3.0. In retrospect, had I got the Ruby version issue fixed earlier in the process so many things would have been smoother.
I felt this pain most when setting up Sorbet, in particular
initializing my project with
exception thrown running
bundle exec tapioca init wasn't super helpful but
luckily enough to search me up a
lead on how to fix it.
Once I eventually got
rbenv setup and working, and
had rebooted everything to use it instead of the Mac-default
Ruby version things got better.
In terms of wall-clock time spent, RubyGems caused me the greatest time loss. RubyGems is great but the search page results were a bit all too easy to misread. When I started my gem-ing, the first thing I did was see if the name "eclair" was available. I got so excited because I saw it was.
It was only after a long night of working on the gem itself that
I finally went to publish my gem and it turned out
eclair was not available. The gem had been recently
"yanked," meaning taken down by its author. The gem
was unused but I wouldn't be able to claim it for 3 months.
Betrayal, the worst of all.
Luckily only a little more than a day later after reaching out to the current gem owner, they graciously transferred the gem over to me. Thanks again, Cyrus!
The Ruby formatter
rubyfmt doesn't seem to
integrate with the
Ruby LSP extension. It probably works with the old "Ruby" extension but
VSCode steers people away from downloading that one.
This isn't a big deal, I just didn't manage to get format-on-save working.
Overall publishing a Ruby gem was a pleasant experience. I
learned a good amount from it and it was nice learning how to
set up Sorbet,
rubyfmt, and other things I'd only
previously used because someone else installed them for me.
Thanks for reading!