RubyConf 2018: Let’s Subclass Hash – What’s the Worst That Could Happen?
Have you ever been tempted to subclass a core class like Hash or String? Or have you read blog posts about why you shouldn’t do that, but been left confused as to the specifics? As a maintainer of Hashie, a gem that commits this exact sin, I’m here to tell you why you want to reach for other tools instead of the subclass.
In this talk, you’ll hear stories from the trenches about what can go wrong when you subclass core classes. We’ll dig into Ruby internals and you will leave with a few new tools for tracking down seemingly inexplicable performance issues and bugs in your applications.
The absurdity of Ruby’s Hash default value
The Hash default value behavior in Ruby is one that can leave people confused. The hallmark of a good API is that it is obvious what is going to happen in each way you use it. This is one of the few places I can think of where Ruby’s standard library has surprising and confusing behavior. In the case where you use a value object — like a
Numeric— as the default value, everything works as you would easily expect.
However, most objects in Ruby are not value objects. They are mutable, which leads to seemingly strange behavior when you accidentally mutate the memoized default. Combined with Hash extensions, like Hashie, you can accidentally ruin your understanding of Hash and end up in a confusing spot.
A checklist for reviewing Rails database migrations
Software teams often cite code reviews as a primary means for ensuring quality and reducing bugs in their code. However, without high quality reviews, the efficacy of this practice is questionable. In most places that I’ve worked, a change requires only one code review (either through necessity due to team size or through informal norms). When this is the case, the code review becomes a taxing process where, if you’re not on your game, bugs or maintainability issues can start to leak into production. This means that it often falls to the senior engineers to do code reviews. However, relying entirely on the seniors means that they become a bottleneck in the process. When it comes to “dangerous” changes like Rails database migrations, the bottleneck of relying on a small subset of the team can mean that velocity drops. Or, to keep up velocity, you make code reviews less stringent and quality drops.
In try to “scale myself” for my team, I have started to experiment with checklists for performing code reviews. The first one that I wrote up is a checklist for reviewing Rails database migrations. We run on Heroku, which means that zero-downtime migrations are easy to do, as long as you write your migrations correctly. I intend this checklist to help more junior teammates do as thorough of a job in reviewing as I do. Going forward, I want to make more checklists for doing different types of code reviews, to further scale myself for my team.
Grouped pagination in ActiveRecord
Sometimes, designers will mock-up an extremely usable page that they’ve thought about and tested. Once they’re done and they bring it to you to implement, you look at it and think, “how on Earth can I do that efficiently?” One such case happened at work recently.
We were working on a “command center” of sorts where we show our customers a list of upgrades in various states. The design called for what looked like three different lists of records with each table consisting of records in a state. Since a customer can have potentially dozens of these records, we knew we wanted to paginate the page. The wrinkle in setup was that the pagination should consider the full list of records as the dataset, not each list individually. This caused us to wonder how we can efficiently implement grouped pagination in ActiveRecord.
Using the double-splat operator in Ruby
The double-splat operator is one of my favorite additions in Ruby 2.0. For some reason, the two little asterisks together make me happier than an optional
Hashparameter in a method. Even so, outside of method definitions, I didn’t realize there was a use for the double-splat operator until I dug into a bug in Hashie. I liked the result enough that I wanted to take a quick minute and share what I found.