The forbid_lazy_load plugin forbids lazy loading of associations for objects in cases where the object wasn’t loaded with a method that only returns a single object.
The main reason for doing this is it makes it easier to detect N+1 query issues. Note that Sequel
also offers a tactical_eager_loading plugin which will automatically eagerly load associations for all objects retrived in the same query if any object would attempt to lazily load an association. That approach may be simpler if you are trying to prevent N+1 issues, though it does retain more objects in memory.
This plugin offers multiple different ways to forbid lazy loading. You can forbid lazy loading associations for individual model instances:
obj = Album[1] obj.forbid_lazy_load obj.artist # raises Sequel::Plugins::ForbidLazyLoad::Error
forbid_lazy_load
is automatically called on instances if the instances are loaded via a method such as Dataset#all, Dataset#each, and other methods that load multiple instances at once. These are the cases where lazily loading associations for such instances can cause N+1 issues.
Album.all.first.artist objs.first.artist # raises Sequel::Plugins::ForbidLazyLoad::Error Album.each do |obj| obj.artist # raises Sequel::Plugins::ForbidLazyLoad::Error end Album[1].artist # no error Album.first.artist # no error
You can allow lazy loading associations for an instance that it was previously forbidden for:
obj = Album.all.first obj.allow_lazy_load obj.artist # no error
You can forbid lazy loading associations on a per-call basis, even if lazy loading of associations is allowed for the instance:
obj = Album[1] obj.artist(forbid_lazy_load: true) # raises Sequel::Plugins::ForbidLazyLoad::Error
This also works for allowing lazy loading associations for a specific association load even if it is forbidden for the instance:
obj = Album.all.first obj.artist(forbid_lazy_load: false) # nothing raised
You can also forbid lazy loading on a per-association basis using the :forbid_lazy_load
association option with a true
value:
Album.many_to_one :artist, forbid_lazy_load: true Album[1].artist # raises Sequel::Plugins::ForbidLazyLoad::Error
However, you probably don’t want to do this as it will forbid any lazy loading of the association, even if the loading could not result in an N+1 issue.
On the flip side, you can allow lazy loading using the :forbid_lazy_load
association option with a false
value:
Album.many_to_one :artist, forbid_lazy_load: false Album.all.first.artist # no error
One reason to do this is when using a plugin like static_cache on the associated model, where a query is not actually issued when doing a lazy association load. To make that particular case easier, this plugin makes Model.finalize_associations automatically set the association option if the associated class uses the static_cache plugin.
Note that even with this plugin, there can still be N+1 issues, such as:
Album.each do |obj| # 1 query for all albums Artist[obj.artist_id] # 1 query per album for each artist end
Usage:
# Make all model subclasses support forbidding lazy load # (called before loading subclasses) Sequel::Model.plugin :forbid_lazy_load # Make the Album class support forbidding lazy load Album.plugin :forbid_lazy_load