module Sequel::Plugins::TacticalEagerLoading

  1. lib/sequel/plugins/tactical_eager_loading.rb

The tactical_eager_loading plugin allows you to eagerly load an association for all objects retrieved from the same dataset without calling eager on the dataset. If you attempt to load associated objects for a record and the association for that object is currently not cached, it assumes you want to get the associated objects for all objects retrieved with the dataset that retrieved the current object.

Tactical eager loading only takes affect if you retrieved the current object with Dataset#all, it doesn't work if you retrieved the current object with Dataset#each.

Basically, this allows the following code to issue only two queries:

Album.where{id<100}.all do |a|
  a.artists
end
# SELECT * FROM albums WHERE (id < 100)
# SELECT * FROM artists WHERE id IN (...)

Note that if you are passing a callback to the association method via a block or :callback option, or using the :reload option to reload the association, eager loading will not be done.

You can use the :eager_reload option to reload the association for all objects that the current object was retrieved with:

# SELECT * FROM albums WHERE (id < 100)
albums = Album.where{id<100}.all

# Eagerly load all artists for these albums
# SELECT * FROM artists WHERE id IN (...)
albums.first.artists

# Do something that may affect which artists are associated to the albums

# Eagerly reload all artists for these albums
# SELECT * FROM artists WHERE id IN (...)
albums.first.artists(:eager_reload=>true)

You can also use the :eager option to specify dependent associations to eager load:

albums = Album.where{id<100}.all

 # Eager load all artists for these albums, and all albums for those artists
 # SELECT * FROM artists WHERE id IN (...)
 # SELECT * FROM albums WHERE artist_id IN (...)
 albums.first.artists(:eager=>:albums)

You can also use :eager to specify an eager callback. For example:

albums = Album.where{id<100}.all

# Eagerly load all artists whose name starts with A-M for these albums
# SELECT * FROM artists WHERE name > 'N' AND id IN (...)
albums.first.artists(:eager=>proc{|ds| ds.where(:name > 'N')})

Usage:

# Make all model subclass instances use tactical eager loading (called before loading subclasses)
Sequel::Model.plugin :tactical_eager_loading

# Make the Album class use tactical eager loading
Album.plugin :tactical_eager_loading