Class: JSONAPI::Serialization::IncludeFilterCache

Inherits:
Object
  • Object
show all
Defined in:
lib/json_api/serialization/include_filter_cache.rb

Overview

Request-scoped memoization for include filtering.

The include walk re-checks the related resource's scope (and the authorization hook) against the loaded records once per parent record, per hop, per include path. Within one request those verdicts cannot change: the scopes are functions of the related class and the controller. So compute each class's filter data once, and vet each record id at most once. Pure memoization — the allowed set is identical, id for id, to the per-visit filtering it replaces.

Defined Under Namespace

Classes: Entry

Instance Method Summary collapse

Constructor Details

#initialize(authorization_context: nil) ⇒ IncludeFilterCache

Returns a new instance of IncludeFilterCache.



18
19
20
21
22
# File 'lib/json_api/serialization/include_filter_cache.rb', line 18

def initialize(authorization_context: nil)
  @authorization_context = authorization_context
  @entries = {}
  @verdicts = {}
end

Instance Method Details

#filter(records, klass) ⇒ Object

Filters loaded records with the same rules as the per-visit filtering: a narrowed authorization scope vets ids in the database; a resource scope with no where clause keeps everything; a where-hash-expressible scope matches in memory; anything else vets ids in the database against the resource scope.



29
30
31
32
33
34
35
36
# File 'lib/json_api/serialization/include_filter_cache.rb', line 29

def filter(records, klass)
  entry = entry_for(klass)
  return filter_by_ids(records, klass, :authorized, entry.authorized_scope) if entry.narrowed
  return records if entry.where_clause_empty
  return filter_by_ids(records, klass, :base, entry.base_scope) if entry.where_hash.blank?

  records.select { |record| matches_where_hash?(record, entry.where_hash) }
end

#warm(klass, ids) ⇒ Object

Vets ids ahead of the walk, one query per class, so the per-visit checks answer from memory. Safe to skip: #filter queries lazily.



40
41
42
43
44
45
46
47
# File 'lib/json_api/serialization/include_filter_cache.rb', line 40

def warm(klass, ids)
  entry = entry_for(klass)
  if entry.narrowed
    vet_ids(klass, :authorized, entry.authorized_scope, ids)
  elsif !entry.where_clause_empty && entry.where_hash.blank?
    vet_ids(klass, :base, entry.base_scope, ids)
  end
end