Skip to content

Commit c9202e7

Browse files
committed
Refine related_through
1 parent 0f7ff61 commit c9202e7

4 files changed

+38
-8
lines changed

lib/jsonapi/active_relation_retrieval.rb

+23-4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ def find_related_ids(relationship, options)
99
end
1010

1111
module ClassMethods
12+
def allowed_related_through
13+
@allowed_related_through ||= [:inverse, :primary]
14+
end
15+
1216
def default_find_related_through(polymorphic = false)
1317
if polymorphic
1418
JSONAPI.configuration.default_find_related_through_polymorphic
@@ -127,6 +131,11 @@ def find_fragments(filters, options)
127131
options: options)
128132

129133
if options[:cache]
134+
# When using caching the a two step process is used. First the records ids are retrieved and then the
135+
# records are retrieved using the ids. Then the ids are used to query the database again to get the
136+
# cache misses. In the second phase the records are not sorted or paginated and the `records_for_populate`
137+
# method is used to ensure any dependent includes or custom database fields are calculated.
138+
130139
# This alias is going to be resolve down to the model's table name and will not actually be an alias
131140
resource_table_alias = resource_klass._table_name
132141

@@ -197,6 +206,10 @@ def find_fragments(filters, options)
197206
warn "Performance issue detected: `#{self.name.to_s}.records` returned non-normalized results in `#{self.name.to_s}.find_fragments`."
198207
end
199208
else
209+
# When not using caching resources can be generated after querying. The `records_for_populate`
210+
# method is merged in to ensure any dependent includes or custom database fields are calculated.
211+
records = records.merge(records_for_populate(options))
212+
200213
linkage_fields = []
201214

202215
linkage_relationships.each do |linkage_relationship|
@@ -320,10 +333,16 @@ def _find_related_monomorphic_fragments_through_primary(source_fragments, relati
320333
resource_klass = relationship.resource_klass
321334
linkage_relationships = resource_klass.to_one_relationships_for_linkage(include_directives[:include_related])
322335

323-
sort_criteria = []
324-
options[:sort_criteria].try(:each) do |sort|
325-
field = sort[:field].to_s == 'id' ? resource_klass._primary_key : sort[:field]
326-
sort_criteria << { field: field, direction: sort[:direction] }
336+
# Do not sort the related_fragments. This can be keyed off `connect_source_identity` to indicate whether this
337+
# is a related resource primary step vs. an include step.
338+
sort_related_fragments = !connect_source_identity
339+
340+
if sort_related_fragments
341+
sort_criteria = []
342+
options[:sort_criteria].try(:each) do |sort|
343+
field = sort[:field].to_s == 'id' ? resource_klass._primary_key : sort[:field]
344+
sort_criteria << { field: field, direction: sort[:direction] }
345+
end
327346
end
328347

329348
join_manager = ActiveRelation::JoinManagerThroughPrimary.new(resource_klass: self,

lib/jsonapi/active_relation_retrieval_v09.rb

+5-1
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,12 @@ def records_for(relation_name)
1515
end
1616

1717
module ClassMethods
18+
def allowed_related_through
19+
@allowed_related_through ||= [:model_includes]
20+
end
21+
1822
def default_find_related_through(polymorphic = false)
19-
polymorphic ? :model : :model
23+
polymorphic ? :model_includes : :model_includes
2024
end
2125

2226
# Finds Resources using the `filters`. Pagination and sort options are used when provided

lib/jsonapi/active_relation_retrieval_v10.rb

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ def find_related_ids(relationship, options)
99
end
1010

1111
module ClassMethods
12+
def allowed_related_through
13+
@allowed_related_through ||= [:primary]
14+
end
15+
1216
def default_find_related_through(polymorphic = false)
1317
polymorphic ? :primary : :primary
1418
end

lib/jsonapi/configuration.rb

+6-3
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,12 @@ def initialize
178178
# Available strategies:
179179
# 'JSONAPI::ActiveRelationRetrieval' - A configurable retrieval strategy
180180
# 'JSONAPI::ActiveRelationRetrievalV09' - Retrieves resources using the v0.9.x approach. This uses rails'
181-
# `includes` method to retrieve related models. This requires overriding the `records_for` method on the resource
182-
# to control filtering of included resources.
183-
# 'JSONAPI::ActiveRelationRetrievalV10' - Retrieves resources using the v0.10.x approach
181+
# `includes` method to retrieve related models. This requires overriding the `records_for` method on the
182+
# resource to control filtering of included resources.
183+
# 'JSONAPI::ActiveRelationRetrievalV10' - Retrieves resources using the v0.10.x approach. While this is mostly
184+
# equivalent to using the default JSONAPI::ActiveRelationRetrieval strategy with the
185+
# `default_find_related_through` and `default_find_related_through_polymorphic` options set to `:primary`,
186+
# it does perform a two phased query to retrieve resources like v0.10.x. did and is therefore less efficient.
184187
# Custom - Specify the a custom retrieval strategy module name as a string
185188
# :none
186189
# :self

0 commit comments

Comments
 (0)