Class: GraphQL::Models::AttributeLoader

Inherits:
Batch::Loader
  • Object
show all
Defined in:
lib/graphql/models/attribute_loader.rb

Overview

Simplified loader that can take a hash of attributes to match, combine them into a single query, and then fulfill then individually. It can also ask the database to order them correctly.

Defined Under Namespace

Classes: Request

Constant Summary collapse

WHERE_STRIP =
/\AWHERE /

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model_class) ⇒ AttributeLoader

Returns a new instance of AttributeLoader.



7
8
9
# File 'lib/graphql/models/attribute_loader.rb', line 7

def initialize(model_class)
  @model_class = model_class
end

Instance Attribute Details

#model_classObject (readonly)

Returns the value of attribute model_class.



5
6
7
# File 'lib/graphql/models/attribute_loader.rb', line 5

def model_class
  @model_class
end

Instance Method Details

#perform(requests) ⇒ Object

Parameters:

  • requests

    An AttributeLoader::Request (or a simple hash) that describes the models to be loaded



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/graphql/models/attribute_loader.rb', line 22

def perform(requests)
  # Combine the conditions together, into the minimal set of conditions needed
  conditions = HashCombiner.combine(requests.map { |r| r.is_a?(Request) ? r.attributes : r })

  # Get the distinct list of sorting conditions that we need to ask for, also
  sorters = requests.map { |r| r.is_a?(Request) ? r.sorting : nil }.compact.reject(&:blank?).uniq

  # Start constructing the query that we'll execute to get the results
  table = model_class.arel_table

  # Start building the query, add in the where conditions
  conditions.map! { |cond| hash_to_condition(table, cond) }
  query = table.where(conditions.reduce { |memo, cond| memo.or(cond) })

  # Convert the list of sorters into RANK() selections that we'll add to the selection
  order_selections = sorters.each_with_index.map { |s, idx| order_selection(s, idx) }

  # Add the projections to the query
  query = order_selections.reduce(query.project(:*)) { |memo, selection| memo.project(selection) }

  # Get the result set
  results = model_class.find_by_sql(query.to_sql)

  # De-multiplex the result set and fulfill the requests
  requests.each do |request|
    # Get the rows that match this request
    response = match_results(results, request)

    if response.size > 1 && request.is_a?(Request) && request.sorting
      idx = sorters.index(request.sorting)
      sort_by = "rank_#{idx}"
      response = response.sort_by { |row| row[sort_by] }
    end

    fulfill(request, response)
  end
end