After years of working on OccamsRecord and wondering if and how any of it could be ported to Rails/ActiveRecord, I finally made the first step: Uberloader.

Uberloader is an “extension” (read: shameful monkeypatch) to ActiveRecord enabling you to customize the SQL of preloaded associations. Add a WHERE condition, ORDER BY, etc.

Example

widgets = Widget
  .where(category_id: category_ids)
  .uberload(:category)
  # order parts
  .uberload(:parts, scope: Part.order(:name)) do |u|
    # Nested uberloads use blocks
    u.uberload(:manufacturer)
    u.uberload(:subparts) do
      # do something to subparts's scope
      u.scope my_subparts_scope_helper
      u.scope Subpart.active if params[:only_active]

      u.uberload(:foo) do
        u.uberload(:bar)
      end
    end
  end

Why not in the model?

You can easily customize the scope of an association when you define it in the model:

class Widget < ApplicationRecord
  has_many :parts, -> { order(:name) }
end

But that’s not very flexible. What if one page/API wants them in descending order? Ordered by price? Filtered by status? You’re out of luck.

ActiveRecord::Associations::Preloader?

This does work. In fact it’s how Uberloader is implemented. But it’s a private, undocumented class. It’s not stable across major Rails versions, and it’s incredibly akward to use on nested associations. Uberloader papers over all those issues, but it is a monkeypatch.

Is this monkeypatched thing safe to use?

Probably. If no uberload calls are made on a query, the patch simply calls super. So non-uberloaded queries are quite safe. But what about queries that do use uberload?

Uberloader has a version matrix test suite that tests every version of Uberloader, plus the latest git commit, against every (supported) version of ActiveRecord. It runs daily and records the results on GitHub. So unless you’re updating Rails versions same-day, you’re pretty well covered.

Why isn’t this in Rails?

I’d love to see it (likely with a different name). Maybe it will be my next project…