The maze book for programmers!
PragProg Amazon BN.com

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|
  updated_ids.concat(relation.pluck(:id))
  relation.update_all(author_id: new_id)
end

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.

Medium.com

2 April 2016 — The author expresses his intent to write future articles on Medium.com — 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