Class: OccamsRecord::EagerLoaders::Context

Inherits:
Object
  • Object
show all
Defined in:
lib/occams-record/eager_loaders/context.rb

Overview

A container for all eager loading on a particular Active Record model. Usually the context is initialized with the model, and all eager loaders are immediately initialized. Any errors (like a wrong association name ) will be thrown immediately and before any queries are run.

However, in certain situations the model cannot be known until runtime (e.g. eager loading off of a polymorphic association). In these cases the model won’t be set, or the eager loaders fully initialized, until the parent queries have run. This means that certain errors (like a wrong association name) won’t be noticed until very late, after queries have started running.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model = nil) ⇒ Context

Initialize a new eager loading context.



22
23
24
25
26
# File 'lib/occams-record/eager_loaders/context.rb', line 22

def initialize(model = nil)
  @model = model
  @loaders = []
  @dynamic_loaders = []
end

Instance Attribute Details

#modelActiveRecord::Base



15
16
17
# File 'lib/occams-record/eager_loaders/context.rb', line 15

def model
  @model
end

Instance Method Details

#<<(loader) ⇒ OccamsRecord::EagerLoaders::Base

Append an already-initialized eager loader.



57
58
59
60
# File 'lib/occams-record/eager_loaders/context.rb', line 57

def <<(loader)
  @loaders << loader
  loader
end

#add(assoc, scope = nil, select: nil, use: nil, as: nil, optimizer: :select) { ... } ⇒ OccamsRecord::EagerLoaders::Base

Specify an association to be eager-loaded. For maximum memory savings, only SELECT the colums you actually need.

ActiveRecord::Relation on which you may call all the normal query hethods (select, where, etc) as well as any scopes you’ve defined on the model.

Yields:

  • a block where you may perform eager loading on this association (optional)



76
77
78
79
80
81
82
83
84
85
# File 'lib/occams-record/eager_loaders/context.rb', line 76

def add(assoc, scope = nil, select: nil, use: nil, as: nil, optimizer: :select, &builder)
  if @model
    loader = build_loader(assoc, scope, select, use, as, optimizer, builder)
    @loaders << loader
    loader
  else
    @dynamic_loaders << [assoc, scope, select, use, as, optimizer, builder]
    nil
  end
end

#namesArray<String>

Return the names of the associations being loaded.



46
47
48
49
# File 'lib/occams-record/eager_loaders/context.rb', line 46

def names
  @loaders.map(&:name) +
    @loaders.select { |l| l.respond_to? :through_name }.map(&:through_name) # TODO make not hacky
end

#run!(rows, query_logger: nil) ⇒ Object

Performs all eager loading in this context (and in any nested ones).



93
94
95
96
97
98
99
# File 'lib/occams-record/eager_loaders/context.rb', line 93

def run!(rows, query_logger: nil)
  raise "Cannot run eager loaders when @model has not been set!" if @dynamic_loaders.any? and @model.nil?
  @loaders.each { |loader|
    loader.run(rows, query_logger: query_logger)
  }
  nil
end