Tapping ActiveRecord Relations
(Yes, I know I said I was probably not going to write here anymore, but while I like Medium for long-form articles, it didn’t quite fit the bill for posts that wanted syntax highlighting. Thus, I’ll probably continue to use the Buckblog for technical articles, and Medium for long-form.)
Not a lot of surprises in today’s post. I just wanted to share a convenient technique that I came across this week.
You’re all familiar with Object#tap
, right? It’s terribly useful, in many situations. The example from the documentation is pretty good:
You’re also probably all familiar with ActiveRecord::Relation
, at least indirectly. This is what is returned any time you query a model in ActiveRecord:
These relation objects allow query operations to be chained together (which you probably also already knew):
I’ve taken advantage of both Object#tap
and the chaining of Relation
instances, numerous times, but I don’t think I’ve ever done them together. Recently, though, I saw it done, something like this:
Here, the code collects the ids (updated_ids
) of all records that are affected by merging one author (old_id
) into another author (new_id
). The #tap
block just yields the relation, appends the ids of all matching records to the array, and then updates all matching records.
(Warning! This particular implementation has a race condition, and is not particularly efficient. A better way would be to use UPDATE
with RETURNING
to fetch the updated ids, thus keeping the operation atomic, and efficient. This was just a novel application of ActiveRecord::Relation with Object#tap
…)
I love this about writing software. No matter how familiar you become with the toolbox you’ve been given, someone always manages to combine those tools in ways you wouldn’t have considered.