Need help with ar_lazy_preload?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

DmitryTsepelev
280 Stars 13 Forks MIT License 103 Commits 1 Opened issues

Description

Lazy loading associations for the ActiveRecord models

Services available

!
?

Need anything else?

Contributors list

# 124,490
Ruby
Rails
GraphQL
graphql...
66 commits
# 42,650
Ruby
ruby-on...
excel
pagespe...
15 commits
# 496,339
Go
Shell
apollog...
GraphQL
3 commits
# 596,959
Ruby
Rails
activer...
1 commit
# 472,359
Ruby
Rails
Shell
rspec
1 commit
# 23,106
Ruby
Rails
gRPC
yarn
1 commit
# 189,457
Ruby
Rails
Less
Shell
1 commit
# 303,241
Ruby
Rails
rails6
rails5
1 commit

ArLazyPreload Cult Of Martians Gem Version Build Status Maintainability Coverage Status

ArLazyPreload is a gem that brings association lazy load functionality to your Rails applications. There is a number of built-in methods to solve N+1 problem, but sometimes a list of associations to preload is not obvious–this is when you can get most of this gem.

  • Simple. The only thing you need to change is to use
    #lazy_preload
    instead of
    #includes
    ,
    #eager_load
    or
    #preload
  • Fast. Take a look at benchmarks (
    TASK=bench
    and
    TASK=memory
    )
  • Perfect fit for GraphQL. Define a list of associations to load at the top-level resolver and let the gem do its job
  • Auto-preload support. If you don't want to specify the association list–set
    ArLazyPreload.config.auto_preload
    to
    true

Sponsored by Evil Martians

Why should I use it?

Lazy loading is super helpful when the list of associations to load is determined dynamically. For instance, in GraphQL this list comes from the API client, and you'll have to inspect the selection set to find out what associations are going to be used.

This gem uses a different approach: it won't load anything until the association is called for a first time. When it happens–it loads all the associated records for all records from the initial relation in a single query.

Usage

Let's try

#lazy_preload
in action! The following code will perform a single SQL request (because we've never accessed posts):
users = User.lazy_preload(:posts).limit(10)  # => SELECT * FROM users LIMIT 10
users.map(&:first_name)

However, when we try to load posts, there will be one more request for posts:

users.map(&:posts) # => SELECT * FROM posts WHERE user_id in (...)

Auto preloading

If you want the gem to be even lazier–you can configure it to load all the associations lazily without specifying them explicitly. 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.

If you want to turn automatic preload off for a specific record, you can call

.skip_preload
before any associations method:
users.first.skip_preload.posts # => SELECT * FROM posts WHERE user_id = ?

Relation auto preloading

Another alternative for auto preloading is using relation

#preload_associations_lazily
method
posts = User.preload_associations_lazily.flat_map(&:posts)
# => SELECT * FROM users LIMIT 10
# => SELECT * FROM posts WHERE user_id in (...)

Gotchas

  1. Lazy preloading does not work for ActiveRecord < 6 when
    .includes
    is called earlier:
  Post.includes(:user).preload_associations_lazily.each do |p|
    p.user.comments.load
  end
  1. When
    #size
    is called on association (e.g.,
    User.lazy_preload(:posts).map { |u| u.posts.size }
    ), lazy preloading won't happen, because
    #size
    method performs
    SELECT COUNT()
    database request instead of loading the association when association haven't been loaded yet (here is the issue, and here is the explanation article about
    size
    ,
    length
    and
    count
    ).

Installation

Add this line to your application's Gemfile, and you're all set:

gem "ar_lazy_preload"

License

The gem is available as open source under the terms of the MIT License.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.