Lazy loading associations for the ActiveRecord models. #includes
, #eager_load
and #preload
are built-in methods to avoid N+1 problem, but sometimes when DB request is made we don't know what associations we are going to need later (for instance when your API allows client to define a list of loaded associations dynamically). The only possible solution for such cases is to load all the associations we might need, but it can be a huge overhead.
This gem allows to set up lazy preloading for associations - it won't load anything until association is called for a first time, but when it happens - it loads all the associated records for all records from the initial relation in a single query.
Add this line to your application's Gemfile, and you're all set:
gem "ar_lazy_preload"
For example, if we define the following relation
users = User.lazy_preload(:posts).limit(10)
and use it in the following way
users.map(&:first_name)
there will be one query because we've never accessed posts:
SELECT * FROM users LIMIT 10
However, when we try to load posts
users.map(&:posts)
there will be one more request for posts:
SELECT * FROM posts WHERE user_id in (...)
If you want the gem to be even more lazy - you can configure it to load all the associations lazily without specifying them explicitly. In order to do that you'll need to change the configuration in the following way:
ArLazyPreload.config.auto_preload = true
After that there is no need to call lazy_preload
on the association, everything would be loaded lazily.
Worried about the performance? Take a look at benchmarks (
TASK=bench
andTASK=memory
)
The gem is available as open source under the terms of the MIT License.