Module: ArLazyPreload::Relation

Defined in:
lib/ar_lazy_preload/active_record/relation.rb

Overview

ActiveRecord::Relation patch with lazy preloading support

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#lazy_preload_valuesObject



77
78
79
# File 'lib/ar_lazy_preload/active_record/relation.rb', line 77

def lazy_preload_values
  @lazy_preload_values ||= []
end

#preloads_associations_lazily=(value) ⇒ Object (writeonly)

Sets the attribute preloads_associations_lazily

Parameters:

  • value

    the value to set the attribute preloads_associations_lazily to.



10
11
12
# File 'lib/ar_lazy_preload/active_record/relation.rb', line 10

def preloads_associations_lazily=(value)
  @preloads_associations_lazily = value
end

Instance Method Details

#lazy_preload(*args) ⇒ Object

Specify relationships to be loaded lazily when association is loaded for the first time. For example:

users = User.lazy_preload(:posts)
users.each do |user|
  user.first_name
end

will cause only one SQL request to load users, while

users = User.lazy_preload(:posts)
users.each do |user|
  user.posts.map(&:id)
end

will make an additional query.



66
67
68
69
# File 'lib/ar_lazy_preload/active_record/relation.rb', line 66

def lazy_preload(*args)
  check_if_method_has_arguments!(:lazy_preload, args)
  spawn.lazy_preload!(*args)
end

#lazy_preload!(*args) ⇒ Object



71
72
73
74
75
# File 'lib/ar_lazy_preload/active_record/relation.rb', line 71

def lazy_preload!(*args)
  args.flatten!
  self.lazy_preload_values += args
  self
end

#loadObject

Enhanced #load method will check if association has not been loaded yet and add a context for lazy preloading to loaded each record



25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/ar_lazy_preload/active_record/relation.rb', line 25

def load
  need_context = !loaded?
  result = super
  if need_context
    Context.register(
      records: ar_lazy_preload_records,
      association_tree: lazy_preload_values,
      auto_preload: preloads_associations_lazily?
    )
  end
  result
end

#preload_associations(records) ⇒ Object



12
13
14
15
16
17
18
19
20
21
# File 'lib/ar_lazy_preload/active_record/relation.rb', line 12

def preload_associations(records)
  preload = preload_values
  preload += includes_values unless eager_loading?

  preload.each do |associations|
    ArLazyPreload::Preloader.new(records, associations).preload.each do |preloader_association|
      handle_preloaded_records(preloader_association.preloaded_records)
    end
  end
end

#preload_associations_lazilyObject

Lazily autoloads all associations. For example:

users = User.preload_associations_lazily
users.each do |user|
  user.posts.flat_map {|post| post.comments.map(&:id)}
end

Same effect can be achieved by User.lazy_preload(posts: :comments)



46
47
48
# File 'lib/ar_lazy_preload/active_record/relation.rb', line 46

def preload_associations_lazily
  spawn.tap { |relation| relation.preloads_associations_lazily = true }
end