Skip to content

Commit dbfd061

Browse files
committed
Refine related_through
1 parent 348eb32 commit dbfd061

File tree

4 files changed

+38
-8
lines changed

4 files changed

+38
-8
lines changed

lib/jsonapi/active_relation_retrieval.rb

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ def find_related_ids(relationship, options)
77
end
88

99
module ClassMethods
10+
def allowed_related_through
11+
@allowed_related_through ||= [:inverse, :primary]
12+
end
13+
1014
def default_find_related_through(polymorphic = false)
1115
if polymorphic
1216
JSONAPI.configuration.default_find_related_through_polymorphic
@@ -125,6 +129,11 @@ def find_fragments(filters, options)
125129
options: options)
126130

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

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

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

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

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

lib/jsonapi/active_relation_retrieval_v09.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,12 @@ def records_for(relation_name)
1313
end
1414

1515
module ClassMethods
16+
def allowed_related_through
17+
@allowed_related_through ||= [:model_includes]
18+
end
19+
1620
def default_find_related_through(polymorphic = false)
17-
polymorphic ? :model : :model
21+
polymorphic ? :model_includes : :model_includes
1822
end
1923

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

lib/jsonapi/active_relation_retrieval_v10.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ def find_related_ids(relationship, options)
77
end
88

99
module ClassMethods
10+
def allowed_related_through
11+
@allowed_related_through ||= [:primary]
12+
end
13+
1014
def default_find_related_through(polymorphic = false)
1115
polymorphic ? :primary : :primary
1216
end

lib/jsonapi/configuration.rb

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

0 commit comments

Comments
 (0)