@@ -70,6 +70,16 @@ def find_by_keys(keys, options = {})
7070 resources_for ( records , options [ :context ] )
7171 end
7272
73+ # Returns an array of Resources identified by the `keys` array. The resources are not filtered as this
74+ # will have been done in a prior step
75+ #
76+ # @param keys [Array<key>] Array of primary keys to find resources for
77+ # @option options [Hash] :context The context of the request, set in the controller
78+ def find_to_populate_by_keys ( keys , options = { } )
79+ records = records_for_populate ( options ) . where ( _primary_key => keys )
80+ resources_for ( records , options [ :context ] )
81+ end
82+
7383 # Finds Resource fragments using the `filters`. Pagination and sort options are used when provided.
7484 # Retrieving the ResourceIdentities and attributes does not instantiate a model instance.
7585 # Note: This is incompatible with Polymorphic resources (which are going to come from two separate tables)
@@ -242,10 +252,57 @@ def count_related(source_rid, relationship_name, options = {})
242252 count_records ( records )
243253 end
244254
245- def records ( _options = { } )
255+ # This resource finder (ActiveRecordResourceFinder) uses an `ActiveRecord::Relation` as the starting point for
256+ # retrieving models. From this relation filters, sorts and joins are applied as needed.
257+ # Depending on which phase of the request processing different `records` methods will be called, giving the user
258+ # the opportunity to override them differently for performance and security reasons.
259+
260+ # begin `records`methods
261+
262+ # Base for the `records` methods that follow and is not directly used for accessing model data by this class.
263+ # Overriding this method gives a single place to affect the `ActiveRecord::Relation` used for the resource.
264+ #
265+ # @option options [Hash] :context The context of the request, set in the controller
266+ #
267+ # @return [ActiveRecord::Relation]
268+ def records_base ( _options = { } )
246269 _model_class . all
247270 end
248271
272+ # The `ActiveRecord::Relation` used for finding user requested models. This may be overridden to enforce
273+ # permissions checks on the request.
274+ #
275+ # @option options [Hash] :context The context of the request, set in the controller
276+ #
277+ # @return [ActiveRecord::Relation]
278+ def records ( options = { } )
279+ records_base ( options )
280+ end
281+
282+ # The `ActiveRecord::Relation` used for populating the ResourceSet. Only resources that have been previously
283+ # identified through the `records` method will be accessed. Thus it should not be necessary to reapply permissions
284+ # checks. However if the model needs to include other models adding `includes` is appropriate
285+ #
286+ # @option options [Hash] :context The context of the request, set in the controller
287+ #
288+ # @return [ActiveRecord::Relation]
289+ def records_for_populate ( options = { } )
290+ records_base ( options )
291+ end
292+
293+ # The `ActiveRecord::Relation` used for the finding related resources. Only resources that have been previously
294+ # identified through the `records` method will be accessed and used as the basis to find related resources. Thus
295+ # it should not be necessary to reapply permissions checks.
296+ #
297+ # @option options [Hash] :context The context of the request, set in the controller
298+ #
299+ # @return [ActiveRecord::Relation]
300+ def records_for_source_to_related ( options = { } )
301+ records_base ( options )
302+ end
303+
304+ # end `records` methods
305+
249306 def apply_join ( records :, relationship :, resource_type :, join_type :, options :)
250307 if relationship . polymorphic? && relationship . belongs_to?
251308 case join_type
@@ -267,7 +324,7 @@ def apply_join(records:, relationship:, resource_type:, join_type:, options:)
267324 end
268325
269326 def relationship_records ( relationship :, join_type : :inner , resource_type : nil , options : { } )
270- records = relationship . parent_resource . records ( options )
327+ records = relationship . parent_resource . records_for_source_to_related ( options )
271328 strategy = relationship . options [ :apply_join ]
272329
273330 if strategy
@@ -336,7 +393,7 @@ def find_related_monomorphic_fragments(source_rids, relationship, options, conne
336393
337394 paginator = options [ :paginator ] if source_rids . count == 1
338395
339- records = apply_request_settings_to_records ( records : records ( options ) ,
396+ records = apply_request_settings_to_records ( records : records_for_source_to_related ( options ) ,
340397 resource_klass : resource_klass ,
341398 sort_criteria : sort_criteria ,
342399 primary_keys : source_ids ,
@@ -463,7 +520,7 @@ def find_related_polymorphic_fragments(source_rids, relationship, options, conne
463520
464521 # Note: We will sort by the source table. Without using unions we can't sort on a polymorphic relationship
465522 # in any manner that makes sense
466- records = apply_request_settings_to_records ( records : records ( options ) ,
523+ records = apply_request_settings_to_records ( records : records_for_source_to_related ( options ) ,
467524 resource_klass : resource_klass ,
468525 sort_primary : true ,
469526 primary_keys : source_ids ,
0 commit comments