Module: JSONAPI::Serialization::IncludeFiltering

Included in:
IncludesSerialization
Defined in:
lib/json_api/serialization/concerns/include_filtering.rb

Instance Method Summary collapse

Instance Method Details

#filter_by_query(loaded_array, resource_scope) ⇒ Object



48
49
50
51
# File 'lib/json_api/serialization/concerns/include_filtering.rb', line 48

def filter_by_query(loaded_array, resource_scope)
  valid_ids = resource_scope.where(id: loaded_array.filter_map(&:id)).pluck(:id).to_set
  loaded_array.select { |r| valid_ids.include?(r.id) }
end

#filter_by_where_hash(loaded_array, resource_scope, related_klass) ⇒ Object



28
29
30
31
32
33
# File 'lib/json_api/serialization/concerns/include_filtering.rb', line 28

def filter_by_where_hash(loaded_array, resource_scope, related_klass)
  hash = where_values_hash_for_scope(resource_scope, related_klass)
  return filter_by_query(loaded_array, resource_scope) if hash.blank?

  loaded_array.select { |r| record_matches_where_hash?(r, hash) }
end

#filter_loaded_records(association, related_klass) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/json_api/serialization/concerns/include_filtering.rb', line 6

def filter_loaded_records(association, related_klass)
  loaded_array = association.target.respond_to?(:to_a) ? association.target.to_a : Array(association.target)
  return [] if loaded_array.empty?

  base_scope = ResourceLoader.find_for_model(related_klass).records
  authorized_scope = apply_include_authorization(base_scope, related_klass)

  # When the authorization_scope hook narrows the relation (joins/subqueries a
  # where-hash can't express), the eager-loaded set — preloaded through acts_as_tenant
  # alone — must be re-checked against the authorized scope in the database, so a
  # relationship never surfaces a record the related endpoint denies. An unchanged
  # scope keeps the in-memory, query-free records-only filtering.
  return filter_by_query(loaded_array, authorized_scope) if narrowed?(base_scope, authorized_scope)
  return loaded_array if base_scope.where_clause.empty?

  filter_by_where_hash(loaded_array, base_scope, related_klass)
end

#narrowed?(base_scope, authorized_scope) ⇒ Boolean

Returns:

  • (Boolean)


24
25
26
# File 'lib/json_api/serialization/concerns/include_filtering.rb', line 24

def narrowed?(base_scope, authorized_scope)
  authorized_scope.to_sql != base_scope.to_sql
end

#record_matches_where_hash?(record, hash) ⇒ Boolean

Returns:

  • (Boolean)


41
42
43
44
45
46
# File 'lib/json_api/serialization/concerns/include_filtering.rb', line 41

def record_matches_where_hash?(record, hash)
  hash.all? do |attr, val|
    r_val = record.read_attribute(attr)
    val.is_a?(Array) ? val.include?(r_val) : r_val == val
  end
end

#where_values_hash_for_scope(resource_scope, related_klass) ⇒ Object



35
36
37
38
39
# File 'lib/json_api/serialization/concerns/include_filtering.rb', line 35

def where_values_hash_for_scope(resource_scope, related_klass)
  resource_scope.where_values_hash(related_klass.table_name)
rescue StandardError
  {}
end