Module: OccamsRecord::EagerLoaders::Builder

Included in:
AdHocBase, Base, PolymorphicBelongsTo, Query, RawQuery
Defined in:
lib/occams-record/eager_loaders/builder.rb

Overview

Methods for adding eager loading to a query.

Users MUST have an OccamsRecord::EagerLoaders::Context at @eager_loaders.

Instance Method Summary collapse

Instance Method Details

#eager_load(assoc, scope = nil, select: nil, use: nil, as: nil, optimizer: :select) { ... } ⇒ OccamsRecord::Query

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.

Parameters:

  • assoc (Symbol)

    name of association

  • scope (Proc) (defaults to: nil)

    a scope to apply to the query (optional). It will be passed an

  • select (String) (defaults to: nil)

    a custom SELECT statement, minus the SELECT (optional)

  • use (Array<Module>) (defaults to: nil)

    optional Module to include in the result class (single or array)

  • as (Symbol) (defaults to: nil)

    Load the association usign a different attribute name

  • optimizer (Symbol) (defaults to: :select)

    Only used for ‘through` associations. Options are :none (load all intermediate records) | :select (load all intermediate records but only SELECT the necessary columns)

Yields:

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

Returns:



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

def eager_load(assoc, scope = nil, select: nil, use: nil, as: nil, optimizer: :select, &builder)
  @eager_loaders.add(assoc, scope, select: select, use: use, as: as, optimizer: optimizer, &builder)
  self
end

#eager_load_many(name, mapping, sql, binds: {}, model: nil, use: nil) { ... } ⇒ Object

Specify some arbitrary SQL to be loaded into some arbitrary attribute (“name”). The attribute will hold an array of 0 or more associated records.

In the example below, :parts is NOT an association on Widget. Though if it where it would be a has_many. The mapping argument says “The widget_id column in this table (parts) maps to the id column in the other table (widgets)”. The %ids bind param will be provided for you, and in this case will be all the id values from the main query.

res = OccamsRecord.
  query(Widget.order("name")).
  eager_load_many(:parts, {:widget_id => :id}, %(
    SELECT * FROM parts WHERE widget_id IN (%{ids}) AND sku NOT IN (%{bad_skus})
  ), binds: {
    bad_skus: ["G90023ASDf0"]
  }).
  run

Parameters:

  • name (Symbol)

    name of attribute to load records into

  • mapping (Hash)

    a one element Hash with the key being the local/child id and the value being the foreign/parent id

  • sql (String)

    the SQL to query the associated records. Include a bind params called ‘%ids’ for the foreign/parent ids.

  • use (Array<Module>) (defaults to: nil)

    optional - Ruby modules to include in the result objects (single or array)

  • binds (Hash) (defaults to: {})

    any additional binds for your query.

  • model (ActiveRecord::Base) (defaults to: nil)

    optional - ActiveRecord model that represents what you’re loading. required when using Sqlite.

Yields:

  • eager load associations nested under this one



106
107
108
109
# File 'lib/occams-record/eager_loaders/builder.rb', line 106

def eager_load_many(name, mapping, sql, binds: {}, model: nil, use: nil, &builder)
  @eager_loaders << EagerLoaders::AdHocMany.new(name, mapping, sql, binds: binds, model: model, use: use, &builder)
  self
end

#eager_load_one(name, mapping, sql, binds: {}, model: nil, use: nil) { ... } ⇒ Object

Specify some arbitrary SQL to be loaded into some arbitrary attribute (“name”). The attribute will hold either one record or none.

In the example below, :category is NOT an association on Widget. Though if it where it would be a belongs_to. The mapping argument says “The id column in this table (categories) maps to the category_id column in the other table (widgets)”. The %ids bind param will be provided for you, and in this case will be all the category_id values from the main query.

res = OccamsRecord.
  query(Widget.order("name")).
  eager_load_one(:category, {:id => :category_id}, %(
    SELECT * FROM categories WHERE id IN (%{ids}) AND name != %{bad_name}
  ), binds: {
    bad_name: "Bad Category"
  }).
  run

Parameters:

  • name (Symbol)

    name of attribute to load records into

  • mapping (Hash)

    a one element Hash with the key being the local/child id and the value being the foreign/parent id

  • sql (String)

    the SQL to query the associated records. Include a bind params called ‘%ids’ for the foreign/parent ids.

  • binds (Hash) (defaults to: {})

    any additional binds for your query.

  • model (ActiveRecord::Base) (defaults to: nil)

    optional - ActiveRecord model that represents what you’re loading. required when using Sqlite.

  • use (Array<Module>) (defaults to: nil)

    optional - Ruby modules to include in the result objects (single or array)

Yields:

  • eager load associations nested under this one



75
76
77
78
# File 'lib/occams-record/eager_loaders/builder.rb', line 75

def eager_load_one(name, mapping, sql, binds: {}, model: nil, use: nil, &builder)
  @eager_loaders << EagerLoaders::AdHocOne.new(name, mapping, sql, binds: binds, model: model, use: use, &builder)
  self
end

#nest(assoc, scope = nil, select: nil, use: nil, as: nil, optimizer: :select) ⇒ OccamsRecord::EagerLoaders::Base

Same as eager_load, except it returns the new eager loader object instead of self. You can use the new object to call “nest” again, programtically building up nested eager loads instead of passing nested blocks.

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.

Parameters:

  • assoc (Symbol)

    name of association

  • scope (Proc) (defaults to: nil)

    a scope to apply to the query (optional). It will be passed an

  • select (String) (defaults to: nil)

    a custom SELECT statement, minus the SELECT (optional)

  • use (Array<Module>) (defaults to: nil)

    optional Module to include in the result class (single or array)

  • as (Symbol) (defaults to: nil)

    Load the association usign a different attribute name

  • optimizer (Symbol) (defaults to: :select)

    Only used for ‘through` associations. Options are :none (load all intermediate records) | :select (load all intermediate records but only SELECT the necessary columns)

Returns:

Raises:

  • (ArgumentError)


43
44
45
46
47
# File 'lib/occams-record/eager_loaders/builder.rb', line 43

def nest(assoc, scope = nil, select: nil, use: nil, as: nil, optimizer: :select)
  raise ArgumentError, "OccamsRecord::EagerLoaders::Builder#nest does not accept a block!" if block_given?
  @eager_loaders.add(assoc, scope, select: select, use: use, as: as, optimizer: optimizer) ||
    raise("OccamsRecord::EagerLoaders::Builder#nest may not be called under a polymorphic association")
end