Occasionally a method will be passed a model, or an array of models, and 
access (possibly nested) associations on those models. In certain cases it 
may be difficult to update the code that originally fetches those models to 
eager load the appropriate models, but we do want to ensure those 
associations are eager loaded.

The tactial_eager_loading_plugin 
<https://sequel.jeremyevans.net/rdoc-plugins/classes/Sequel/Plugins/TacticalEagerLoading.html>
 
partially solves this problem by proactively fetching associations on a set 
of models that were loaded together, but I'm hesitant to use it because it 
removes control from the programmer to control exactly what gets loaded 
when.

I wrote a plugin that allows eager loading (including nested associations) 
on an array of models that are already in memory. Here's a gist with the 
code:

https://gist.github.com/PaulJuliusMartinez/bd2a2c243dcd3b5990ccf2984dca12f5

A more in-depth explanation of the plugin's capabilities from the above 
gist:

This plugin adds support for eager loading associations _after_ a record, or
multiple records, have been fetched from the database. It is useful for 
ensuring
nested associations are efficiently loaded when it is difficult to modify 
the
dataset used to initially fetch the data.

Example usage:

  artist = Artist.first

  # SELECT * FROM albums WHERE artist_id = ?
  # SELECT * FROM tracks WHERE album_id IN (?, ?, ?, ...)
  Artist.eager_load(artist, albums: :tracks)

  # No queries issued
  artist.albums[2].tracks

Additionally, an array of models may be passed in to eager load 
associations for all
of them:

  albums = Album.dataset.limit(10).all

  # SELECT * FROM tracks WHERE album_id IN (?, ?, ?, ...)
  Album.eager_load(albums, :tracks)

The plugin will traverse through associations already loaded to eager load 
nested
associations:

  artist = Artist.first
  artist.albums

  # SELECT * FROM tracks WHERE album_id IN (?, ?, ?, ...)
  Artist.eager_load(artist, albums: :tracks)

This plugin supports the same capabilities as the regular eager method, 
namely
using procs as callbacks for filtering association dataset. If an 
association has
already been loaded, however, the proc will not apply to that dataset.


This method is very similar to the private eager_load 
<https://github.com/jeremyevans/sequel/blob/master/lib/sequel/model/associations.rb#L3324-L3374>
 Dataset 
method defined by the associations plugin.

I think moving this method to become a Class method (as I've essentially 
done in the plugin above) would make the incredible existing eager loading 
functionality even more flexible and more powerful. It makes sense to 
separate eager loading from the initial fetching of data. Nested 
associations are likely paired with nested processing or nested code 
structure, which means that the initial fetching of the data and accessing 
of the association are far apart (in terms of lines of code or method 
calls). This makes it difficult to ensure that data is properly eager 
loaded, but by allowing this method to be used after models are fetched, it 
makes it possible to move our intentions for fetching data closer to where 
we actually use it.

Obviously I don't expect this architectural change to be implemented 
without significant deliberation. It's just a suggestion borne from 
personal experience with a large Sequel codebase.

-- 
You received this message because you are subscribed to the Google Groups 
"sequel-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sequel-talk.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sequel-talk/adf89507-e22c-4f67-baec-6b8c5cf481be%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to