Compatibility and Status of Goldiloader
masterGoldiloader is tested and compatible with the following environments:
- Rails versions: 7.2, 8.0, 8.1, and Edge
- Ruby (MRI) versions: 3.2, 3.3, and 3.4
repository·master·Indexed 23 days ago
https://github.com/salsify/goldiloaderAn ActiveRecord extension for Rails applications that provides automatic eager loading to solve the N+1 query problem. It detects when associations are accessed uniformly across a collection and loads them in a single batch query. Supports Rails 7.2+ and Ruby 3.2+, with additional features like custom preloads via `goldiload` and granular control to disable eager loading at the query, association, or global level.
Goldiloader is tested and compatible with the following environments:
Goldiloader automatically eager loads ActiveRecord associations when they are first accessed. It assumes that if you access an association on one model in a collection, you will likely do so for all of them.
When the first model in a loaded collection traverses an association, Goldiloader executes a single query (using IN (...)) to load that association for all models in the current context, preventing N+1 queries.
Example Behavior:
# Without Goldiloader:
# blogs.each { |blog| blog.posts.to_a }
# SELECT * FROM posts WHERE blog_id = 1
# SELECT * FROM posts WHERE blog_id = 2 ... (N queries)
# With Goldiloader:
# blogs.each { |blog| blog.posts.to_a }
# SELECT * FROM posts WHERE blog_id IN (1,2,3,4,5) (1 query)Goldiloader has certain limitations inherited from ActiveRecord's eager loading mechanism:
has_one with SQL limitsDo not use automatic eager loading for has_one associations that rely on a LIMIT 1 to return a single record. Eager loading converts the query to an IN (...) clause, which removes the limit and may fetch all associated records, causing performance issues.
Automatic eager loading is automatically disabled for associations that use:
limitoffsetfinder_sqlWorkaround: You can use Custom Preloads to handle these cases.
To use Goldiloader in your Rails application, add it to your Gemfile and run bundle install.
Requirements:
Note: For older versions of Rails/Ruby, refer to the specific release branches (e.g., release-5.x, release-4.x, etc.) in the repository.
# Gemfile
gem 'goldiloader'$ bundleOr install via gem directly:
$ gem install goldiloaderYou can disable automatic eager loading at three different granularities:
Use the auto_include(false) query scope method on an ActiveRecord relation.
Customize the association's scope in the model definition.
Disable it for all threads using Goldiloader.globally_enabled = false in an initializer. You can then selectively enable it for specific code blocks using Goldiloader.enabled { ... } or Goldiloader.disabled { ... }.
# Disable for a specific query
Blog.order(:name).auto_include(false)
# Disable for a specific association
class Blog < ActiveRecord::Base
has_many :posts, -> { auto_include(false) }
end
# Disable globally (in config/initializers/goldiloader.rb)
Goldiloader.globally_enabled = false
# Selectively enable/disable for a block (thread-local)
Goldiloader.enabled do
# Automatic eager loading is enabled for the current thread
end
Goldiloader.disabled do
# Automatic eager loading is disabled for the current thread
endGoldiloader automatically determines if an association can be eager loaded based on several criteria. An association is considered eager_loadable? if:
where, order, etc.) are always eager loadable.limit or offset calls.has_one associations, the scope cannot contain an order clause.Additionally, Goldiloader will only auto-include associations that do not have in-memory changes (i.e., they are not new_record?, changed?, or destroyed?), because the Rails association Preloader can clobber in-memory changes.
You can define custom preloads for non-association data (like aggregations, external API calls, or complex SQL) using the goldiload method.
Requirements:
self (the instance) to avoid breaking the internal caching mechanism.Use goldiload to fetch data based on a single ID (e.g., blog_id).
Pass a key: option to specify which attribute(s) to use for the lookup.
Pass an array to the key: option to perform lookups based on multiple columns (e.g., [:organizer_id, :room_id]).
Some ActiveRecord methods (like exists?, empty?, size, first, last) can behave differently depending on whether an association is already loaded in memory or if they trigger a new SQL query.
If you want to ensure that calling these methods triggers Goldiloader's automatic eager loading instead of executing a single-record SQL check, use the fully_load: true option on the association.
Goldiloader provides a way to enable or disable automatic eager loading globally or within specific blocks of code.
Goldiloader.globally_enabled = true/false to set the process-wide default. By default, it is set to true.Goldiloader.enabled = true/false sets the status for the current thread. This is useful for isolating changes to specific requests or background jobs.Goldiloader.enabled { ... } or Goldiloader.disabled { ... } methods to temporarily change the status for the duration of a block. This is the recommended way to disable eager loading for specific operations without affecting the rest of the application.The preloaded method allows you to manually define how data should be preloaded for a specific model and cache. This is useful when standard association preloading is insufficient.
To use it, provide the model class, a cache_name to identify the preload, and a key (or an array of keys) to extract from the records. The block passed to preloaded is executed in the context of the model's class, receiving the collected ids as an argument. The block should return a hash where the keys are the values extracted from the records and the values are the preloaded data.
Note: The block is executed using instance_exec on the model class to prevent accidental references to specific model instances, ensuring the logic operates at the class level.
You can control whether associations are automatically fully loaded by setting the default_fully_load class attribute on your ActiveRecord model. By default, this is set to false.
When default_fully_load is true, methods like .size, .ids, and .empty? on collection associations will trigger a full load of the association to ensure the collection is complete.
The goldiload method allows you to manually wrap a block of code to manage preloading within a specific context. This is useful for fine-grained control over when and how models are registered for automatic eager loading. It accepts an optional cache_name and a key (defaults to the class's primary key).
# Example usage of goldiload
User.goldiload do
# Code that triggers association loading
users = User.limit(5).to_a
users.each { |u| u.profile }
end