Skip to content

Commit

Permalink
Refine related_through
Browse files Browse the repository at this point in the history
  • Loading branch information
lgebhardt committed Jan 13, 2024
1 parent 348eb32 commit dbfd061
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 8 deletions.
27 changes: 23 additions & 4 deletions lib/jsonapi/active_relation_retrieval.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ def find_related_ids(relationship, options)
end

module ClassMethods
def allowed_related_through
@allowed_related_through ||= [:inverse, :primary]
end

def default_find_related_through(polymorphic = false)
if polymorphic
JSONAPI.configuration.default_find_related_through_polymorphic
Expand Down Expand Up @@ -125,6 +129,11 @@ def find_fragments(filters, options)
options: options)

if options[:cache]
# When using caching the a two step process is used. First the records ids are retrieved and then the
# records are retrieved using the ids. Then the ids are used to query the database again to get the
# cache misses. In the second phase the records are not sorted or paginated and the `records_for_populate`
# method is used to ensure any dependent includes or custom database fields are calculated.

# This alias is going to be resolve down to the model's table name and will not actually be an alias
resource_table_alias = resource_klass._table_name

Expand Down Expand Up @@ -195,6 +204,10 @@ def find_fragments(filters, options)
warn "Performance issue detected: `#{self.name.to_s}.records` returned non-normalized results in `#{self.name.to_s}.find_fragments`."
end
else
# When not using caching resources can be generated after querying. The `records_for_populate`
# method is merged in to ensure any dependent includes or custom database fields are calculated.
records = records.merge(records_for_populate(options))

linkage_fields = []

linkage_relationships.each do |linkage_relationship|
Expand Down Expand Up @@ -318,10 +331,16 @@ def _find_related_monomorphic_fragments_through_primary(source_fragments, relati
resource_klass = relationship.resource_klass
linkage_relationships = resource_klass.to_one_relationships_for_linkage(include_directives[:include_related])

sort_criteria = []
options[:sort_criteria].try(:each) do |sort|
field = sort[:field].to_s == 'id' ? resource_klass._primary_key : sort[:field]
sort_criteria << { field: field, direction: sort[:direction] }
# Do not sort the related_fragments. This can be keyed off `connect_source_identity` to indicate whether this
# is a related resource primary step vs. an include step.
sort_related_fragments = !connect_source_identity

if sort_related_fragments
sort_criteria = []
options[:sort_criteria].try(:each) do |sort|
field = sort[:field].to_s == 'id' ? resource_klass._primary_key : sort[:field]
sort_criteria << { field: field, direction: sort[:direction] }
end
end

join_manager = ActiveRelation::JoinManagerThroughPrimary.new(resource_klass: self,
Expand Down
6 changes: 5 additions & 1 deletion lib/jsonapi/active_relation_retrieval_v09.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@ def records_for(relation_name)
end

module ClassMethods
def allowed_related_through
@allowed_related_through ||= [:model_includes]
end

def default_find_related_through(polymorphic = false)
polymorphic ? :model : :model
polymorphic ? :model_includes : :model_includes
end

# Finds Resources using the `filters`. Pagination and sort options are used when provided
Expand Down
4 changes: 4 additions & 0 deletions lib/jsonapi/active_relation_retrieval_v10.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ def find_related_ids(relationship, options)
end

module ClassMethods
def allowed_related_through
@allowed_related_through ||= [:primary]
end

def default_find_related_through(polymorphic = false)
polymorphic ? :primary : :primary
end
Expand Down
9 changes: 6 additions & 3 deletions lib/jsonapi/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,12 @@ def initialize
# Available strategies:
# 'JSONAPI::ActiveRelationRetrieval' - A configurable retrieval strategy
# 'JSONAPI::ActiveRelationRetrievalV09' - Retrieves resources using the v0.9.x approach. This uses rails'
# `includes` method to retrieve related models. This requires overriding the `records_for` method on the resource
# to control filtering of included resources.
# 'JSONAPI::ActiveRelationRetrievalV10' - Retrieves resources using the v0.10.x approach
# `includes` method to retrieve related models. This requires overriding the `records_for` method on the
# resource to control filtering of included resources.
# 'JSONAPI::ActiveRelationRetrievalV10' - Retrieves resources using the v0.10.x approach. While this is mostly
# equivalent to using the default JSONAPI::ActiveRelationRetrieval strategy with the
# `default_find_related_through` and `default_find_related_through_polymorphic` options set to `:primary`,
# it does perform a two phased query to retrieve resources like v0.10.x. did and is therefore less efficient.
# Custom - Specify the a custom retrieval strategy module name as a string
# :none
# :self
Expand Down

0 comments on commit dbfd061

Please sign in to comment.