Class: OccamsRecord::Query

Inherits:
Object
  • Object
show all
Includes:
Enumerable, Batches, EagerLoaders::Builder
Defined in:
lib/occams-record/query.rb

Overview

Represents a query to be run and eager associations to be loaded. Use OccamsRecord.query to create your queries instead of instantiating objects directly.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from EagerLoaders::Builder

#eager_load, #eager_load_many, #eager_load_one, #nest

Methods included from Batches

#find_each, #find_in_batches

Constructor Details

#initialize(scope, use: nil, eager_loaders: nil, query_logger: nil) ⇒ Query

Initialize a new query.

Parameters:

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

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

  • query_logger (Array) (defaults to: nil)

    (optional) an array into which all queries will be inserted for logging/debug purposes

  • eager_loaders (OccamsRecord::EagerLoaders::Context) (defaults to: nil)


51
52
53
54
55
56
57
# File 'lib/occams-record/query.rb', line 51

def initialize(scope, use: nil, eager_loaders: nil, query_logger: nil)
  @model = scope.klass
  @scope = scope
  @eager_loaders = eager_loaders || EagerLoaders::Context.new(@model)
  @use = use
  @query_logger = query_logger
end

Instance Attribute Details

#modelActiveRecord::Base (readonly)

Returns:

  • (ActiveRecord::Base)


35
36
37
# File 'lib/occams-record/query.rb', line 35

def model
  @model
end

#scopeActiveRecord::Relation (readonly)

Returns scope for building the main SQL query.

Returns:

  • (ActiveRecord::Relation)

    scope for building the main SQL query



37
38
39
# File 'lib/occams-record/query.rb', line 37

def scope
  @scope
end

Instance Method Details

#countInteger

Returns the number of rows that will be returned if the query is run.

Returns:

  • (Integer)


96
97
98
# File 'lib/occams-record/query.rb', line 96

def count
  scope.count
end

#each {|OccamsRecord::Results::Row| ... } ⇒ Object

If you pass a block, each result row will be yielded to it. If you don’t, an Enumerable will be returned.

Yields:

Returns:

  • Enumerable



126
127
128
129
130
131
132
# File 'lib/occams-record/query.rb', line 126

def each
  if block_given?
    to_a.each { |row| yield row }
  else
    to_a.each
  end
end

#firstOccamsRecord::Results::Row

Run the query with LIMIT 1 and return the first result (which could be nil).



105
106
107
# File 'lib/occams-record/query.rb', line 105

def first
  run { |q| q.limit 1 }.first
end

#first!OccamsRecord::Results::Row

Run the query with LIMIT 1 and return the first result. If nothing is found an OccamsRecord::NotFound exception will be raised.



115
116
117
# File 'lib/occams-record/query.rb', line 115

def first!
  first || raise(OccamsRecord::NotFound.new(model.name, scope.where_values_hash))
end

#run {|ActiveRecord::Relation| ... } ⇒ Array<OccamsRecord::Results::Row> Also known as: to_a

Run the query and return the results.

You may optionally pass a block to modify the query just before it’s run (the change will NOT persist). This is very useful for running paginated queries.

occams = OccamsRecord.query(Widget.all)

# returns first 100 rows
occams.run { |q| q.offset(0).limit(100) }

# returns second 100 rows
occams.run { |q| q.offset(100).limit(100) }

# returns ALL rows
occams.run

Yields:

  • (ActiveRecord::Relation)

    You may use this to return and run a modified relation

Returns:



79
80
81
82
83
84
85
86
87
# File 'lib/occams-record/query.rb', line 79

def run
  sql = block_given? ? yield(scope).to_sql : scope.to_sql
  @query_logger << sql if @query_logger
  result = model.connection.exec_query sql
  row_class = OccamsRecord::Results.klass(result.columns, result.column_types, @eager_loaders.names, model: model, modules: @use)
  rows = result.rows.map { |row| row_class.new row }
  @eager_loaders.run!(rows, query_logger: @query_logger)
  rows
end