The maze book for programmers!
PragProg Amazon

Algorithms, circle mazes, hex grids, masking, weaving, braiding, 3D and 4D grids, spheres, and more!

DRM-Free Ebook

The Buckblog

assorted ramblings by Jamis Buck

Apr 2016

Tapping ActiveRecord Relations

23 April 2016 — A technique is demonstrated, calling Object#tap to reuse an ActiveRecord relation instance in order to accomplish more than one task — 2-minute read

(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:

(1..10)              .tap {|x| puts "original: #{x.inspect}"}.
  to_a               .tap {|x| puts "array:    #{x.inspect}"}.
  select {|x| x%2==0}.tap {|x| puts "evens:    #{x.inspect}"}.
  map    {|x| x*x}   .tap {|x| puts "squares:  #{x.inspect}"}.

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:

User.where("created_at > ?", Date.yesterday)
#-> #<ActiveRecord::Relation [...]>

These relation objects allow query operations to be chained together (which you probably also already knew):

q = User.where("created_at > ?", Date.yesterday)
#-> #<ActiveRecord::Relation [...]>
q = q.limit(5)
#-> #<ActiveRecord::Relation [...]>
q = q.order(:name)
#-> #<ActiveRecord::Relation [...]>

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:

updated_ids = []

Composition.where(author_id: old_id).tap do |relation|
  relation.update_all(author_id: new_id)

p updated_ids.uniq

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.

2 April 2016 — The author expresses his intent to write future articles on — 1-minute read
Mar 2016

Introducing the Query Composer

26 March 2016 — A new gem is announced, which simplifies the creation and maintenance of complex SQL queries — 4-minute read

The Poverty of Constraints

19 March 2016 — Two Korean proverbs are presented to support the argument that constraints—a poverty of resources—can enrich your software — 1-minute read

Variations on a Theme: "I Becomes We..."

12 March 2016 — A light-hearted search for pithy sayings inspired by a church billboard — 2-minute read

Being a Good Neighbor...

5 March 2016 — 6-minute read

Feb 2016

Implementing a Bloom Effect with Swift+Metal

27 February 2016 — 7-minute read

Don't Feed the Hamster the Whole Stalk

20 February 2016 — 6-minute read

The weakly-flowing stream

13 February 2016 — 4-minute read

Living with Your Eyes Open

6 February 2016 — 6-minute read

Jan 2016

Software Proverbs

30 January 2016 — 4-minute read

Mazes in Swift

23 January 2016 — 4-minute read

A Pretty-Printer for SQL

16 January 2016 — 2-minute read

Don't Assume It's Difficult until It Is

9 January 2016 — 5-minute read

Game Demonstration: Recover the Widgets

2 January 2016 — 6-minute read

Dec 2015

Checking In...

26 December 2015 — 1-minute read

Avoiding "Call Super" with Callbacks

19 December 2015 — 5-minute read

Little Things: Introspecting Block Parameters

12 December 2015 — 1-minute read

Integration API vs. Internal API

5 December 2015 — 3-minute read

Nov 2015

Upsilon Mazes

28 November 2015 — 9-minute read

Representing a Toroidal Grid

21 November 2015 — 11-minute read

Little Things: Refactoring with Hashes

14 November 2015 — 2-minute read

Fifteen Minutes at a Time

7 November 2015 — 5-minute read

Oct 2015

Mazes with Blockwise Geometry

31 October 2015 — 5-minute read

Testing What You Should Have Written

24 October 2015 — 3-minute read

The Dynamic Def

17 October 2015 — 8-minute read

Bulk Inserts in ActiveRecord

10 October 2015 — 2-minute read

Changing the Channel

3 October 2015 — 3-minute read

Sep 2015

Generating Word Search Puzzles

26 September 2015 — 5-minute read

Default Scopes are an Anti-Pattern

19 September 2015 — 4-minute read

Way Back

The Buckblog Archives

Dating to 2004 — Hundreds more articles