Class: Praxis::Extensions::FieldSelection::ActiveRecordQuerySelector

Inherits:
Object
  • Object
show all
Defined in:
lib/praxis/extensions/field_selection/active_record_query_selector.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(query:, selectors:, debug: false) ⇒ ActiveRecordQuerySelector

Gets a dataset, a selector…and should return a dataset with the selector definition applied.



10
11
12
13
14
# File 'lib/praxis/extensions/field_selection/active_record_query_selector.rb', line 10

def initialize(query:, selectors:, debug: false)
  @selector = selectors
  @query = query
  @logger = debug ? Logger.new($stdout) : nil
end

Instance Attribute Details

#queryObject (readonly)

Returns the value of attribute query.



7
8
9
# File 'lib/praxis/extensions/field_selection/active_record_query_selector.rb', line 7

def query
  @query
end

#selectorObject (readonly)

Returns the value of attribute selector.



7
8
9
# File 'lib/praxis/extensions/field_selection/active_record_query_selector.rb', line 7

def selector
  @selector
end

Instance Method Details

#add_select(query:, selector_node:) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/praxis/extensions/field_selection/active_record_query_selector.rb', line 28

def add_select(query:, selector_node:)
  # We're gonna always require the PK of the model, as it is a special case for AR, and the app itself
  # might assume it is always there and not be surprised by the fact that if it isn't, it won't blow up
  # in the same way as any other attribute not being loaded...i.e., ActiveModel::MissingAttributeError: missing attribute: xyz
  select_fields =
    _hoist_select(
      selector_node: selector_node,
      fields_closure:
        Set.new([selector_node.resource.model.primary_key.to_sym]),
    ).to_a
  select_fields.empty? ? query : query.select(*select_fields)
end

#explain_query(query, eager_hash) ⇒ Object



41
42
43
44
45
46
47
48
49
50
# File 'lib/praxis/extensions/field_selection/active_record_query_selector.rb', line 41

def explain_query(query, eager_hash)
  @logger.debug(
    "Query plan for ...#{selector.resource.model} with selectors: #{JSON.generate(selector.dump)}",
  )
  @logger.debug(
    " ActiveRecord query: #{selector.resource.model}.includes(#{eager_hash})",
  )
  query.explain
  @logger.debug('Query plan end')
end

#generateObject



16
17
18
19
20
21
22
23
24
25
26
# File 'lib/praxis/extensions/field_selection/active_record_query_selector.rb', line 16

def generate
  # TODO: unfortunately, I think we can only control the select clauses for the top model
  # (as I'm not sure ActiveRecord supports expressing it in the join...)
  @query = add_select(query: query, selector_node: selector)
  eager_hash = _eager(selector)

  @query = @query.includes(eager_hash)
  explain_query(query, eager_hash) if @logger

  @query
end